@@ -461,22 +461,24 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
461461 return err. emit ( ) ;
462462 }
463463
464- let mut bound_spans = Vec :: new ( ) ;
464+ let mut bound_spans: FxHashMap < Span , Vec < String > > = Default :: default ( ) ;
465465
466466 let mut bound_span_label = |self_ty : Ty < ' _ > , obligation : & str , quiet : & str | {
467- let msg = format ! (
468- "doesn't satisfy `{}`" ,
469- if obligation. len( ) > 50 { quiet } else { obligation }
470- ) ;
467+ let msg = format ! ( "`{}`" , if obligation. len( ) > 50 { quiet } else { obligation } ) ;
471468 match & self_ty. kind ( ) {
472469 // Point at the type that couldn't satisfy the bound.
473- ty:: Adt ( def, _) => bound_spans. push ( ( tcx. def_span ( def. did ( ) ) , msg) ) ,
470+ ty:: Adt ( def, _) => {
471+ bound_spans. entry ( tcx. def_span ( def. did ( ) ) ) . or_default ( ) . push ( msg)
472+ }
474473 // Point at the trait object that couldn't satisfy the bound.
475474 ty:: Dynamic ( preds, _, _) => {
476475 for pred in preds. iter ( ) {
477476 match pred. skip_binder ( ) {
478477 ty:: ExistentialPredicate :: Trait ( tr) => {
479- bound_spans. push ( ( tcx. def_span ( tr. def_id ) , msg. clone ( ) ) )
478+ bound_spans
479+ . entry ( tcx. def_span ( tr. def_id ) )
480+ . or_default ( )
481+ . push ( msg. clone ( ) ) ;
480482 }
481483 ty:: ExistentialPredicate :: Projection ( _)
482484 | ty:: ExistentialPredicate :: AutoTrait ( _) => { }
@@ -485,7 +487,10 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
485487 }
486488 // Point at the closure that couldn't satisfy the bound.
487489 ty:: Closure ( def_id, _) => {
488- bound_spans. push ( ( tcx. def_span ( * def_id) , format ! ( "doesn't satisfy `{quiet}`" ) ) )
490+ bound_spans
491+ . entry ( tcx. def_span ( * def_id) )
492+ . or_default ( )
493+ . push ( format ! ( "`{quiet}`" ) ) ;
489494 }
490495 _ => { }
491496 }
@@ -554,12 +559,24 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
554559 format ! ( "associated type cannot be referenced on `{self_ty}` due to unsatisfied trait bounds" )
555560 ) ;
556561
557- bound_spans. sort ( ) ;
558- bound_spans. dedup ( ) ;
559- for ( span, msg) in bound_spans {
562+ let mut bound_spans: Vec < ( Span , Vec < String > ) > = bound_spans
563+ . into_iter ( )
564+ . map ( |( span, mut bounds) | {
565+ bounds. sort ( ) ;
566+ bounds. dedup ( ) ;
567+ ( span, bounds)
568+ } )
569+ . collect ( ) ;
570+ bound_spans. sort_by_key ( |( span, _) | * span) ;
571+ for ( span, bounds) in bound_spans {
560572 if !tcx. sess . source_map ( ) . is_span_accessible ( span) {
561573 continue ;
562574 }
575+ let msg = match & bounds[ ..] {
576+ [ bound] => format ! ( "doesn't satisfy {bound}" ) ,
577+ [ bounds @ .., last] => format ! ( "doesn't satisfy {} or {last}" , bounds. join( ", " ) ) ,
578+ [ ] => unreachable ! ( ) ,
579+ } ;
563580 err. span_label ( span, msg) ;
564581 }
565582 add_def_label ( & mut err) ;
0 commit comments