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