@@ -2716,38 +2716,119 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> {
27162716 return None ;
27172717 } ;
27182718 /// 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+ }
27242726 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+ }
27252743 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+ }
27362790 }
2737- _ => false ,
27382791 }
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 ( ) ;
27432819 }
2744- // We want to keep a span to the lifetime bound on the trait object.
2745- self . 2 . insert ( lt. ident . span ) ;
2820+ _ => { }
27462821 }
27472822 hir:: intravisit:: walk_ty ( self , t) ;
27482823 }
27492824 }
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+ } ;
27512832 for field in item. fields ( ) {
27522833 if field. ty . span == * span {
27532834 // `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> {
27562837 }
27572838 }
27582839
2759- // The display of these spans will not change regardless or sorting.
27602840 #[ 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 ( ) ) )
27932843 }
27942844
27952845 /// Determine whether an error associated with the given span and definition
0 commit comments