@@ -88,26 +88,31 @@ impl<'tcx> PlaceTy<'tcx> {
8888 ///
8989 /// Note that the resulting type has not been normalized.
9090 #[ 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 ( ) {
9499 ty:: Adt ( adt_def, args) if adt_def. is_enum ( ) => {
95100 adt_def. variant ( variant_index) . fields [ f] . ty ( tcx, args)
96101 }
97102 ty:: Coroutine ( def_id, args) => {
98103 let mut variants = args. as_coroutine ( ) . state_tys ( def_id, tcx) ;
99104 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 :?}" ) ;
101106 } ;
102107
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+ } )
106111 }
107- _ => bug ! ( "can't downcast non-adt non-coroutine type: {self :?}" ) ,
112+ _ => bug ! ( "can't downcast non-adt non-coroutine type: {self_ty :?}" ) ,
108113 }
109114 } else {
110- match self . ty . kind ( ) {
115+ match self_ty . kind ( ) {
111116 ty:: Adt ( adt_def, args) if !adt_def. is_enum ( ) => {
112117 adt_def. non_enum_variant ( ) . fields [ f] . ty ( tcx, args)
113118 }
@@ -116,26 +121,25 @@ impl<'tcx> PlaceTy<'tcx> {
116121 . upvar_tys ( )
117122 . get ( f. index ( ) )
118123 . copied ( )
119- . unwrap_or_else ( || bug ! ( "field {f:?} out of range: {self :?}" ) ) ,
124+ . unwrap_or_else ( || bug ! ( "field {f:?} out of range: {self_ty :?}" ) ) ,
120125 ty:: CoroutineClosure ( _, args) => args
121126 . as_coroutine_closure ( )
122127 . upvar_tys ( )
123128 . get ( f. index ( ) )
124129 . copied ( )
125- . unwrap_or_else ( || bug ! ( "field {f:?} out of range: {self :?}" ) ) ,
130+ . unwrap_or_else ( || bug ! ( "field {f:?} out of range: {self_ty :?}" ) ) ,
126131 // Only prefix fields (upvars and current state) are
127132 // 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+ }
134138 ty:: Tuple ( tys) => tys
135139 . get ( f. index ( ) )
136140 . 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 :?}" ) ,
139143 }
140144 }
141145 }
@@ -148,11 +152,11 @@ impl<'tcx> PlaceTy<'tcx> {
148152 elems. iter ( ) . fold ( self , |place_ty, & elem| place_ty. projection_ty ( tcx, elem) )
149153 }
150154
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.
154158 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)
156160 }
157161
158162 /// `place_ty.projection_ty_core(tcx, elem, |...| { ... })`
@@ -164,8 +168,9 @@ impl<'tcx> PlaceTy<'tcx> {
164168 self ,
165169 tcx : TyCtxt < ' tcx > ,
166170 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 > ,
169174 ) -> PlaceTy < ' tcx >
170175 where
171176 V : :: std:: fmt:: Debug ,
@@ -176,16 +181,16 @@ impl<'tcx> PlaceTy<'tcx> {
176181 }
177182 let answer = match * elem {
178183 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 ( || {
180185 bug ! ( "deref projection of non-dereferenceable ty {:?}" , self )
181186 } ) ;
182187 PlaceTy :: from_ty ( ty)
183188 }
184189 ProjectionElem :: Index ( _) | ProjectionElem :: ConstantIndex { .. } => {
185- PlaceTy :: from_ty ( self . ty . builtin_index ( ) . unwrap ( ) )
190+ PlaceTy :: from_ty ( structurally_normalize ( self . ty ) . builtin_index ( ) . unwrap ( ) )
186191 }
187192 ProjectionElem :: Subslice { from, to, from_end } => {
188- PlaceTy :: from_ty ( match self . ty . kind ( ) {
193+ PlaceTy :: from_ty ( match structurally_normalize ( self . ty ) . kind ( ) {
189194 ty:: Slice ( ..) => self . ty ,
190195 ty:: Array ( inner, _) if !from_end => Ty :: new_array ( tcx, * inner, to - from) ,
191196 ty:: Array ( inner, size) if from_end => {
@@ -201,17 +206,18 @@ impl<'tcx> PlaceTy<'tcx> {
201206 ProjectionElem :: Downcast ( _name, index) => {
202207 PlaceTy { ty : self . ty , variant_index : Some ( index) }
203208 }
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) ) ,
211217
212218 // FIXME(unsafe_binders): Rename `handle_opaque_cast_and_subtype` to be more general.
213219 ProjectionElem :: UnwrapUnsafeBinder ( ty) => {
214- PlaceTy :: from_ty ( handle_opaque_cast_and_subtype ( & self , ty) )
220+ PlaceTy :: from_ty ( handle_opaque_cast_and_subtype ( ty) )
215221 }
216222 } ;
217223 debug ! ( "projection_ty self: {:?} elem: {:?} yields: {:?}" , self , elem, answer) ;
0 commit comments