@@ -361,6 +361,7 @@ fn collect_items_rec<'a, 'tcx: 'a>(scx: &SharedCrateContext<'a, 'tcx>,
361
361
recursion_depth_reset = Some ( check_recursion_limit ( scx. tcx ( ) ,
362
362
instance,
363
363
recursion_depths) ) ;
364
+ check_type_length_limit ( scx. tcx ( ) , instance) ;
364
365
365
366
// Scan the MIR in order to find function calls, closures, and
366
367
// drop-glue
@@ -432,6 +433,40 @@ fn check_recursion_limit<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
432
433
( instance. def , recursion_depth)
433
434
}
434
435
436
+ fn check_type_length_limit < ' a , ' tcx > ( tcx : TyCtxt < ' a , ' tcx , ' tcx > ,
437
+ instance : Instance < ' tcx > )
438
+ {
439
+ let type_length = instance. substs . types ( ) . flat_map ( |ty| ty. walk ( ) ) . count ( ) ;
440
+ debug ! ( " => type length={}" , type_length) ;
441
+
442
+ // Rust code can easily create exponentially-long types using only a
443
+ // polynomial recursion depth. Even with the default recursion
444
+ // depth, you can easily get cases that take >2^60 steps to run,
445
+ // which means that rustc basically hangs.
446
+ //
447
+ // Bail out in these cases to avoid that bad user experience.
448
+ let type_length_limit = tcx. sess . type_length_limit . get ( ) ;
449
+ if type_length > type_length_limit {
450
+ // The instance name is already known to be too long for rustc. Use
451
+ // `{:.64}` to avoid blasting the user's terminal with thousands of
452
+ // lines of type-name.
453
+ let instance_name = instance. to_string ( ) ;
454
+ let msg = format ! ( "reached the type-length limit while instantiating `{:.64}...`" ,
455
+ instance_name) ;
456
+ let mut diag = if let Some ( node_id) = tcx. map . as_local_node_id ( instance. def ) {
457
+ tcx. sess . struct_span_fatal ( tcx. map . span ( node_id) , & msg)
458
+ } else {
459
+ tcx. sess . struct_fatal ( & msg)
460
+ } ;
461
+
462
+ diag. note ( & format ! (
463
+ "consider adding a `#![type_length_limit=\" {}\" ]` attribute to your crate" ,
464
+ type_length_limit* 2 ) ) ;
465
+ diag. emit ( ) ;
466
+ tcx. sess . abort_if_errors ( ) ;
467
+ }
468
+ }
469
+
435
470
struct MirNeighborCollector < ' a , ' tcx : ' a > {
436
471
scx : & ' a SharedCrateContext < ' a , ' tcx > ,
437
472
mir : & ' a mir:: Mir < ' tcx > ,
0 commit comments