@@ -59,7 +59,7 @@ use crate::traits::{
59
59
PredicateObligation ,
60
60
} ;
61
61
62
- use rustc_data_structures:: fx:: { FxHashSet , FxIndexMap , FxIndexSet } ;
62
+ use rustc_data_structures:: fx:: { FxIndexMap , FxIndexSet } ;
63
63
use rustc_errors:: {
64
64
codes:: * , pluralize, struct_span_code_err, Applicability , Diag , DiagCtxt , DiagStyledString ,
65
65
ErrorGuaranteed , IntoDiagnosticArg , MultiSpan ,
@@ -2698,7 +2698,8 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> {
2698
2698
pub struct HirTraitObjectVisitor < ' tcx > {
2699
2699
pub expected_region : ty:: Region < ' tcx > ,
2700
2700
pub found_region : ty:: Region < ' tcx > ,
2701
- pub lifetime_spans : FxHashSet < Span > ,
2701
+ pub primary_spans : Vec < Span > ,
2702
+ pub secondary_spans : Vec < Span > ,
2702
2703
pub pred_spans : Vec < Span > ,
2703
2704
pub tcx : TyCtxt < ' tcx > ,
2704
2705
}
@@ -2716,7 +2717,7 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> {
2716
2717
_ => false ,
2717
2718
} {
2718
2719
// 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 ) ;
2720
2721
}
2721
2722
}
2722
2723
fn visit_ty ( & mut self , t : & ' tcx hir:: Ty < ' tcx > ) {
@@ -2742,18 +2743,20 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> {
2742
2743
. filter_map ( filter_predicates ( self . found_region , |_| true ) )
2743
2744
. collect ( ) ;
2744
2745
if !bindings. is_empty ( ) {
2745
- self . lifetime_spans . insert ( ptr. span ) ;
2746
+ self . secondary_spans . push ( ptr. span ) ;
2746
2747
self . pred_spans . extend ( bindings) ;
2747
2748
}
2748
2749
}
2749
2750
}
2750
2751
}
2751
2752
// Detect when an associated item is given a lifetime restriction that the
2752
2753
// 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
+ ) ;
2757
2760
}
2758
2761
_ => { }
2759
2762
}
@@ -2763,7 +2766,8 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> {
2763
2766
let mut visitor = HirTraitObjectVisitor {
2764
2767
expected_region : sup,
2765
2768
found_region : sub,
2766
- lifetime_spans : Default :: default ( ) ,
2769
+ primary_spans : vec ! [ ] ,
2770
+ secondary_spans : vec ! [ ] ,
2767
2771
pred_spans : vec ! [ ] ,
2768
2772
tcx : self . tcx ,
2769
2773
} ;
@@ -2775,9 +2779,22 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> {
2775
2779
}
2776
2780
}
2777
2781
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 ( ) ) )
2781
2798
}
2782
2799
2783
2800
/// Determine whether an error associated with the given span and definition
0 commit comments