@@ -19,6 +19,9 @@ use rustc_hir::intravisit::Visitor;
1919use rustc_hir:: GenericParam ;
2020use rustc_hir:: Item ;
2121use rustc_hir:: Node ;
22+ use rustc_middle:: mir:: interpret:: {
23+ ConstDedupResult , ConstErrorEmitted , ErrorHandled , SilentError ,
24+ } ;
2225use rustc_middle:: thir:: abstract_const:: NotConstEvaluatable ;
2326use rustc_middle:: ty:: error:: ExpectedFound ;
2427use rustc_middle:: ty:: fast_reject:: { self , SimplifyParams , StripReferences } ;
@@ -238,6 +241,7 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> {
238241 error : & SelectionError < ' tcx > ,
239242 fallback_has_occurred : bool ,
240243 ) {
244+ debug ! ( "report_selection_error(error: {:?})" , error) ;
241245 let tcx = self . tcx ;
242246 let mut span = obligation. cause . span ;
243247
@@ -799,7 +803,94 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> {
799803 bug ! (
800804 "MentionsInfer should have been handled in `traits/fulfill.rs` or `traits/select/mod.rs`"
801805 )
802- ConstEvalFailure ( ErrorHandled :: Silent ) => {
806+ }
807+ SelectionError :: NotConstEvaluatable ( NotConstEvaluatable :: Silent ( id) ) => {
808+ // try to report a ConstEvalErr which gives better diagnostics by providing
809+ // information about why the constant couldn't be evaluated.
810+ let const_dedup_map = tcx. dedup_const_map . lock ( ) ;
811+ debug ! ( "const_dedup_map: {:#?}" , & const_dedup_map) ;
812+ debug ! ( ?id) ;
813+
814+ // FIXME This only reports errors stored as `ConstDedupResult::Selection`
815+ // but we should also report cached errors with other Reveal variants
816+ // here. See e.g. test `ui/const-generics/generic_const_exprs/issue-62504.rs`
817+ // which fails to report the `TooGeneric` error because it was stored
818+ // with `Reveal::All`.
819+ if !const_dedup_map. error_reported_map . borrow ( ) . contains_key ( & id) {
820+ if let Some ( ConstDedupResult :: Selection ( (
821+ Err ( SilentError :: ConstErr ( err) ) ,
822+ sp,
823+ ) ) ) = const_dedup_map. alloc_map . borrow ( ) . get ( & id)
824+ {
825+ let def = id. instance . def . with_opt_param ( ) ;
826+ let is_static = tcx. is_static ( def. did ) ;
827+
828+ let err_emitted = tcx. report_const_alloc_error (
829+ & const_dedup_map,
830+ id,
831+ obligation. param_env ,
832+ err,
833+ is_static,
834+ def,
835+ * sp,
836+ ) ;
837+
838+ match err_emitted {
839+ ConstErrorEmitted :: NotEmitted ( err) => {
840+ if let ErrorHandled :: TooGeneric = err {
841+ let selection_err = SelectionError :: NotConstEvaluatable (
842+ NotConstEvaluatable :: MentionsParam ,
843+ ) ;
844+
845+ self . report_selection_error (
846+ obligation. clone ( ) ,
847+ root_obligation,
848+ & selection_err,
849+ fallback_has_occurred,
850+ ) ;
851+ }
852+ }
853+ _ => { }
854+ }
855+ } else {
856+ if let Some ( ConstDedupResult :: Selection ( (
857+ Err ( SilentError :: ConstErr ( err) ) ,
858+ sp,
859+ ) ) ) = const_dedup_map. const_val_map . borrow ( ) . get ( & id)
860+ {
861+ let def = id. instance . def . with_opt_param ( ) ;
862+ let is_static = tcx. is_static ( def. did ) ;
863+
864+ let err_emitted = tcx. report_const_alloc_error (
865+ & const_dedup_map,
866+ id,
867+ obligation. param_env ,
868+ err,
869+ is_static,
870+ def,
871+ * sp,
872+ ) ;
873+
874+ match err_emitted {
875+ ConstErrorEmitted :: NotEmitted ( err) => {
876+ if let ErrorHandled :: TooGeneric = err {
877+ let selection_err = SelectionError :: NotConstEvaluatable (
878+ NotConstEvaluatable :: MentionsParam ,
879+ ) ;
880+
881+ self . report_selection_error (
882+ obligation. clone ( ) ,
883+ root_obligation,
884+ & selection_err,
885+ fallback_has_occurred,
886+ ) ;
887+ }
888+ }
889+ _ => { }
890+ }
891+ }
892+ }
893+ }
803894 tcx. sess . struct_span_err ( span, "failed to evaluate the given constant" )
804895 }
805896 SelectionError :: NotConstEvaluatable ( NotConstEvaluatable :: MentionsParam ) => {
0 commit comments