@@ -197,6 +197,7 @@ use rustc_session::config::EntryFnType;
197
197
use rustc_span:: source_map:: { dummy_spanned, respan, Span , Spanned , DUMMY_SP } ;
198
198
use smallvec:: SmallVec ;
199
199
use std:: iter;
200
+ use std:: path:: PathBuf ;
200
201
201
202
#[ derive( PartialEq ) ]
202
203
pub enum MonoItemCollectionMode {
@@ -418,27 +419,38 @@ fn record_accesses<'a, 'tcx: 'a>(
418
419
inlining_map. lock_mut ( ) . record_accesses ( caller, & accesses) ;
419
420
}
420
421
421
- // Shrinks string by keeping prefix and suffix of given sizes.
422
- fn shrink ( s : String , before : usize , after : usize ) -> String {
423
- // An iterator of all byte positions including the end of the string.
424
- let positions = || s. char_indices ( ) . map ( |( i, _) | i) . chain ( iter:: once ( s. len ( ) ) ) ;
425
-
426
- let shrunk = format ! (
427
- "{before}...{after}" ,
428
- before = & s[ ..positions( ) . nth( before) . unwrap_or( s. len( ) ) ] ,
429
- after = & s[ positions( ) . rev( ) . nth( after) . unwrap_or( 0 ) ..] ,
430
- ) ;
422
+ /// Format instance name that is already known to be too long for rustc.
423
+ /// Show only the first and last 32 characters to avoid blasting
424
+ /// the user's terminal with thousands of lines of type-name.
425
+ ///
426
+ /// If the type name is longer than before+after, it will be written to a file.
427
+ fn shrunk_instance_name (
428
+ tcx : TyCtxt < ' tcx > ,
429
+ instance : & Instance < ' tcx > ,
430
+ before : usize ,
431
+ after : usize ,
432
+ ) -> ( String , Option < PathBuf > ) {
433
+ let s = instance. to_string ( ) ;
431
434
432
435
// Only use the shrunk version if it's really shorter.
433
436
// This also avoids the case where before and after slices overlap.
434
- if shrunk. len ( ) < s. len ( ) { shrunk } else { s }
435
- }
437
+ if s. chars ( ) . nth ( before + after + 1 ) . is_some ( ) {
438
+ // An iterator of all byte positions including the end of the string.
439
+ let positions = || s. char_indices ( ) . map ( |( i, _) | i) . chain ( iter:: once ( s. len ( ) ) ) ;
440
+
441
+ let shrunk = format ! (
442
+ "{before}...{after}" ,
443
+ before = & s[ ..positions( ) . nth( before) . unwrap_or( s. len( ) ) ] ,
444
+ after = & s[ positions( ) . rev( ) . nth( after) . unwrap_or( 0 ) ..] ,
445
+ ) ;
446
+
447
+ let path = tcx. output_filenames ( LOCAL_CRATE ) . temp_path_ext ( "long-type.txt" , None ) ;
448
+ let written_to_path = std:: fs:: write ( & path, s) . ok ( ) . map ( |_| path) ;
436
449
437
- // Format instance name that is already known to be too long for rustc.
438
- // Show only the first and last 32 characters to avoid blasting
439
- // the user's terminal with thousands of lines of type-name.
440
- fn shrunk_instance_name ( instance : & Instance < ' tcx > ) -> String {
441
- shrink ( instance. to_string ( ) , 32 , 32 )
450
+ ( shrunk, written_to_path)
451
+ } else {
452
+ ( s, None )
453
+ }
442
454
}
443
455
444
456
fn check_recursion_limit < ' tcx > (
@@ -463,15 +475,16 @@ fn check_recursion_limit<'tcx>(
463
475
// more than the recursion limit is assumed to be causing an
464
476
// infinite expansion.
465
477
if !tcx. sess . recursion_limit ( ) . value_within_limit ( adjusted_recursion_depth) {
466
- let error = format ! (
467
- "reached the recursion limit while instantiating `{}`" ,
468
- shrunk_instance_name( & instance) ,
469
- ) ;
478
+ let ( shrunk, written_to_path) = shrunk_instance_name ( tcx, & instance, 32 , 32 ) ;
479
+ let error = format ! ( "reached the recursion limit while instantiating `{}`" , shrunk) ;
470
480
let mut err = tcx. sess . struct_span_fatal ( span, & error) ;
471
481
err. span_note (
472
482
tcx. def_span ( def_id) ,
473
483
& format ! ( "`{}` defined here" , tcx. def_path_str( def_id) ) ,
474
484
) ;
485
+ if let Some ( path) = written_to_path {
486
+ err. note ( & format ! ( "the full type name has been written to '{}'" , path. display( ) ) ) ;
487
+ }
475
488
err. emit ( ) ;
476
489
FatalError . raise ( ) ;
477
490
}
@@ -500,12 +513,13 @@ fn check_type_length_limit<'tcx>(tcx: TyCtxt<'tcx>, instance: Instance<'tcx>) {
500
513
//
501
514
// Bail out in these cases to avoid that bad user experience.
502
515
if !tcx. sess . type_length_limit ( ) . value_within_limit ( type_length) {
503
- let msg = format ! (
504
- "reached the type-length limit while instantiating `{}`" ,
505
- shrunk_instance_name( & instance) ,
506
- ) ;
516
+ let ( shrunk, written_to_path) = shrunk_instance_name ( tcx, & instance, 32 , 32 ) ;
517
+ let msg = format ! ( "reached the type-length limit while instantiating `{}`" , shrunk) ;
507
518
let mut diag = tcx. sess . struct_span_fatal ( tcx. def_span ( instance. def_id ( ) ) , & msg) ;
508
- diag. note ( & format ! (
519
+ if let Some ( path) = written_to_path {
520
+ diag. note ( & format ! ( "the full type name has been written to '{}'" , path. display( ) ) ) ;
521
+ }
522
+ diag. help ( & format ! (
509
523
"consider adding a `#![type_length_limit=\" {}\" ]` attribute to your crate" ,
510
524
type_length
511
525
) ) ;
0 commit comments