@@ -2727,38 +2727,119 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> {
2727
2727
return None ;
2728
2728
} ;
2729
2729
/// Collect all `hir::Ty<'_>` `Span`s for trait objects with the sup lifetime.
2730
- pub struct HirTraitObjectVisitor < ' tcx > (
2731
- pub Vec < & ' tcx hir:: PolyTraitRef < ' tcx > > ,
2732
- pub ty:: Region < ' tcx > ,
2733
- pub FxHashSet < Span > ,
2734
- ) ;
2730
+ pub struct HirTraitObjectVisitor < ' tcx > {
2731
+ pub expected_region : ty:: Region < ' tcx > ,
2732
+ pub found_region : ty:: Region < ' tcx > ,
2733
+ pub lifetime_spans : FxHashSet < Span > ,
2734
+ pub pred_spans : Vec < Span > ,
2735
+ pub tcx : TyCtxt < ' tcx > ,
2736
+ }
2735
2737
impl < ' tcx > Visitor < ' tcx > for HirTraitObjectVisitor < ' tcx > {
2738
+ fn visit_lifetime ( & mut self , lt : & ' tcx hir:: Lifetime ) {
2739
+ if match ( lt. res , self . expected_region . kind ( ) ) {
2740
+ (
2741
+ hir:: LifetimeName :: ImplicitObjectLifetimeDefault
2742
+ | hir:: LifetimeName :: Static ,
2743
+ ty:: RegionKind :: ReStatic ,
2744
+ ) => true ,
2745
+ ( hir:: LifetimeName :: Param ( a) , ty:: RegionKind :: ReEarlyParam ( b) ) => {
2746
+ a. to_def_id ( ) == b. def_id
2747
+ }
2748
+ _ => false ,
2749
+ } {
2750
+ // We want to keep a span to the lifetime bound on the trait object.
2751
+ self . lifetime_spans . insert ( lt. ident . span ) ;
2752
+ }
2753
+ }
2736
2754
fn visit_ty ( & mut self , t : & ' tcx hir:: Ty < ' tcx > ) {
2737
- // Find all the trait objects that have the lifetime that was found.
2738
- if let hir:: TyKind :: TraitObject ( poly_trait_refs, lt, _) = t. kind
2739
- && match ( lt. res , self . 1 . kind ( ) ) {
2740
- (
2741
- hir:: LifetimeName :: ImplicitObjectLifetimeDefault
2742
- | hir:: LifetimeName :: Static ,
2743
- ty:: RegionKind :: ReStatic ,
2744
- ) => true ,
2745
- ( hir:: LifetimeName :: Param ( a) , ty:: RegionKind :: ReEarlyParam ( b) ) => {
2746
- a. to_def_id ( ) == b. def_id
2755
+ match t. kind {
2756
+ // Find all the trait objects that have the lifetime that was found.
2757
+ hir:: TyKind :: TraitObject ( poly_trait_refs, lt, _)
2758
+ if match ( lt. res , self . expected_region . kind ( ) ) {
2759
+ (
2760
+ hir:: LifetimeName :: ImplicitObjectLifetimeDefault
2761
+ | hir:: LifetimeName :: Static ,
2762
+ ty:: RegionKind :: ReStatic ,
2763
+ ) => true ,
2764
+ ( hir:: LifetimeName :: Param ( a) , ty:: RegionKind :: ReEarlyParam ( b) ) => {
2765
+ a. to_def_id ( ) == b. def_id
2766
+ }
2767
+ _ => false ,
2768
+ } =>
2769
+ {
2770
+ for ptr in poly_trait_refs {
2771
+ if let Some ( def_id) = ptr. trait_ref . trait_def_id ( ) {
2772
+ // Find the bounds on the trait with the lifetime that couldn't be met.
2773
+ let bindings: Vec < Span > = elaborate (
2774
+ self . tcx ,
2775
+ self . tcx
2776
+ . predicates_of ( def_id)
2777
+ . predicates
2778
+ . iter ( )
2779
+ . map ( |( p, sp) | ( p. as_predicate ( ) , * sp) ) ,
2780
+ )
2781
+ . filter_map ( |( pred, pred_span) | {
2782
+ if let ty:: PredicateKind :: Clause ( clause) =
2783
+ pred. kind ( ) . skip_binder ( )
2784
+ && let ty:: ClauseKind :: TypeOutlives ( ty:: OutlivesPredicate (
2785
+ _pred_ty,
2786
+ r,
2787
+ ) ) = clause
2788
+ && r == self . found_region
2789
+ {
2790
+ Some ( pred_span)
2791
+ } else {
2792
+ None
2793
+ }
2794
+ } )
2795
+ . collect ( ) ;
2796
+ if !bindings. is_empty ( ) {
2797
+ self . lifetime_spans . insert ( ptr. span ) ;
2798
+ self . pred_spans . extend ( bindings) ;
2799
+ }
2800
+ }
2747
2801
}
2748
- _ => false ,
2749
2802
}
2750
- {
2751
- for ptr in poly_trait_refs {
2752
- // We'll filter the traits later, after collection.
2753
- self . 0 . push ( ptr) ;
2803
+ // Detect when an associated item is given a lifetime restriction that the
2804
+ // definition of that associated item couldn't meet.
2805
+ hir:: TyKind :: Path ( hir:: QPath :: Resolved ( Some ( _) , path) ) => {
2806
+ self . pred_spans = elaborate (
2807
+ self . tcx ,
2808
+ self . tcx
2809
+ . predicates_of ( path. res . def_id ( ) )
2810
+ . predicates
2811
+ . iter ( )
2812
+ . map ( |( p, sp) | ( p. as_predicate ( ) , * sp) ) ,
2813
+ )
2814
+ . filter_map ( |( pred, pred_span) | {
2815
+ match pred. kind ( ) . skip_binder ( ) {
2816
+ ty:: PredicateKind :: Clause ( ty:: ClauseKind :: TypeOutlives (
2817
+ ty:: OutlivesPredicate (
2818
+ // What should I filter this with?
2819
+ _pred_ty,
2820
+ r,
2821
+ ) ,
2822
+ ) ) if r == self . found_region => Some ( pred_span) ,
2823
+ ty:: PredicateKind :: Clause ( ty:: ClauseKind :: RegionOutlives (
2824
+ ty:: OutlivesPredicate ( _, r) ,
2825
+ ) ) if r == self . found_region => Some ( pred_span) ,
2826
+ _ => None ,
2827
+ }
2828
+ } )
2829
+ . collect ( ) ;
2754
2830
}
2755
- // We want to keep a span to the lifetime bound on the trait object.
2756
- self . 2 . insert ( lt. ident . span ) ;
2831
+ _ => { }
2757
2832
}
2758
2833
hir:: intravisit:: walk_ty ( self , t) ;
2759
2834
}
2760
2835
}
2761
- let mut visitor = HirTraitObjectVisitor ( vec ! [ ] , sup, Default :: default ( ) ) ;
2836
+ let mut visitor = HirTraitObjectVisitor {
2837
+ expected_region : sup,
2838
+ found_region : sub,
2839
+ lifetime_spans : Default :: default ( ) ,
2840
+ pred_spans : vec ! [ ] ,
2841
+ tcx : self . tcx ,
2842
+ } ;
2762
2843
for field in item. fields ( ) {
2763
2844
if field. ty . span == * span {
2764
2845
// `span` points at the type of a field, we only want to look for trait objects in
@@ -2767,40 +2848,9 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> {
2767
2848
}
2768
2849
}
2769
2850
2770
- // The display of these spans will not change regardless or sorting.
2771
2851
#[ allow( rustc:: potential_query_instability) ]
2772
- let mut primary_spans: Vec < Span > = visitor. 2 . into_iter ( ) . collect ( ) ;
2773
- let mut relevant_bindings: Vec < Span > = vec ! [ ] ;
2774
- for ptr in visitor. 0 {
2775
- if let Some ( def_id) = ptr. trait_ref . trait_def_id ( ) {
2776
- // Find the bounds on the trait with the lifetime that couldn't be met.
2777
- let bindings: Vec < Span > = elaborate (
2778
- self . tcx ,
2779
- self . tcx
2780
- . predicates_of ( def_id)
2781
- . predicates
2782
- . iter ( )
2783
- . map ( |( p, sp) | ( p. as_predicate ( ) , * sp) ) ,
2784
- )
2785
- . filter_map ( |( pred, pred_span) | {
2786
- if let ty:: PredicateKind :: Clause ( clause) = pred. kind ( ) . skip_binder ( )
2787
- && let ty:: ClauseKind :: TypeOutlives ( ty:: OutlivesPredicate ( _pred_ty, r) ) =
2788
- clause
2789
- && r == sub
2790
- {
2791
- Some ( pred_span)
2792
- } else {
2793
- None
2794
- }
2795
- } )
2796
- . collect ( ) ;
2797
- if !bindings. is_empty ( ) {
2798
- primary_spans. push ( ptr. span ) ;
2799
- relevant_bindings. extend ( bindings) ;
2800
- }
2801
- }
2802
- }
2803
- Some ( ( primary_spans. into ( ) , relevant_bindings. into ( ) ) )
2852
+ let primary_spans: Vec < Span > = visitor. lifetime_spans . into_iter ( ) . collect ( ) ;
2853
+ Some ( ( primary_spans. into ( ) , visitor. pred_spans . into ( ) ) )
2804
2854
}
2805
2855
2806
2856
/// Determine whether an error associated with the given span and definition
0 commit comments