@@ -59,7 +59,7 @@ use crate::traits::{
5959 PredicateObligation ,
6060} ;
6161
62- use rustc_data_structures:: fx:: { FxHashSet , FxIndexMap , FxIndexSet } ;
62+ use rustc_data_structures:: fx:: { FxIndexMap , FxIndexSet } ;
6363use rustc_errors:: {
6464 codes:: * , pluralize, struct_span_code_err, Applicability , Diag , DiagCtxt , DiagStyledString ,
6565 ErrorGuaranteed , IntoDiagnosticArg , MultiSpan ,
@@ -2698,7 +2698,8 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> {
26982698 pub struct HirTraitObjectVisitor < ' tcx > {
26992699 pub expected_region : ty:: Region < ' tcx > ,
27002700 pub found_region : ty:: Region < ' tcx > ,
2701- pub lifetime_spans : FxHashSet < Span > ,
2701+ pub primary_spans : Vec < Span > ,
2702+ pub secondary_spans : Vec < Span > ,
27022703 pub pred_spans : Vec < Span > ,
27032704 pub tcx : TyCtxt < ' tcx > ,
27042705 }
@@ -2716,7 +2717,7 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> {
27162717 _ => false ,
27172718 } {
27182719 // We want to keep a span to the lifetime bound on the trait object.
2719- self . lifetime_spans . insert ( lt. ident . span ) ;
2720+ self . primary_spans . push ( lt. ident . span ) ;
27202721 }
27212722 }
27222723 fn visit_ty ( & mut self , t : & ' tcx hir:: Ty < ' tcx > ) {
@@ -2742,18 +2743,20 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> {
27422743 . filter_map ( filter_predicates ( self . found_region , |_| true ) )
27432744 . collect ( ) ;
27442745 if !bindings. is_empty ( ) {
2745- self . lifetime_spans . insert ( ptr. span ) ;
2746+ self . secondary_spans . push ( ptr. span ) ;
27462747 self . pred_spans . extend ( bindings) ;
27472748 }
27482749 }
27492750 }
27502751 }
27512752 // Detect when an associated item is given a lifetime restriction that the
27522753 // definition of that associated item couldn't meet.
2753- hir:: TyKind :: Path ( hir:: QPath :: Resolved ( Some ( _) , path) ) => {
2754- self . pred_spans = elaborate_predicates_of ( self . tcx , path. res . def_id ( ) )
2755- . filter_map ( filter_predicates ( self . found_region , |_| true ) )
2756- . collect ( ) ;
2754+ hir:: TyKind :: Path ( hir:: QPath :: Resolved ( _, path) ) => {
2755+ self . pred_spans . extend (
2756+ elaborate_predicates_of ( self . tcx , path. res . def_id ( ) )
2757+ . filter_map ( filter_predicates ( self . found_region , |_| true ) )
2758+ . collect :: < Vec < _ > > ( ) ,
2759+ ) ;
27572760 }
27582761 _ => { }
27592762 }
@@ -2763,7 +2766,8 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> {
27632766 let mut visitor = HirTraitObjectVisitor {
27642767 expected_region : sup,
27652768 found_region : sub,
2766- lifetime_spans : Default :: default ( ) ,
2769+ primary_spans : vec ! [ ] ,
2770+ secondary_spans : vec ! [ ] ,
27672771 pred_spans : vec ! [ ] ,
27682772 tcx : self . tcx ,
27692773 } ;
@@ -2775,9 +2779,22 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> {
27752779 }
27762780 }
27772781
2778- #[ allow( rustc:: potential_query_instability) ]
2779- let primary_spans: Vec < Span > = visitor. lifetime_spans . into_iter ( ) . collect ( ) ;
2780- Some ( ( primary_spans. into ( ) , visitor. pred_spans . into ( ) ) )
2782+ visitor. primary_spans . sort ( ) ;
2783+ let mut primary_span: MultiSpan = visitor. primary_spans . clone ( ) . into ( ) ;
2784+ if let Some ( last) = visitor. primary_spans . iter ( ) . rev ( ) . next ( ) {
2785+ primary_span. push_span_label (
2786+ * last,
2787+ format ! (
2788+ "lifetime bound{s} not satisfied" ,
2789+ s = pluralize!( visitor. primary_spans. len( ) )
2790+ ) ,
2791+ ) ;
2792+ }
2793+
2794+ for span in visitor. secondary_spans {
2795+ primary_span. push_span_label ( span, format ! ( "this requires `{sub}`" ) ) ;
2796+ }
2797+ Some ( ( primary_span, visitor. pred_spans . into ( ) ) )
27812798 }
27822799
27832800 /// Determine whether an error associated with the given span and definition
0 commit comments