@@ -198,6 +198,8 @@ use monomorphize::item::{MonoItemExt, DefPathBasedNames, InstantiationMode};
198
198
use rustc_data_structures:: bit_set:: GrowableBitSet ;
199
199
use rustc_data_structures:: sync:: { MTRef , MTLock , ParallelIterator , par_iter} ;
200
200
201
+ use std:: iter;
202
+
201
203
#[ derive( PartialEq , Eq , Hash , Clone , Copy , Debug ) ]
202
204
pub enum MonoItemCollectionMode {
203
205
Eager ,
@@ -476,21 +478,33 @@ fn check_type_length_limit<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
476
478
// Bail out in these cases to avoid that bad user experience.
477
479
let type_length_limit = * tcx. sess . type_length_limit . get ( ) ;
478
480
if type_length > type_length_limit {
479
- // The instance name is already known to be too long for rustc. Use
480
- // `{:.64}` to avoid blasting the user's terminal with thousands of
481
- // lines of type-name.
482
- let instance_name = instance. to_string ( ) ;
483
- let msg = format ! ( "reached the type-length limit while instantiating `{:.64}...`" ,
484
- instance_name) ;
485
- let mut diag = if let Some ( node_id) = tcx. hir ( ) . as_local_node_id ( instance. def_id ( ) ) {
486
- tcx. sess . struct_span_fatal ( tcx. hir ( ) . span ( node_id) , & msg)
487
- } else {
488
- tcx. sess . struct_fatal ( & msg)
481
+ // The instance name is already known to be too long for rustc.
482
+ // Show only the first and last 32 characters to avoid blasting
483
+ // the user's terminal with thousands of lines of type-name.
484
+ let shrink = |s : String , before : usize , after : usize | {
485
+ // An iterator of all byte positions including the end of the string.
486
+ let positions = || s. char_indices ( ) . map ( |( i, _) | i) . chain ( iter:: once ( s. len ( ) ) ) ;
487
+
488
+ let shrunk = format ! (
489
+ "{before}...{after}" ,
490
+ before = & s[ ..positions( ) . nth( before) . unwrap_or( s. len( ) ) ] ,
491
+ after = & s[ positions( ) . rev( ) . nth( after) . unwrap_or( 0 ) ..] ,
492
+ ) ;
493
+
494
+ // Only use the shrunk version if it's really shorter.
495
+ // This also avoids the case where before and after slices overlap.
496
+ if shrunk. len ( ) < s. len ( ) {
497
+ shrunk
498
+ } else {
499
+ s
500
+ }
489
501
} ;
490
-
502
+ let msg = format ! ( "reached the type-length limit while instantiating `{}`" ,
503
+ shrink( instance. to_string( ) , 32 , 32 ) ) ;
504
+ let mut diag = tcx. sess . struct_span_fatal ( tcx. def_span ( instance. def_id ( ) ) , & msg) ;
491
505
diag. note ( & format ! (
492
506
"consider adding a `#![type_length_limit=\" {}\" ]` attribute to your crate" ,
493
- type_length_limit * 2 ) ) ;
507
+ type_length ) ) ;
494
508
diag. emit ( ) ;
495
509
tcx. sess . abort_if_errors ( ) ;
496
510
}
0 commit comments