@@ -9,6 +9,7 @@ use crate::FnCtxt;
9
9
use rustc_ast:: ast:: Mutability ;
10
10
use rustc_attr:: parse_confusables;
11
11
use rustc_data_structures:: fx:: { FxIndexMap , FxIndexSet } ;
12
+ use rustc_data_structures:: sorted_map:: SortedMap ;
12
13
use rustc_data_structures:: unord:: UnordSet ;
13
14
use rustc_errors:: {
14
15
codes:: * , pluralize, struct_span_code_err, Applicability , Diagnostic , DiagnosticBuilder ,
@@ -458,22 +459,13 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
458
459
) ;
459
460
}
460
461
461
- let ty_span = match rcvr_ty. kind ( ) {
462
+ let mut ty_span = match rcvr_ty. kind ( ) {
462
463
ty:: Param ( param_type) => {
463
464
Some ( param_type. span_from_generics ( self . tcx , self . body_id . to_def_id ( ) ) )
464
465
}
465
466
ty:: Adt ( def, _) if def. did ( ) . is_local ( ) => Some ( tcx. def_span ( def. did ( ) ) ) ,
466
467
_ => None ,
467
468
} ;
468
- if let Some ( span) = ty_span {
469
- err. span_label (
470
- span,
471
- format ! (
472
- "{item_kind} `{item_name}` not found for this {}" ,
473
- rcvr_ty. prefix_string( self . tcx)
474
- ) ,
475
- ) ;
476
- }
477
469
478
470
if let SelfSource :: MethodCall ( rcvr_expr) = source {
479
471
self . suggest_fn_call ( & mut err, rcvr_expr, rcvr_ty, |output_ty| {
@@ -546,7 +538,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
546
538
) ;
547
539
}
548
540
549
- let mut bound_spans = vec ! [ ] ;
541
+ let mut bound_spans: SortedMap < Span , Vec < String > > = Default :: default ( ) ;
550
542
let mut restrict_type_params = false ;
551
543
let mut unsatisfied_bounds = false ;
552
544
if item_name. name == sym:: count && self . is_slice_ty ( rcvr_ty, span) {
@@ -641,28 +633,32 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
641
633
false
642
634
} ;
643
635
let mut bound_span_label = |self_ty : Ty < ' _ > , obligation : & str , quiet : & str | {
644
- let msg = format ! (
645
- "doesn't satisfy `{}`" ,
646
- if obligation. len( ) > 50 { quiet } else { obligation }
647
- ) ;
636
+ let msg = format ! ( "`{}`" , if obligation. len( ) > 50 { quiet } else { obligation } ) ;
648
637
match & self_ty. kind ( ) {
649
638
// Point at the type that couldn't satisfy the bound.
650
- ty:: Adt ( def, _) => bound_spans. push ( ( self . tcx . def_span ( def. did ( ) ) , msg) ) ,
639
+ ty:: Adt ( def, _) => {
640
+ bound_spans. get_mut_or_insert_default ( tcx. def_span ( def. did ( ) ) ) . push ( msg)
641
+ }
651
642
// Point at the trait object that couldn't satisfy the bound.
652
643
ty:: Dynamic ( preds, _, _) => {
653
644
for pred in preds. iter ( ) {
654
645
match pred. skip_binder ( ) {
655
646
ty:: ExistentialPredicate :: Trait ( tr) => {
656
- bound_spans. push ( ( self . tcx . def_span ( tr. def_id ) , msg. clone ( ) ) )
647
+ bound_spans
648
+ . get_mut_or_insert_default ( tcx. def_span ( tr. def_id ) )
649
+ . push ( msg. clone ( ) ) ;
657
650
}
658
651
ty:: ExistentialPredicate :: Projection ( _)
659
652
| ty:: ExistentialPredicate :: AutoTrait ( _) => { }
660
653
}
661
654
}
662
655
}
663
656
// Point at the closure that couldn't satisfy the bound.
664
- ty:: Closure ( def_id, _) => bound_spans
665
- . push ( ( tcx. def_span ( * def_id) , format ! ( "doesn't satisfy `{quiet}`" ) ) ) ,
657
+ ty:: Closure ( def_id, _) => {
658
+ bound_spans
659
+ . get_mut_or_insert_default ( tcx. def_span ( * def_id) )
660
+ . push ( format ! ( "`{quiet}`" ) ) ;
661
+ }
666
662
_ => { }
667
663
}
668
664
} ;
@@ -1169,11 +1165,40 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
1169
1165
1170
1166
self . suggest_unwrapping_inner_self ( & mut err, source, rcvr_ty, item_name) ;
1171
1167
1172
- bound_spans. sort ( ) ;
1173
- bound_spans. dedup ( ) ;
1174
- for ( span, msg) in bound_spans. into_iter ( ) {
1168
+ for ( span, mut bounds) in bound_spans {
1169
+ if !tcx. sess . source_map ( ) . is_span_accessible ( span) {
1170
+ continue ;
1171
+ }
1172
+ bounds. sort ( ) ;
1173
+ bounds. dedup ( ) ;
1174
+ let pre = if Some ( span) == ty_span {
1175
+ ty_span. take ( ) ;
1176
+ format ! (
1177
+ "{item_kind} `{item_name}` not found for this {} because it " ,
1178
+ rcvr_ty. prefix_string( self . tcx)
1179
+ )
1180
+ } else {
1181
+ String :: new ( )
1182
+ } ;
1183
+ let msg = match & bounds[ ..] {
1184
+ [ bound] => format ! ( "{pre}doesn't satisfy {bound}" ) ,
1185
+ bounds if bounds. len ( ) > 4 => format ! ( "doesn't satisfy {} bounds" , bounds. len( ) ) ,
1186
+ [ bounds @ .., last] => {
1187
+ format ! ( "{pre}doesn't satisfy {} or {last}" , bounds. join( ", " ) )
1188
+ }
1189
+ [ ] => unreachable ! ( ) ,
1190
+ } ;
1175
1191
err. span_label ( span, msg) ;
1176
1192
}
1193
+ if let Some ( span) = ty_span {
1194
+ err. span_label (
1195
+ span,
1196
+ format ! (
1197
+ "{item_kind} `{item_name}` not found for this {}" ,
1198
+ rcvr_ty. prefix_string( self . tcx)
1199
+ ) ,
1200
+ ) ;
1201
+ }
1177
1202
1178
1203
if rcvr_ty. is_numeric ( ) && rcvr_ty. is_fresh ( ) || restrict_type_params {
1179
1204
} else {
0 commit comments