@@ -7,7 +7,8 @@ use rustc_arena::DroplessArena;
77use rustc_hir:: def:: DefKind ;
88use rustc_hir:: def_id:: { DefId , LocalDefId } ;
99use rustc_middle:: ty:: query:: Providers ;
10- use rustc_middle:: ty:: { self , CrateVariancesMap , TyCtxt , TypeSuperVisitable , TypeVisitable } ;
10+ use rustc_middle:: ty:: { self , CrateVariancesMap , SubstsRef , Ty , TyCtxt } ;
11+ use rustc_middle:: ty:: { DefIdTree , TypeSuperVisitable , TypeVisitable } ;
1112use std:: ops:: ControlFlow ;
1213
1314/// Defines the `TermsContext` basically houses an arena where we can
@@ -75,18 +76,50 @@ fn variance_of_opaque(tcx: TyCtxt<'_>, item_def_id: LocalDefId) -> &[ty::Varianc
7576 // type Foo<'a, 'b, 'c> = impl Trait<'a> + 'b;
7677 // ```
7778 // we may not use `'c` in the hidden type.
78- struct OpaqueTypeLifetimeCollector {
79+ struct OpaqueTypeLifetimeCollector < ' tcx > {
80+ tcx : TyCtxt < ' tcx > ,
81+ root_def_id : DefId ,
7982 variances : Vec < ty:: Variance > ,
8083 }
8184
82- impl < ' tcx > ty:: TypeVisitor < ' tcx > for OpaqueTypeLifetimeCollector {
85+ impl < ' tcx > OpaqueTypeLifetimeCollector < ' tcx > {
86+ #[ instrument( level = "trace" , skip( self ) , ret) ]
87+ fn visit_opaque ( & mut self , def_id : DefId , substs : SubstsRef < ' tcx > ) -> ControlFlow < !> {
88+ if def_id != self . root_def_id && self . tcx . is_descendant_of ( def_id, self . root_def_id ) {
89+ let child_variances = self . tcx . variances_of ( def_id) ;
90+ for ( a, v) in substs. iter ( ) . zip ( child_variances) {
91+ if * v != ty:: Bivariant {
92+ a. visit_with ( self ) ?;
93+ }
94+ }
95+ ControlFlow :: CONTINUE
96+ } else {
97+ substs. visit_with ( self )
98+ }
99+ }
100+ }
101+
102+ impl < ' tcx > ty:: TypeVisitor < ' tcx > for OpaqueTypeLifetimeCollector < ' tcx > {
83103 #[ instrument( level = "trace" , skip( self ) , ret) ]
84104 fn visit_region ( & mut self , r : ty:: Region < ' tcx > ) -> ControlFlow < Self :: BreakTy > {
85105 if let ty:: RegionKind :: ReEarlyBound ( ebr) = r. kind ( ) {
86106 self . variances [ ebr. index as usize ] = ty:: Invariant ;
87107 }
88108 r. super_visit_with ( self )
89109 }
110+
111+ #[ instrument( level = "trace" , skip( self ) , ret) ]
112+ fn visit_ty ( & mut self , t : Ty < ' tcx > ) -> ControlFlow < Self :: BreakTy > {
113+ match t. kind ( ) {
114+ ty:: Opaque ( def_id, substs) => self . visit_opaque ( * def_id, substs) ,
115+ ty:: Projection ( proj)
116+ if self . tcx . def_kind ( proj. item_def_id ) == DefKind :: ImplTraitPlaceholder =>
117+ {
118+ self . visit_opaque ( proj. item_def_id , proj. substs )
119+ }
120+ _ => t. super_visit_with ( self ) ,
121+ }
122+ }
90123 }
91124
92125 // By default, RPIT are invariant wrt type and const generics, but they are bivariant wrt
@@ -111,7 +144,8 @@ fn variance_of_opaque(tcx: TyCtxt<'_>, item_def_id: LocalDefId) -> &[ty::Varianc
111144 }
112145 }
113146
114- let mut collector = OpaqueTypeLifetimeCollector { variances } ;
147+ let mut collector =
148+ OpaqueTypeLifetimeCollector { tcx, root_def_id : item_def_id. to_def_id ( ) , variances } ;
115149 let id_substs = ty:: InternalSubsts :: identity_for_item ( tcx, item_def_id. to_def_id ( ) ) ;
116150 for pred in tcx. bound_explicit_item_bounds ( item_def_id. to_def_id ( ) ) . transpose_iter ( ) {
117151 let pred = pred. map_bound ( |( pred, _) | * pred) . subst ( tcx, id_substs) ;
0 commit comments