@@ -9,6 +9,7 @@ use crate::FnCtxt;
99use rustc_ast:: ast:: Mutability ;
1010use rustc_attr:: parse_confusables;
1111use rustc_data_structures:: fx:: { FxIndexMap , FxIndexSet } ;
12+ use rustc_data_structures:: sorted_map:: SortedMap ;
1213use rustc_data_structures:: unord:: UnordSet ;
1314use rustc_errors:: {
1415 codes:: * , pluralize, struct_span_code_err, Applicability , Diagnostic , DiagnosticBuilder ,
@@ -458,22 +459,13 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
458459 ) ;
459460 }
460461
461- let ty_span = match rcvr_ty. kind ( ) {
462+ let mut ty_span = match rcvr_ty. kind ( ) {
462463 ty:: Param ( param_type) => {
463464 Some ( param_type. span_from_generics ( self . tcx , self . body_id . to_def_id ( ) ) )
464465 }
465466 ty:: Adt ( def, _) if def. did ( ) . is_local ( ) => Some ( tcx. def_span ( def. did ( ) ) ) ,
466467 _ => None ,
467468 } ;
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- }
477469
478470 if let SelfSource :: MethodCall ( rcvr_expr) = source {
479471 self . suggest_fn_call ( & mut err, rcvr_expr, rcvr_ty, |output_ty| {
@@ -546,7 +538,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
546538 ) ;
547539 }
548540
549- let mut bound_spans = vec ! [ ] ;
541+ let mut bound_spans: SortedMap < Span , Vec < String > > = Default :: default ( ) ;
550542 let mut restrict_type_params = false ;
551543 let mut unsatisfied_bounds = false ;
552544 if item_name. name == sym:: count && self . is_slice_ty ( rcvr_ty, span) {
@@ -641,28 +633,32 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
641633 false
642634 } ;
643635 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 } ) ;
648637 match & self_ty. kind ( ) {
649638 // 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+ }
651642 // Point at the trait object that couldn't satisfy the bound.
652643 ty:: Dynamic ( preds, _, _) => {
653644 for pred in preds. iter ( ) {
654645 match pred. skip_binder ( ) {
655646 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 ( ) ) ;
657650 }
658651 ty:: ExistentialPredicate :: Projection ( _)
659652 | ty:: ExistentialPredicate :: AutoTrait ( _) => { }
660653 }
661654 }
662655 }
663656 // 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+ }
666662 _ => { }
667663 }
668664 } ;
@@ -1169,11 +1165,40 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
11691165
11701166 self . suggest_unwrapping_inner_self ( & mut err, source, rcvr_ty, item_name) ;
11711167
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+ } ;
11751191 err. span_label ( span, msg) ;
11761192 }
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+ }
11771202
11781203 if rcvr_ty. is_numeric ( ) && rcvr_ty. is_fresh ( ) || restrict_type_params {
11791204 } else {
0 commit comments