@@ -5,8 +5,7 @@ use rustc_index::{IndexSlice, IndexVec};
55use rustc_middle:: mir:: { GeneratorLayout , GeneratorSavedLocal } ;
66use rustc_middle:: query:: { LocalCrate , Providers } ;
77use rustc_middle:: ty:: layout:: {
8- IntegerExt , LayoutCx , LayoutError , LayoutOf , NaiveAbi , NaiveLayout , TyAndLayout ,
9- TyAndNaiveLayout , MAX_SIMD_LANES ,
8+ IntegerExt , LayoutCx , LayoutError , LayoutOf , TyAndLayout , MAX_SIMD_LANES ,
109} ;
1110use rustc_middle:: ty:: {
1211 self , AdtDef , EarlyBinder , GenericArgsRef , ReprOptions , Ty , TyCtxt , TypeVisitableExt ,
@@ -25,7 +24,7 @@ use crate::errors::{
2524use crate :: layout_sanity_check:: sanity_check_layout;
2625
2726pub fn provide ( providers : & mut Providers ) {
28- * providers = Providers { layout_of, naive_layout_of , reference_niches_policy, ..* providers } ;
27+ * providers = Providers { layout_of, reference_niches_policy, ..* providers } ;
2928}
3029
3130#[ instrument( skip( tcx) , level = "debug" ) ]
@@ -37,40 +36,6 @@ fn reference_niches_policy<'tcx>(tcx: TyCtxt<'tcx>, _: LocalCrate) -> ReferenceN
3736/// crates not specifying `-Z reference-niches`.
3837const DEFAULT_REF_NICHES : ReferenceNichePolicy = ReferenceNichePolicy { size : false , align : false } ;
3938
40- #[ instrument( skip( tcx, query) , level = "debug" ) ]
41- fn naive_layout_of < ' tcx > (
42- tcx : TyCtxt < ' tcx > ,
43- query : ty:: ParamEnvAnd < ' tcx , Ty < ' tcx > > ,
44- ) -> Result < TyAndNaiveLayout < ' tcx > , & ' tcx LayoutError < ' tcx > > {
45- let ( param_env, ty) = query. into_parts ( ) ;
46- debug ! ( ?ty) ;
47-
48- let param_env = param_env. with_reveal_all_normalized ( tcx) ;
49- let unnormalized_ty = ty;
50-
51- // FIXME: We might want to have two different versions of `layout_of`:
52- // One that can be called after typecheck has completed and can use
53- // `normalize_erasing_regions` here and another one that can be called
54- // before typecheck has completed and uses `try_normalize_erasing_regions`.
55- let ty = match tcx. try_normalize_erasing_regions ( param_env, ty) {
56- Ok ( t) => t,
57- Err ( normalization_error) => {
58- return Err ( tcx
59- . arena
60- . alloc ( LayoutError :: NormalizationFailure ( ty, normalization_error) ) ) ;
61- }
62- } ;
63-
64- if ty != unnormalized_ty {
65- // Ensure this layout is also cached for the normalized type.
66- return tcx. naive_layout_of ( param_env. and ( ty) ) ;
67- }
68-
69- let cx = LayoutCx { tcx, param_env } ;
70- let layout = naive_layout_of_uncached ( & cx, ty) ?;
71- Ok ( TyAndNaiveLayout { ty, layout } )
72- }
73-
7439#[ instrument( skip( tcx, query) , level = "debug" ) ]
7540fn layout_of < ' tcx > (
7641 tcx : TyCtxt < ' tcx > ,
@@ -90,13 +55,9 @@ fn layout_of<'tcx>(
9055 let cx = LayoutCx { tcx, param_env } ;
9156 let layout = layout_of_uncached ( & cx, ty) ?;
9257
93- if !naive. is_refined_by ( layout) {
94- bug ! ( "the naive layout isn't refined by the actual layout:\n {:#?}\n {:#?}" , naive, layout, ) ;
95- }
96-
9758 let layout = TyAndLayout { ty, layout } ;
9859 record_layout_for_printing ( & cx, layout) ;
99- sanity_check_layout ( & cx, & layout) ;
60+ sanity_check_layout ( & cx, & layout, & naive ) ;
10061
10162 Ok ( layout)
10263}
@@ -108,191 +69,6 @@ fn error<'tcx>(
10869 cx. tcx . arena . alloc ( err)
10970}
11071
111- fn naive_layout_of_uncached < ' tcx > (
112- cx : & LayoutCx < ' tcx , TyCtxt < ' tcx > > ,
113- ty : Ty < ' tcx > ,
114- ) -> Result < NaiveLayout , & ' tcx LayoutError < ' tcx > > {
115- let tcx = cx. tcx ;
116- let dl = cx. data_layout ( ) ;
117-
118- let scalar = |value : Primitive | NaiveLayout {
119- abi : NaiveAbi :: Scalar ( value) ,
120- size : value. size ( dl) ,
121- align : value. align ( dl) . abi ,
122- exact : true ,
123- } ;
124-
125- let univariant = |fields : & mut dyn Iterator < Item = Ty < ' tcx > > ,
126- repr : & ReprOptions |
127- -> Result < NaiveLayout , & ' tcx LayoutError < ' tcx > > {
128- if repr. pack . is_some ( ) && repr. align . is_some ( ) {
129- cx. tcx . sess . delay_span_bug ( DUMMY_SP , "struct cannot be packed and aligned" ) ;
130- return Err ( error ( cx, LayoutError :: Unknown ( ty) ) ) ;
131- }
132-
133- let linear = repr. inhibit_struct_field_reordering_opt ( ) ;
134- let pack = repr. pack . unwrap_or ( Align :: MAX ) ;
135- let mut layout = NaiveLayout :: EMPTY ;
136-
137- for field in fields {
138- let field = cx. naive_layout_of ( field) ?. packed ( pack) ;
139- if linear {
140- layout = layout. pad_to_align ( field. align ) ;
141- }
142- layout = layout
143- . concat ( & field, dl)
144- . ok_or_else ( || error ( cx, LayoutError :: SizeOverflow ( ty) ) ) ?;
145- }
146-
147- if let Some ( align) = repr. align {
148- layout = layout. align_to ( align) ;
149- }
150-
151- if linear {
152- layout. abi = layout. abi . as_aggregate ( ) ;
153- }
154-
155- Ok ( layout. pad_to_align ( layout. align ) )
156- } ;
157-
158- debug_assert ! ( !ty. has_non_region_infer( ) ) ;
159-
160- Ok ( match * ty. kind ( ) {
161- // Basic scalars
162- ty:: Bool => scalar ( Int ( I8 , false ) ) ,
163- ty:: Char => scalar ( Int ( I32 , false ) ) ,
164- ty:: Int ( ity) => scalar ( Int ( Integer :: from_int_ty ( dl, ity) , true ) ) ,
165- ty:: Uint ( ity) => scalar ( Int ( Integer :: from_uint_ty ( dl, ity) , false ) ) ,
166- ty:: Float ( fty) => scalar ( match fty {
167- ty:: FloatTy :: F32 => F32 ,
168- ty:: FloatTy :: F64 => F64 ,
169- } ) ,
170- ty:: FnPtr ( _) => scalar ( Pointer ( dl. instruction_address_space ) ) ,
171-
172- // The never type.
173- ty:: Never => NaiveLayout { abi : NaiveAbi :: Uninhabited , ..NaiveLayout :: EMPTY } ,
174-
175- // Potentially-wide pointers.
176- ty:: Ref ( _, pointee, _) | ty:: RawPtr ( ty:: TypeAndMut { ty : pointee, .. } ) => {
177- let data_ptr = scalar ( Pointer ( AddressSpace :: DATA ) ) ;
178- if let Some ( metadata) = ptr_metadata_scalar ( cx, pointee) ? {
179- // Effectively a (ptr, meta) tuple.
180- let l = data_ptr
181- . concat ( & scalar ( metadata. primitive ( ) ) , dl)
182- . ok_or_else ( || error ( cx, LayoutError :: SizeOverflow ( ty) ) ) ?;
183- l. pad_to_align ( l. align )
184- } else {
185- // No metadata, this is a thin pointer.
186- data_ptr
187- }
188- }
189-
190- ty:: Dynamic ( _, _, ty:: DynStar ) => {
191- let ptr = scalar ( Pointer ( AddressSpace :: DATA ) ) ;
192- ptr. concat ( & ptr, dl) . ok_or_else ( || error ( cx, LayoutError :: SizeOverflow ( ty) ) ) ?
193- }
194-
195- // Arrays and slices.
196- ty:: Array ( element, count) => {
197- let count = compute_array_count ( cx, count)
198- . ok_or_else ( || error ( cx, LayoutError :: Unknown ( ty) ) ) ?;
199- let element = cx. naive_layout_of ( element) ?;
200- NaiveLayout {
201- abi : element. abi . as_aggregate ( ) ,
202- size : element
203- . size
204- . checked_mul ( count, cx)
205- . ok_or_else ( || error ( cx, LayoutError :: SizeOverflow ( ty) ) ) ?,
206- ..* element
207- }
208- }
209- ty:: Slice ( element) => {
210- let element = cx. naive_layout_of ( element) ?;
211- NaiveLayout { abi : NaiveAbi :: Unsized , size : Size :: ZERO , ..* element }
212- }
213-
214- ty:: FnDef ( ..) => NaiveLayout :: EMPTY ,
215-
216- // Unsized types.
217- ty:: Str | ty:: Dynamic ( _, _, ty:: Dyn ) | ty:: Foreign ( ..) => {
218- NaiveLayout { abi : NaiveAbi :: Unsized , ..NaiveLayout :: EMPTY }
219- }
220-
221- // FIXME(reference_niches): try to actually compute a reasonable layout estimate,
222- // without duplicating too much code from `generator_layout`.
223- ty:: Generator ( ..) => NaiveLayout { exact : false , ..NaiveLayout :: EMPTY } ,
224-
225- ty:: Closure ( _, ref substs) => {
226- univariant ( & mut substs. as_closure ( ) . upvar_tys ( ) , & ReprOptions :: default ( ) ) ?
227- }
228-
229- ty:: Tuple ( tys) => univariant ( & mut tys. iter ( ) , & ReprOptions :: default ( ) ) ?,
230-
231- ty:: Adt ( def, substs) if def. is_union ( ) => {
232- let repr = def. repr ( ) ;
233- let pack = repr. pack . unwrap_or ( Align :: MAX ) ;
234- if repr. pack . is_some ( ) && repr. align . is_some ( ) {
235- cx. tcx . sess . delay_span_bug ( DUMMY_SP , "union cannot be packed and aligned" ) ;
236- return Err ( error ( cx, LayoutError :: Unknown ( ty) ) ) ;
237- }
238-
239- let mut layout = NaiveLayout :: EMPTY ;
240- for f in & def. variants ( ) [ FIRST_VARIANT ] . fields {
241- let field = cx. naive_layout_of ( f. ty ( tcx, substs) ) ?;
242- layout = layout. union ( & field. packed ( pack) ) ;
243- }
244-
245- // Unions are always inhabited, and never scalar if `repr(C)`.
246- if !matches ! ( layout. abi, NaiveAbi :: Scalar ( _) ) || repr. inhibit_enum_layout_opt ( ) {
247- layout. abi = NaiveAbi :: Sized ;
248- }
249-
250- if let Some ( align) = repr. align {
251- layout = layout. align_to ( align) ;
252- }
253- layout. pad_to_align ( layout. align )
254- }
255-
256- ty:: Adt ( def, substs) => {
257- let repr = def. repr ( ) ;
258- let base = NaiveLayout {
259- // For simplicity, assume that any enum has its discriminant field (if it exists)
260- // niched inside one of the variants; this will underestimate the size (and sometimes
261- // alignment) of enums. We also doesn't compute exact alignment for SIMD structs.
262- // FIXME(reference_niches): Be smarter here.
263- // Also consider adding a special case for null-optimized enums, so that we can have
264- // `Option<&T>: PointerLike` in generic contexts.
265- exact : !def. is_enum ( ) && !repr. simd ( ) ,
266- // An ADT with no inhabited variants should have an uninhabited ABI.
267- abi : NaiveAbi :: Uninhabited ,
268- ..NaiveLayout :: EMPTY
269- } ;
270-
271- let layout = def. variants ( ) . iter ( ) . try_fold ( base, |layout, v| {
272- let mut fields = v. fields . iter ( ) . map ( |f| f. ty ( tcx, substs) ) ;
273- let vlayout = univariant ( & mut fields, & repr) ?;
274- Ok ( layout. union ( & vlayout) )
275- } ) ?;
276- layout. pad_to_align ( layout. align )
277- }
278-
279- // Types with no meaningful known layout.
280- ty:: Alias ( ..) => {
281- // NOTE(eddyb) `layout_of` query should've normalized these away,
282- // if that was possible, so there's no reason to try again here.
283- return Err ( error ( cx, LayoutError :: Unknown ( ty) ) ) ;
284- }
285-
286- ty:: Bound ( ..) | ty:: GeneratorWitness ( ..) | ty:: GeneratorWitnessMIR ( ..) | ty:: Infer ( _) => {
287- bug ! ( "Layout::compute: unexpected type `{}`" , ty)
288- }
289-
290- ty:: Placeholder ( ..) | ty:: Param ( _) | ty:: Error ( _) => {
291- return Err ( error ( cx, LayoutError :: Unknown ( ty) ) ) ;
292- }
293- } )
294- }
295-
29672fn univariant_uninterned < ' tcx > (
29773 cx : & LayoutCx < ' tcx , TyCtxt < ' tcx > > ,
29874 ty : Ty < ' tcx > ,
@@ -739,7 +515,7 @@ fn layout_of_uncached<'tcx>(
739515 } )
740516}
741517
742- fn compute_array_count < ' tcx > (
518+ pub ( crate ) fn compute_array_count < ' tcx > (
743519 cx : & LayoutCx < ' tcx , TyCtxt < ' tcx > > ,
744520 mut count : ty:: Const < ' tcx > ,
745521) -> Option < u64 > {
@@ -754,7 +530,7 @@ fn compute_array_count<'tcx>(
754530 count. try_eval_target_usize ( tcx, param_env)
755531}
756532
757- fn ptr_metadata_scalar < ' tcx > (
533+ pub ( crate ) fn ptr_metadata_scalar < ' tcx > (
758534 cx : & LayoutCx < ' tcx , TyCtxt < ' tcx > > ,
759535 pointee : Ty < ' tcx > ,
760536) -> Result < Option < Scalar > , & ' tcx LayoutError < ' tcx > > {
0 commit comments