@@ -357,6 +357,7 @@ fn collect_items_root<'tcx>(
357357 starting_item : Spanned < MonoItem < ' tcx > > ,
358358 state : & SharedState < ' tcx > ,
359359 recursion_limit : Limit ,
360+ type_length_limit : Limit ,
360361) {
361362 if !state. visited . lock ( ) . insert ( starting_item. node ) {
362363 // We've been here already, no need to search again.
@@ -370,6 +371,7 @@ fn collect_items_root<'tcx>(
370371 & mut recursion_depths,
371372 recursion_limit,
372373 CollectionMode :: UsedItems ,
374+ type_length_limit,
373375 ) ;
374376}
375377
@@ -378,14 +380,18 @@ fn collect_items_root<'tcx>(
378380///
379381/// `mode` determined whether we are scanning for [used items][CollectionMode::UsedItems]
380382/// or [mentioned items][CollectionMode::MentionedItems].
381- #[ instrument( skip( tcx, state, recursion_depths, recursion_limit) , level = "debug" ) ]
383+ #[ instrument(
384+ skip( tcx, state, recursion_depths, recursion_limit, type_length_limit) ,
385+ level = "debug"
386+ ) ]
382387fn collect_items_rec < ' tcx > (
383388 tcx : TyCtxt < ' tcx > ,
384389 starting_item : Spanned < MonoItem < ' tcx > > ,
385390 state : & SharedState < ' tcx > ,
386391 recursion_depths : & mut DefIdMap < usize > ,
387392 recursion_limit : Limit ,
388393 mode : CollectionMode ,
394+ type_length_limit : Limit ,
389395) {
390396 let mut used_items = MonoItems :: new ( ) ;
391397 let mut mentioned_items = MonoItems :: new ( ) ;
@@ -463,13 +469,14 @@ fn collect_items_rec<'tcx>(
463469 // Sanity check whether this ended up being collected accidentally
464470 debug_assert ! ( tcx. should_codegen_locally( instance) ) ;
465471
466- // Keep track of the monomorphization recursion depth
472+ // Check for recursive monomorphization before collecting uses
467473 recursion_depth_reset = Some ( check_recursion_limit (
468474 tcx,
469475 instance,
470476 starting_item. span ,
471477 recursion_depths,
472478 recursion_limit,
479+ type_length_limit,
473480 ) ) ;
474481
475482 rustc_data_structures:: stack:: ensure_sufficient_stack ( || {
@@ -595,6 +602,7 @@ fn collect_items_rec<'tcx>(
595602 recursion_depths,
596603 recursion_limit,
597604 CollectionMode :: UsedItems ,
605+ type_length_limit,
598606 ) ;
599607 }
600608 }
@@ -609,6 +617,7 @@ fn collect_items_rec<'tcx>(
609617 recursion_depths,
610618 recursion_limit,
611619 CollectionMode :: MentionedItems ,
620+ type_length_limit,
612621 ) ;
613622 }
614623
@@ -652,6 +661,7 @@ fn check_recursion_limit<'tcx>(
652661 span : Span ,
653662 recursion_depths : & mut DefIdMap < usize > ,
654663 recursion_limit : Limit ,
664+ type_length_limit : Limit ,
655665) -> ( DefId , usize ) {
656666 let def_id = instance. def_id ( ) ;
657667 let recursion_depth = recursion_depths. get ( & def_id) . cloned ( ) . unwrap_or ( 0 ) ;
@@ -665,17 +675,17 @@ fn check_recursion_limit<'tcx>(
665675 recursion_depth
666676 } ;
667677
668- // Rust code can create exponentially-long types using only a
669- // polynomial recursion depth. Start checking the type length before
670- // the depth limit is reached, to avoid hanging on enormous instance
671- // arguments.
672- let type_length_check_depth = ( recursion_limit / 8 ) . 0 . max ( 4 ) ;
678+ // Recursive monomorphization can grow instance args exponentially with polynomial
679+ // recursion depth. Start checking type lengths around `ilog2(type_length_limit.0)`
680+ // to avoid hanging on enormous instance arguments.
681+ let type_length_check_depth = type_length_limit. 0 . checked_ilog2 ( ) . unwrap_or ( 0 ) . max ( 4 ) as usize ;
673682 let recursive_type_growth_limit_reached = recursion_depth >= type_length_check_depth
674- && !tcx . type_length_limit ( ) . value_within_limit ( type_length ( instance. args ) ) ;
683+ && !type_length_limit. value_within_limit ( type_length ( instance. args ) ) ;
675684
676- // Code that needs to instantiate the same function recursively
677- // more than the recursion limit, or with type arguments that exceed the
678- // type length limit, is assumed to be causing an infinite expansion.
685+ // Code that needs to instantiate the same function recursively more
686+ // than the recursion limit is assumed to be causing an infinite
687+ // expansion. Bail out earlier if recursive instantiations have already
688+ // produced instance args exceeding the type length limit.
679689 if !recursion_limit. value_within_limit ( adjusted_recursion_depth)
680690 || recursive_type_growth_limit_reached
681691 {
@@ -1848,9 +1858,17 @@ pub(crate) fn collect_crate_mono_items<'tcx>(
18481858 } ;
18491859 let recursion_limit = tcx. recursion_limit ( ) ;
18501860
1861+ let type_length_limit = tcx. type_length_limit ( ) ;
1862+
18511863 tcx. sess . time ( "monomorphization_collector_graph_walk" , || {
18521864 par_for_each_in ( roots, |root| {
1853- collect_items_root ( tcx, dummy_spanned ( * root) , & state, recursion_limit) ;
1865+ collect_items_root (
1866+ tcx,
1867+ dummy_spanned ( * root) ,
1868+ & state,
1869+ recursion_limit,
1870+ type_length_limit,
1871+ ) ;
18541872 } ) ;
18551873 } ) ;
18561874
0 commit comments