@@ -88,26 +88,31 @@ impl<'tcx> PlaceTy<'tcx> {
88
88
///
89
89
/// Note that the resulting type has not been normalized.
90
90
#[ instrument( level = "debug" , skip( tcx) , ret) ]
91
- pub fn field_ty ( self , tcx : TyCtxt < ' tcx > , f : FieldIdx ) -> Ty < ' tcx > {
92
- if let Some ( variant_index) = self . variant_index {
93
- match * self . ty . kind ( ) {
91
+ pub fn field_ty (
92
+ tcx : TyCtxt < ' tcx > ,
93
+ self_ty : Ty < ' tcx > ,
94
+ variant_idx : Option < VariantIdx > ,
95
+ f : FieldIdx ,
96
+ ) -> Ty < ' tcx > {
97
+ if let Some ( variant_index) = variant_idx {
98
+ match * self_ty. kind ( ) {
94
99
ty:: Adt ( adt_def, args) if adt_def. is_enum ( ) => {
95
100
adt_def. variant ( variant_index) . fields [ f] . ty ( tcx, args)
96
101
}
97
102
ty:: Coroutine ( def_id, args) => {
98
103
let mut variants = args. as_coroutine ( ) . state_tys ( def_id, tcx) ;
99
104
let Some ( mut variant) = variants. nth ( variant_index. into ( ) ) else {
100
- bug ! ( "variant {variant_index:?} of coroutine out of range: {self :?}" ) ;
105
+ bug ! ( "variant {variant_index:?} of coroutine out of range: {self_ty :?}" ) ;
101
106
} ;
102
107
103
- variant
104
- . nth ( f . index ( ) )
105
- . unwrap_or_else ( || bug ! ( "field {f:?} out of range: {self:?}" ) )
108
+ variant. nth ( f . index ( ) ) . unwrap_or_else ( || {
109
+ bug ! ( "field {f:?} out of range of variant: {self_ty:?} {variant_idx:?}" )
110
+ } )
106
111
}
107
- _ => bug ! ( "can't downcast non-adt non-coroutine type: {self :?}" ) ,
112
+ _ => bug ! ( "can't downcast non-adt non-coroutine type: {self_ty :?}" ) ,
108
113
}
109
114
} else {
110
- match self . ty . kind ( ) {
115
+ match self_ty . kind ( ) {
111
116
ty:: Adt ( adt_def, args) if !adt_def. is_enum ( ) => {
112
117
adt_def. non_enum_variant ( ) . fields [ f] . ty ( tcx, args)
113
118
}
@@ -116,26 +121,25 @@ impl<'tcx> PlaceTy<'tcx> {
116
121
. upvar_tys ( )
117
122
. get ( f. index ( ) )
118
123
. copied ( )
119
- . unwrap_or_else ( || bug ! ( "field {f:?} out of range: {self :?}" ) ) ,
124
+ . unwrap_or_else ( || bug ! ( "field {f:?} out of range: {self_ty :?}" ) ) ,
120
125
ty:: CoroutineClosure ( _, args) => args
121
126
. as_coroutine_closure ( )
122
127
. upvar_tys ( )
123
128
. get ( f. index ( ) )
124
129
. copied ( )
125
- . unwrap_or_else ( || bug ! ( "field {f:?} out of range: {self :?}" ) ) ,
130
+ . unwrap_or_else ( || bug ! ( "field {f:?} out of range: {self_ty :?}" ) ) ,
126
131
// Only prefix fields (upvars and current state) are
127
132
// accessible without a variant index.
128
- ty:: Coroutine ( _, args) => args
129
- . as_coroutine ( )
130
- . prefix_tys ( )
131
- . get ( f. index ( ) )
132
- . copied ( )
133
- . unwrap_or_else ( || bug ! ( "field {f:?} out of range: {self:?}" ) ) ,
133
+ ty:: Coroutine ( _, args) => {
134
+ args. as_coroutine ( ) . prefix_tys ( ) . get ( f. index ( ) ) . copied ( ) . unwrap_or_else ( || {
135
+ bug ! ( "field {f:?} out of range of prefixes for {self_ty}" )
136
+ } )
137
+ }
134
138
ty:: Tuple ( tys) => tys
135
139
. get ( f. index ( ) )
136
140
. copied ( )
137
- . unwrap_or_else ( || bug ! ( "field {f:?} out of range: {self :?}" ) ) ,
138
- _ => bug ! ( "can't project out of {self :?}" ) ,
141
+ . unwrap_or_else ( || bug ! ( "field {f:?} out of range: {self_ty :?}" ) ) ,
142
+ _ => bug ! ( "can't project out of {self_ty :?}" ) ,
139
143
}
140
144
}
141
145
}
@@ -148,11 +152,11 @@ impl<'tcx> PlaceTy<'tcx> {
148
152
elems. iter ( ) . fold ( self , |place_ty, & elem| place_ty. projection_ty ( tcx, elem) )
149
153
}
150
154
151
- /// Convenience wrapper around `projection_ty_core` for
152
- /// `PlaceElem`, where we can just use the `Ty` that is already
153
- /// stored inline on field projection elems.
155
+ /// Convenience wrapper around `projection_ty_core` for `PlaceElem`,
156
+ /// where we can just use the `Ty` that is already stored inline on
157
+ /// field projection elems.
154
158
pub fn projection_ty ( self , tcx : TyCtxt < ' tcx > , elem : PlaceElem < ' tcx > ) -> PlaceTy < ' tcx > {
155
- self . projection_ty_core ( tcx, & elem, |_, _, ty| ty, |_ , ty| ty)
159
+ self . projection_ty_core ( tcx, & elem, |ty| ty , | _, _, _ , ty| ty, |ty| ty)
156
160
}
157
161
158
162
/// `place_ty.projection_ty_core(tcx, elem, |...| { ... })`
@@ -164,8 +168,9 @@ impl<'tcx> PlaceTy<'tcx> {
164
168
self ,
165
169
tcx : TyCtxt < ' tcx > ,
166
170
elem : & ProjectionElem < V , T > ,
167
- mut handle_field : impl FnMut ( & Self , FieldIdx , T ) -> Ty < ' tcx > ,
168
- mut handle_opaque_cast_and_subtype : impl FnMut ( & Self , T ) -> Ty < ' tcx > ,
171
+ mut structurally_normalize : impl FnMut ( Ty < ' tcx > ) -> Ty < ' tcx > ,
172
+ mut handle_field : impl FnMut ( Ty < ' tcx > , Option < VariantIdx > , FieldIdx , T ) -> Ty < ' tcx > ,
173
+ mut handle_opaque_cast_and_subtype : impl FnMut ( T ) -> Ty < ' tcx > ,
169
174
) -> PlaceTy < ' tcx >
170
175
where
171
176
V : :: std:: fmt:: Debug ,
@@ -176,16 +181,16 @@ impl<'tcx> PlaceTy<'tcx> {
176
181
}
177
182
let answer = match * elem {
178
183
ProjectionElem :: Deref => {
179
- let ty = self . ty . builtin_deref ( true ) . unwrap_or_else ( || {
184
+ let ty = structurally_normalize ( self . ty ) . builtin_deref ( true ) . unwrap_or_else ( || {
180
185
bug ! ( "deref projection of non-dereferenceable ty {:?}" , self )
181
186
} ) ;
182
187
PlaceTy :: from_ty ( ty)
183
188
}
184
189
ProjectionElem :: Index ( _) | ProjectionElem :: ConstantIndex { .. } => {
185
- PlaceTy :: from_ty ( self . ty . builtin_index ( ) . unwrap ( ) )
190
+ PlaceTy :: from_ty ( structurally_normalize ( self . ty ) . builtin_index ( ) . unwrap ( ) )
186
191
}
187
192
ProjectionElem :: Subslice { from, to, from_end } => {
188
- PlaceTy :: from_ty ( match self . ty . kind ( ) {
193
+ PlaceTy :: from_ty ( match structurally_normalize ( self . ty ) . kind ( ) {
189
194
ty:: Slice ( ..) => self . ty ,
190
195
ty:: Array ( inner, _) if !from_end => Ty :: new_array ( tcx, * inner, to - from) ,
191
196
ty:: Array ( inner, size) if from_end => {
@@ -201,17 +206,18 @@ impl<'tcx> PlaceTy<'tcx> {
201
206
ProjectionElem :: Downcast ( _name, index) => {
202
207
PlaceTy { ty : self . ty , variant_index : Some ( index) }
203
208
}
204
- ProjectionElem :: Field ( f, fty) => PlaceTy :: from_ty ( handle_field ( & self , f, fty) ) ,
205
- ProjectionElem :: OpaqueCast ( ty) => {
206
- PlaceTy :: from_ty ( handle_opaque_cast_and_subtype ( & self , ty) )
207
- }
208
- ProjectionElem :: Subtype ( ty) => {
209
- PlaceTy :: from_ty ( handle_opaque_cast_and_subtype ( & self , ty) )
210
- }
209
+ ProjectionElem :: Field ( f, fty) => PlaceTy :: from_ty ( handle_field (
210
+ structurally_normalize ( self . ty ) ,
211
+ self . variant_index ,
212
+ f,
213
+ fty,
214
+ ) ) ,
215
+ ProjectionElem :: OpaqueCast ( ty) => PlaceTy :: from_ty ( handle_opaque_cast_and_subtype ( ty) ) ,
216
+ ProjectionElem :: Subtype ( ty) => PlaceTy :: from_ty ( handle_opaque_cast_and_subtype ( ty) ) ,
211
217
212
218
// FIXME(unsafe_binders): Rename `handle_opaque_cast_and_subtype` to be more general.
213
219
ProjectionElem :: UnwrapUnsafeBinder ( ty) => {
214
- PlaceTy :: from_ty ( handle_opaque_cast_and_subtype ( & self , ty) )
220
+ PlaceTy :: from_ty ( handle_opaque_cast_and_subtype ( ty) )
215
221
}
216
222
} ;
217
223
debug ! ( "projection_ty self: {:?} elem: {:?} yields: {:?}" , self , elem, answer) ;
0 commit comments