@@ -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