@@ -19,6 +19,9 @@ use rustc_hir::intravisit::Visitor;
19
19
use rustc_hir:: GenericParam ;
20
20
use rustc_hir:: Item ;
21
21
use rustc_hir:: Node ;
22
+ use rustc_middle:: mir:: interpret:: {
23
+ ConstDedupResult , ConstErrorEmitted , ErrorHandled , SilentError ,
24
+ } ;
22
25
use rustc_middle:: thir:: abstract_const:: NotConstEvaluatable ;
23
26
use rustc_middle:: ty:: error:: ExpectedFound ;
24
27
use rustc_middle:: ty:: fast_reject:: { self , SimplifyParams , StripReferences } ;
@@ -238,6 +241,7 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> {
238
241
error : & SelectionError < ' tcx > ,
239
242
fallback_has_occurred : bool ,
240
243
) {
244
+ debug ! ( "report_selection_error(error: {:?})" , error) ;
241
245
let tcx = self . tcx ;
242
246
let mut span = obligation. cause . span ;
243
247
@@ -799,7 +803,94 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> {
799
803
bug ! (
800
804
"MentionsInfer should have been handled in `traits/fulfill.rs` or `traits/select/mod.rs`"
801
805
)
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
+ }
803
894
tcx. sess . struct_span_err ( span, "failed to evaluate the given constant" )
804
895
}
805
896
SelectionError :: NotConstEvaluatable ( NotConstEvaluatable :: MentionsParam ) => {
0 commit comments