@@ -2105,118 +2105,148 @@ where
21052105 }
21062106
21072107 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+ }
21162112
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+ } ;
21522131
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+ ) ) ;
21702166 }
2171- _ => bug ! ( "TyAndLayout::field_type({:?}): not applicable" , this) ,
2172- }
2173- }
21742167
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) ,
21932190 }
2194- substs. as_generator ( ) . prefix_tys ( ) . nth ( i) . unwrap ( )
21952191 }
2196- } ,
21972192
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 ) ,
21992196
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+ }
22042228
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+ }
22092234 }
22102235 }
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) ,
22112244 }
2245+ }
22122246
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,
22202250 } )
22212251 }
22222252
0 commit comments