@@ -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 , IntoDiagArg , MultiSpan ,
@@ -2709,7 +2709,8 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> {
2709
2709
pub struct HirTraitObjectVisitor < ' tcx > {
2710
2710
pub expected_region : ty:: Region < ' tcx > ,
2711
2711
pub found_region : ty:: Region < ' tcx > ,
2712
- pub lifetime_spans : FxHashSet < Span > ,
2712
+ pub primary_spans : Vec < Span > ,
2713
+ pub secondary_spans : Vec < Span > ,
2713
2714
pub pred_spans : Vec < Span > ,
2714
2715
pub tcx : TyCtxt < ' tcx > ,
2715
2716
}
@@ -2727,7 +2728,7 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> {
2727
2728
_ => false ,
2728
2729
} {
2729
2730
// We want to keep a span to the lifetime bound on the trait object.
2730
- self . lifetime_spans . insert ( lt. ident . span ) ;
2731
+ self . primary_spans . push ( lt. ident . span ) ;
2731
2732
}
2732
2733
}
2733
2734
fn visit_ty ( & mut self , t : & ' tcx hir:: Ty < ' tcx > ) {
@@ -2753,18 +2754,20 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> {
2753
2754
. filter_map ( filter_predicates ( self . found_region , |_| true ) )
2754
2755
. collect ( ) ;
2755
2756
if !bindings. is_empty ( ) {
2756
- self . lifetime_spans . insert ( ptr. span ) ;
2757
+ self . secondary_spans . push ( ptr. span ) ;
2757
2758
self . pred_spans . extend ( bindings) ;
2758
2759
}
2759
2760
}
2760
2761
}
2761
2762
}
2762
2763
// Detect when an associated item is given a lifetime restriction that the
2763
2764
// definition of that associated item couldn't meet.
2764
- hir:: TyKind :: Path ( hir:: QPath :: Resolved ( Some ( _) , path) ) => {
2765
- self . pred_spans = elaborate_predicates_of ( self . tcx , path. res . def_id ( ) )
2766
- . filter_map ( filter_predicates ( self . found_region , |_| true ) )
2767
- . collect ( ) ;
2765
+ hir:: TyKind :: Path ( hir:: QPath :: Resolved ( _, path) ) => {
2766
+ self . pred_spans . extend (
2767
+ elaborate_predicates_of ( self . tcx , path. res . def_id ( ) )
2768
+ . filter_map ( filter_predicates ( self . found_region , |_| true ) )
2769
+ . collect :: < Vec < _ > > ( ) ,
2770
+ ) ;
2768
2771
}
2769
2772
_ => { }
2770
2773
}
@@ -2774,7 +2777,8 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> {
2774
2777
let mut visitor = HirTraitObjectVisitor {
2775
2778
expected_region : sup,
2776
2779
found_region : sub,
2777
- lifetime_spans : Default :: default ( ) ,
2780
+ primary_spans : vec ! [ ] ,
2781
+ secondary_spans : vec ! [ ] ,
2778
2782
pred_spans : vec ! [ ] ,
2779
2783
tcx : self . tcx ,
2780
2784
} ;
@@ -2786,9 +2790,22 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> {
2786
2790
}
2787
2791
}
2788
2792
2789
- #[ allow( rustc:: potential_query_instability) ]
2790
- let primary_spans: Vec < Span > = visitor. lifetime_spans . into_iter ( ) . collect ( ) ;
2791
- Some ( ( primary_spans. into ( ) , visitor. pred_spans . into ( ) ) )
2793
+ visitor. primary_spans . sort ( ) ;
2794
+ let mut primary_span: MultiSpan = visitor. primary_spans . clone ( ) . into ( ) ;
2795
+ if let Some ( last) = visitor. primary_spans . iter ( ) . rev ( ) . next ( ) {
2796
+ primary_span. push_span_label (
2797
+ * last,
2798
+ format ! (
2799
+ "lifetime bound{s} not satisfied" ,
2800
+ s = pluralize!( visitor. primary_spans. len( ) )
2801
+ ) ,
2802
+ ) ;
2803
+ }
2804
+
2805
+ for span in visitor. secondary_spans {
2806
+ primary_span. push_span_label ( span, format ! ( "this requires `{sub}`" ) ) ;
2807
+ }
2808
+ Some ( ( primary_span, visitor. pred_spans . into ( ) ) )
2792
2809
}
2793
2810
2794
2811
/// Determine whether an error associated with the given span and definition
0 commit comments