@@ -5,8 +5,7 @@ use rustc_index::{IndexSlice, IndexVec};
5
5
use rustc_middle:: mir:: { GeneratorLayout , GeneratorSavedLocal } ;
6
6
use rustc_middle:: query:: { LocalCrate , Providers } ;
7
7
use 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 ,
10
9
} ;
11
10
use rustc_middle:: ty:: {
12
11
self , AdtDef , EarlyBinder , GenericArgsRef , ReprOptions , Ty , TyCtxt , TypeVisitableExt ,
@@ -25,7 +24,7 @@ use crate::errors::{
25
24
use crate :: layout_sanity_check:: sanity_check_layout;
26
25
27
26
pub 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 } ;
29
28
}
30
29
31
30
#[ instrument( skip( tcx) , level = "debug" ) ]
@@ -37,40 +36,6 @@ fn reference_niches_policy<'tcx>(tcx: TyCtxt<'tcx>, _: LocalCrate) -> ReferenceN
37
36
/// crates not specifying `-Z reference-niches`.
38
37
const DEFAULT_REF_NICHES : ReferenceNichePolicy = ReferenceNichePolicy { size : false , align : false } ;
39
38
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
-
74
39
#[ instrument( skip( tcx, query) , level = "debug" ) ]
75
40
fn layout_of < ' tcx > (
76
41
tcx : TyCtxt < ' tcx > ,
@@ -90,13 +55,9 @@ fn layout_of<'tcx>(
90
55
let cx = LayoutCx { tcx, param_env } ;
91
56
let layout = layout_of_uncached ( & cx, ty) ?;
92
57
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
-
97
58
let layout = TyAndLayout { ty, layout } ;
98
59
record_layout_for_printing ( & cx, layout) ;
99
- sanity_check_layout ( & cx, & layout) ;
60
+ sanity_check_layout ( & cx, & layout, & naive ) ;
100
61
101
62
Ok ( layout)
102
63
}
@@ -108,191 +69,6 @@ fn error<'tcx>(
108
69
cx. tcx . arena . alloc ( err)
109
70
}
110
71
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
-
296
72
fn univariant_uninterned < ' tcx > (
297
73
cx : & LayoutCx < ' tcx , TyCtxt < ' tcx > > ,
298
74
ty : Ty < ' tcx > ,
@@ -739,7 +515,7 @@ fn layout_of_uncached<'tcx>(
739
515
} )
740
516
}
741
517
742
- fn compute_array_count < ' tcx > (
518
+ pub ( crate ) fn compute_array_count < ' tcx > (
743
519
cx : & LayoutCx < ' tcx , TyCtxt < ' tcx > > ,
744
520
mut count : ty:: Const < ' tcx > ,
745
521
) -> Option < u64 > {
@@ -754,7 +530,7 @@ fn compute_array_count<'tcx>(
754
530
count. try_eval_target_usize ( tcx, param_env)
755
531
}
756
532
757
- fn ptr_metadata_scalar < ' tcx > (
533
+ pub ( crate ) fn ptr_metadata_scalar < ' tcx > (
758
534
cx : & LayoutCx < ' tcx , TyCtxt < ' tcx > > ,
759
535
pointee : Ty < ' tcx > ,
760
536
) -> Result < Option < Scalar > , & ' tcx LayoutError < ' tcx > > {
0 commit comments