@@ -2727,38 +2727,119 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> {
27272727 return None ;
27282728 } ;
27292729 /// 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+ }
27352737 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+ }
27362754 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+ }
27472801 }
2748- _ => false ,
27492802 }
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 ( ) ;
27542830 }
2755- // We want to keep a span to the lifetime bound on the trait object.
2756- self . 2 . insert ( lt. ident . span ) ;
2831+ _ => { }
27572832 }
27582833 hir:: intravisit:: walk_ty ( self , t) ;
27592834 }
27602835 }
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+ } ;
27622843 for field in item. fields ( ) {
27632844 if field. ty . span == * span {
27642845 // `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> {
27672848 }
27682849 }
27692850
2770- // The display of these spans will not change regardless or sorting.
27712851 #[ 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 ( ) ) )
28042854 }
28052855
28062856 /// Determine whether an error associated with the given span and definition
0 commit comments