@@ -221,9 +221,11 @@ use rustc_hir::lang_items::LangItem;
221221use rustc_hir:: limit:: Limit ;
222222use rustc_middle:: middle:: codegen_fn_attrs:: CodegenFnAttrFlags ;
223223use rustc_middle:: mir:: interpret:: { AllocId , ErrorHandled , GlobalAlloc , Scalar } ;
224- use rustc_middle:: mir:: mono:: { CollectionMode , InstantiationMode , MonoItem } ;
224+ use rustc_middle:: mir:: mono:: {
225+ CollectionMode , InstantiationMode , MonoItem , NormalizationErrorInMono ,
226+ } ;
225227use rustc_middle:: mir:: visit:: Visitor as MirVisitor ;
226- use rustc_middle:: mir:: { self , Location , MentionedItem , traversal} ;
228+ use rustc_middle:: mir:: { self , Body , Location , MentionedItem , traversal} ;
227229use rustc_middle:: query:: TyCtxtAt ;
228230use rustc_middle:: ty:: adjustment:: { CustomCoerceUnsized , PointerCoercion } ;
229231use rustc_middle:: ty:: layout:: ValidityRequirement ;
@@ -474,25 +476,23 @@ fn collect_items_rec<'tcx>(
474476 recursion_limit,
475477 ) ) ;
476478
477- // Plenty of code paths later assume that everything can be normalized.
478- // Check normalization here to provide better diagnostics.
479- // Normalization errors here are usually due to trait solving overflow.
480- // FIXME: I assume that there are few type errors at post-analysis stage, but not
481- // entirely sure.
482- if tcx. has_normalization_error_in_mono ( instance) {
483- let def_id = instance. def_id ( ) ;
484- let def_span = tcx. def_span ( def_id) ;
485- let def_path_str = tcx. def_path_str ( def_id) ;
486- tcx. dcx ( ) . emit_fatal ( RecursionLimit {
487- span : starting_item. span ,
488- instance,
489- def_span,
490- def_path_str,
491- } ) ;
492- }
493-
494479 rustc_data_structures:: stack:: ensure_sufficient_stack ( || {
495- let ( used, mentioned) = tcx. items_of_instance ( ( instance, mode) ) ;
480+ let Ok ( ( used, mentioned) ) = tcx. items_of_instance ( ( instance, mode) ) else {
481+ // Normalization errors here are usually due to trait solving overflow.
482+ // FIXME: I assume that there are few type errors at post-analysis stage, but not
483+ // entirely sure.
484+ // We have to emit the error outside of `items_of_instance` to access the
485+ // span of the `starting_item`.
486+ let def_id = instance. def_id ( ) ;
487+ let def_span = tcx. def_span ( def_id) ;
488+ let def_path_str = tcx. def_path_str ( def_id) ;
489+ tcx. dcx ( ) . emit_fatal ( RecursionLimit {
490+ span : starting_item. span ,
491+ instance,
492+ def_span,
493+ def_path_str,
494+ } ) ;
495+ } ;
496496 used_items. extend ( used. into_iter ( ) . copied ( ) ) ;
497497 mentioned_items. extend ( mentioned. into_iter ( ) . copied ( ) ) ;
498498 } ) ;
@@ -621,9 +621,12 @@ fn collect_items_rec<'tcx>(
621621 }
622622}
623623
624- // Check whether we can normalize the MIR body. Make it a query since decoding MIR from disk cache
625- // may be expensive.
626- fn has_normalization_error_in_mono < ' tcx > ( tcx : TyCtxt < ' tcx > , instance : Instance < ' tcx > ) -> bool {
624+ // Check whether we can normalize every type in the instantiated MIR body.
625+ fn check_normalization_error < ' tcx > (
626+ tcx : TyCtxt < ' tcx > ,
627+ instance : Instance < ' tcx > ,
628+ body : & Body < ' tcx > ,
629+ ) -> Result < ( ) , NormalizationErrorInMono > {
627630 struct NormalizationChecker < ' tcx > {
628631 tcx : TyCtxt < ' tcx > ,
629632 instance : Instance < ' tcx > ,
@@ -643,9 +646,8 @@ fn has_normalization_error_in_mono<'tcx>(tcx: TyCtxt<'tcx>, instance: Instance<'
643646 }
644647 }
645648
646- let body = tcx. instance_mir ( instance. def ) ;
647649 let mut checker = NormalizationChecker { tcx, instance } ;
648- body. visit_with ( & mut checker) . is_break ( )
650+ if body. visit_with ( & mut checker) . is_break ( ) { Err ( NormalizationErrorInMono ) } else { Ok ( ( ) ) }
649651}
650652
651653fn check_recursion_limit < ' tcx > (
@@ -1304,11 +1306,15 @@ fn collect_items_of_instance<'tcx>(
13041306 tcx : TyCtxt < ' tcx > ,
13051307 instance : Instance < ' tcx > ,
13061308 mode : CollectionMode ,
1307- ) -> ( MonoItems < ' tcx > , MonoItems < ' tcx > ) {
1309+ ) -> Result < ( MonoItems < ' tcx > , MonoItems < ' tcx > ) , NormalizationErrorInMono > {
13081310 // This item is getting monomorphized, do mono-time checks.
1311+ let body = tcx. instance_mir ( instance. def ) ;
1312+ // Plenty of code paths later assume that everything can be normalized. So we have to check
1313+ // normalization first.
1314+ // We choose to emit the error outside to provide helpful diagnostics.
1315+ check_normalization_error ( tcx, instance, body) ?;
13091316 tcx. ensure_ok ( ) . check_mono_item ( instance) ;
13101317
1311- let body = tcx. instance_mir ( instance. def ) ;
13121318 // Naively, in "used" collection mode, all functions get added to *both* `used_items` and
13131319 // `mentioned_items`. Mentioned items processing will then notice that they have already been
13141320 // visited, but at that point each mentioned item has been monomorphized, added to the
@@ -1358,19 +1364,22 @@ fn collect_items_of_instance<'tcx>(
13581364 }
13591365 }
13601366
1361- ( used_items, mentioned_items)
1367+ Ok ( ( used_items, mentioned_items) )
13621368}
13631369
13641370fn items_of_instance < ' tcx > (
13651371 tcx : TyCtxt < ' tcx > ,
13661372 ( instance, mode) : ( Instance < ' tcx > , CollectionMode ) ,
1367- ) -> ( & ' tcx [ Spanned < MonoItem < ' tcx > > ] , & ' tcx [ Spanned < MonoItem < ' tcx > > ] ) {
1368- let ( used_items, mentioned_items) = collect_items_of_instance ( tcx, instance, mode) ;
1373+ ) -> Result <
1374+ ( & ' tcx [ Spanned < MonoItem < ' tcx > > ] , & ' tcx [ Spanned < MonoItem < ' tcx > > ] ) ,
1375+ NormalizationErrorInMono ,
1376+ > {
1377+ let ( used_items, mentioned_items) = collect_items_of_instance ( tcx, instance, mode) ?;
13691378
13701379 let used_items = tcx. arena . alloc_from_iter ( used_items) ;
13711380 let mentioned_items = tcx. arena . alloc_from_iter ( mentioned_items) ;
13721381
1373- ( used_items, mentioned_items)
1382+ Ok ( ( used_items, mentioned_items) )
13741383}
13751384
13761385/// `item` must be already monomorphized.
@@ -1815,5 +1824,4 @@ pub(crate) fn collect_crate_mono_items<'tcx>(
18151824pub ( crate ) fn provide ( providers : & mut Providers ) {
18161825 providers. hooks . should_codegen_locally = should_codegen_locally;
18171826 providers. items_of_instance = items_of_instance;
1818- providers. has_normalization_error_in_mono = has_normalization_error_in_mono;
18191827}
0 commit comments