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