@@ -7,7 +7,8 @@ use rustc_arena::DroplessArena;
7
7
use rustc_hir:: def:: DefKind ;
8
8
use rustc_hir:: def_id:: { DefId , LocalDefId } ;
9
9
use 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 } ;
11
12
use std:: ops:: ControlFlow ;
12
13
13
14
/// 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
75
76
// type Foo<'a, 'b, 'c> = impl Trait<'a> + 'b;
76
77
// ```
77
78
// 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 ,
79
82
variances : Vec < ty:: Variance > ,
80
83
}
81
84
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 > {
83
103
#[ instrument( level = "trace" , skip( self ) , ret) ]
84
104
fn visit_region ( & mut self , r : ty:: Region < ' tcx > ) -> ControlFlow < Self :: BreakTy > {
85
105
if let ty:: RegionKind :: ReEarlyBound ( ebr) = r. kind ( ) {
86
106
self . variances [ ebr. index as usize ] = ty:: Invariant ;
87
107
}
88
108
r. super_visit_with ( self )
89
109
}
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
+ }
90
123
}
91
124
92
125
// 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
111
144
}
112
145
}
113
146
114
- let mut collector = OpaqueTypeLifetimeCollector { variances } ;
147
+ let mut collector =
148
+ OpaqueTypeLifetimeCollector { tcx, root_def_id : item_def_id. to_def_id ( ) , variances } ;
115
149
let id_substs = ty:: InternalSubsts :: identity_for_item ( tcx, item_def_id. to_def_id ( ) ) ;
116
150
for pred in tcx. bound_explicit_item_bounds ( item_def_id. to_def_id ( ) ) . transpose_iter ( ) {
117
151
let pred = pred. map_bound ( |( pred, _) | * pred) . subst ( tcx, id_substs) ;
0 commit comments