@@ -2105,118 +2105,148 @@ where
2105
2105
}
2106
2106
2107
2107
fn field ( this : TyAndLayout < ' tcx > , cx : & C , i : usize ) -> C :: TyAndLayout {
2108
- let tcx = cx. tcx ( ) ;
2109
- let tag_layout = |tag : & Scalar | -> C :: TyAndLayout {
2110
- let layout = Layout :: scalar ( cx, tag. clone ( ) ) ;
2111
- MaybeResult :: from ( Ok ( TyAndLayout {
2112
- layout : tcx. intern_layout ( layout) ,
2113
- ty : tag. value . to_ty ( tcx) ,
2114
- } ) )
2115
- } ;
2108
+ enum TyMaybeWithLayout < C : LayoutOf > {
2109
+ Ty ( C :: Ty ) ,
2110
+ TyAndLayout ( C :: TyAndLayout ) ,
2111
+ }
2116
2112
2117
- cx. layout_of ( match * this. ty . kind ( ) {
2118
- ty:: Bool
2119
- | ty:: Char
2120
- | ty:: Int ( _)
2121
- | ty:: Uint ( _)
2122
- | ty:: Float ( _)
2123
- | ty:: FnPtr ( _)
2124
- | ty:: Never
2125
- | ty:: FnDef ( ..)
2126
- | ty:: GeneratorWitness ( ..)
2127
- | ty:: Foreign ( ..)
2128
- | ty:: Dynamic ( ..) => bug ! ( "TyAndLayout::field_type({:?}): not applicable" , this) ,
2129
-
2130
- // Potentially-fat pointers.
2131
- ty:: Ref ( _, pointee, _) | ty:: RawPtr ( ty:: TypeAndMut { ty : pointee, .. } ) => {
2132
- assert ! ( i < this. fields. count( ) ) ;
2133
-
2134
- // Reuse the fat `*T` type as its own thin pointer data field.
2135
- // This provides information about, e.g., DST struct pointees
2136
- // (which may have no non-DST form), and will work as long
2137
- // as the `Abi` or `FieldsShape` is checked by users.
2138
- if i == 0 {
2139
- let nil = tcx. mk_unit ( ) ;
2140
- let ptr_ty = if this. ty . is_unsafe_ptr ( ) {
2141
- tcx. mk_mut_ptr ( nil)
2142
- } else {
2143
- tcx. mk_mut_ref ( tcx. lifetimes . re_static , nil)
2144
- } ;
2145
- return MaybeResult :: from ( cx. layout_of ( ptr_ty) . to_result ( ) . map (
2146
- |mut ptr_layout| {
2147
- ptr_layout. ty = this. ty ;
2148
- ptr_layout
2149
- } ,
2150
- ) ) ;
2151
- }
2113
+ fn ty_and_layout_kind <
2114
+ C : LayoutOf < Ty = Ty < ' tcx > , TyAndLayout : MaybeResult < TyAndLayout < ' tcx > > >
2115
+ + HasTyCtxt < ' tcx >
2116
+ + HasParamEnv < ' tcx > ,
2117
+ > (
2118
+ this : TyAndLayout < ' tcx > ,
2119
+ cx : & C ,
2120
+ i : usize ,
2121
+ ty : C :: Ty ,
2122
+ ) -> TyMaybeWithLayout < C > {
2123
+ let tcx = cx. tcx ( ) ;
2124
+ let tag_layout = |tag : & Scalar | -> C :: TyAndLayout {
2125
+ let layout = Layout :: scalar ( cx, tag. clone ( ) ) ;
2126
+ MaybeResult :: from ( Ok ( TyAndLayout {
2127
+ layout : tcx. intern_layout ( layout) ,
2128
+ ty : tag. value . to_ty ( tcx) ,
2129
+ } ) )
2130
+ } ;
2152
2131
2153
- match tcx. struct_tail_erasing_lifetimes ( pointee, cx. param_env ( ) ) . kind ( ) {
2154
- ty:: Slice ( _) | ty:: Str => tcx. types . usize ,
2155
- ty:: Dynamic ( _, _) => {
2156
- tcx. mk_imm_ref ( tcx. lifetimes . re_static , tcx. mk_array ( tcx. types . usize , 3 ) )
2157
- /* FIXME: use actual fn pointers
2158
- Warning: naively computing the number of entries in the
2159
- vtable by counting the methods on the trait + methods on
2160
- all parent traits does not work, because some methods can
2161
- be not object safe and thus excluded from the vtable.
2162
- Increase this counter if you tried to implement this but
2163
- failed to do it without duplicating a lot of code from
2164
- other places in the compiler: 2
2165
- tcx.mk_tup(&[
2166
- tcx.mk_array(tcx.types.usize, 3),
2167
- tcx.mk_array(Option<fn()>),
2168
- ])
2169
- */
2132
+ match * ty. kind ( ) {
2133
+ ty:: Bool
2134
+ | ty:: Char
2135
+ | ty:: Int ( _)
2136
+ | ty:: Uint ( _)
2137
+ | ty:: Float ( _)
2138
+ | ty:: FnPtr ( _)
2139
+ | ty:: Never
2140
+ | ty:: FnDef ( ..)
2141
+ | ty:: GeneratorWitness ( ..)
2142
+ | ty:: Foreign ( ..)
2143
+ | ty:: Dynamic ( ..) => bug ! ( "TyAndLayout::field_type({:?}): not applicable" , this) ,
2144
+
2145
+ // Potentially-fat pointers.
2146
+ ty:: Ref ( _, pointee, _) | ty:: RawPtr ( ty:: TypeAndMut { ty : pointee, .. } ) => {
2147
+ assert ! ( i < this. fields. count( ) ) ;
2148
+
2149
+ // Reuse the fat `*T` type as its own thin pointer data field.
2150
+ // This provides information about, e.g., DST struct pointees
2151
+ // (which may have no non-DST form), and will work as long
2152
+ // as the `Abi` or `FieldsShape` is checked by users.
2153
+ if i == 0 {
2154
+ let nil = tcx. mk_unit ( ) ;
2155
+ let ptr_ty = if ty. is_unsafe_ptr ( ) {
2156
+ tcx. mk_mut_ptr ( nil)
2157
+ } else {
2158
+ tcx. mk_mut_ref ( tcx. lifetimes . re_static , nil)
2159
+ } ;
2160
+ return TyMaybeWithLayout :: TyAndLayout ( MaybeResult :: from (
2161
+ cx. layout_of ( ptr_ty) . to_result ( ) . map ( |mut ptr_layout| {
2162
+ ptr_layout. ty = ty;
2163
+ ptr_layout
2164
+ } ) ,
2165
+ ) ) ;
2170
2166
}
2171
- _ => bug ! ( "TyAndLayout::field_type({:?}): not applicable" , this) ,
2172
- }
2173
- }
2174
2167
2175
- // Arrays and slices.
2176
- ty:: Array ( element, _) | ty:: Slice ( element) => element,
2177
- ty:: Str => tcx. types . u8 ,
2178
-
2179
- // Tuples, generators and closures.
2180
- ty:: Closure ( _, ref substs) => substs. as_closure ( ) . upvar_tys ( ) . nth ( i) . unwrap ( ) ,
2181
-
2182
- ty:: Generator ( def_id, ref substs, _) => match this. variants {
2183
- Variants :: Single { index } => substs
2184
- . as_generator ( )
2185
- . state_tys ( def_id, tcx)
2186
- . nth ( index. as_usize ( ) )
2187
- . unwrap ( )
2188
- . nth ( i)
2189
- . unwrap ( ) ,
2190
- Variants :: Multiple { ref tag, tag_field, .. } => {
2191
- if i == tag_field {
2192
- return tag_layout ( tag) ;
2168
+ match tcx. struct_tail_erasing_lifetimes ( pointee, cx. param_env ( ) ) . kind ( ) {
2169
+ ty:: Slice ( _) | ty:: Str => TyMaybeWithLayout :: Ty ( tcx. types . usize ) ,
2170
+ ty:: Dynamic ( _, _) => {
2171
+ TyMaybeWithLayout :: Ty ( tcx. mk_imm_ref (
2172
+ tcx. lifetimes . re_static ,
2173
+ tcx. mk_array ( tcx. types . usize , 3 ) ,
2174
+ ) )
2175
+ /* FIXME: use actual fn pointers
2176
+ Warning: naively computing the number of entries in the
2177
+ vtable by counting the methods on the trait + methods on
2178
+ all parent traits does not work, because some methods can
2179
+ be not object safe and thus excluded from the vtable.
2180
+ Increase this counter if you tried to implement this but
2181
+ failed to do it without duplicating a lot of code from
2182
+ other places in the compiler: 2
2183
+ tcx.mk_tup(&[
2184
+ tcx.mk_array(tcx.types.usize, 3),
2185
+ tcx.mk_array(Option<fn()>),
2186
+ ])
2187
+ */
2188
+ }
2189
+ _ => bug ! ( "TyAndLayout::field_type({:?}): not applicable" , this) ,
2193
2190
}
2194
- substs. as_generator ( ) . prefix_tys ( ) . nth ( i) . unwrap ( )
2195
2191
}
2196
- } ,
2197
2192
2198
- ty:: Tuple ( tys) => tys[ i] . expect_ty ( ) ,
2193
+ // Arrays and slices.
2194
+ ty:: Array ( element, _) | ty:: Slice ( element) => TyMaybeWithLayout :: Ty ( element) ,
2195
+ ty:: Str => TyMaybeWithLayout :: Ty ( tcx. types . u8 ) ,
2199
2196
2200
- // ADTs.
2201
- ty:: Adt ( def, substs) => {
2202
- match this. variants {
2203
- Variants :: Single { index } => def. variants [ index] . fields [ i] . ty ( tcx, substs) ,
2197
+ // Tuples, generators and closures.
2198
+ ty:: Closure ( _, ref substs) => {
2199
+ ty_and_layout_kind ( this, cx, i, substs. as_closure ( ) . tupled_upvars_ty ( ) )
2200
+ }
2201
+
2202
+ ty:: Generator ( def_id, ref substs, _) => match this. variants {
2203
+ Variants :: Single { index } => TyMaybeWithLayout :: Ty (
2204
+ substs
2205
+ . as_generator ( )
2206
+ . state_tys ( def_id, tcx)
2207
+ . nth ( index. as_usize ( ) )
2208
+ . unwrap ( )
2209
+ . nth ( i)
2210
+ . unwrap ( ) ,
2211
+ ) ,
2212
+ Variants :: Multiple { ref tag, tag_field, .. } => {
2213
+ if i == tag_field {
2214
+ return TyMaybeWithLayout :: TyAndLayout ( tag_layout ( tag) ) ;
2215
+ }
2216
+ TyMaybeWithLayout :: Ty ( substs. as_generator ( ) . prefix_tys ( ) . nth ( i) . unwrap ( ) )
2217
+ }
2218
+ } ,
2219
+
2220
+ ty:: Tuple ( tys) => TyMaybeWithLayout :: Ty ( tys[ i] . expect_ty ( ) ) ,
2221
+
2222
+ // ADTs.
2223
+ ty:: Adt ( def, substs) => {
2224
+ match this. variants {
2225
+ Variants :: Single { index } => {
2226
+ TyMaybeWithLayout :: Ty ( def. variants [ index] . fields [ i] . ty ( tcx, substs) )
2227
+ }
2204
2228
2205
- // Discriminant field for enums (where applicable).
2206
- Variants :: Multiple { ref tag, .. } => {
2207
- assert_eq ! ( i, 0 ) ;
2208
- return tag_layout ( tag) ;
2229
+ // Discriminant field for enums (where applicable).
2230
+ Variants :: Multiple { ref tag, .. } => {
2231
+ assert_eq ! ( i, 0 ) ;
2232
+ return TyMaybeWithLayout :: TyAndLayout ( tag_layout ( tag) ) ;
2233
+ }
2209
2234
}
2210
2235
}
2236
+
2237
+ ty:: Projection ( _)
2238
+ | ty:: Bound ( ..)
2239
+ | ty:: Placeholder ( ..)
2240
+ | ty:: Opaque ( ..)
2241
+ | ty:: Param ( _)
2242
+ | ty:: Infer ( _)
2243
+ | ty:: Error ( _) => bug ! ( "TyAndLayout::field_type: unexpected type `{}`" , this. ty) ,
2211
2244
}
2245
+ }
2212
2246
2213
- ty:: Projection ( _)
2214
- | ty:: Bound ( ..)
2215
- | ty:: Placeholder ( ..)
2216
- | ty:: Opaque ( ..)
2217
- | ty:: Param ( _)
2218
- | ty:: Infer ( _)
2219
- | ty:: Error ( _) => bug ! ( "TyAndLayout::field_type: unexpected type `{}`" , this. ty) ,
2247
+ cx. layout_of ( match ty_and_layout_kind ( this, cx, i, this. ty ) {
2248
+ TyMaybeWithLayout :: Ty ( result) => result,
2249
+ TyMaybeWithLayout :: TyAndLayout ( result) => return result,
2220
2250
} )
2221
2251
}
2222
2252
0 commit comments