@@ -154,9 +154,19 @@ fn naive_layout_of_uncached<'tcx>(
154
154
ty:: Never => NaiveLayout :: EMPTY ,
155
155
156
156
// Potentially-wide pointers.
157
- ty:: Ref ( _, _, _) | ty:: RawPtr ( _) => {
158
- // TODO(reference_niches): handle wide pointers
159
- scalar ( Pointer ( AddressSpace :: DATA ) )
157
+ ty:: Ref ( _, pointee, _) | ty:: RawPtr ( ty:: TypeAndMut { ty : pointee, .. } ) => {
158
+ let data_ptr = scalar ( Pointer ( AddressSpace :: DATA ) ) ;
159
+
160
+ if let Some ( metadata) = ptr_metadata_scalar ( cx, pointee) ? {
161
+ // Effectively a (ptr, meta) tuple.
162
+ data_ptr
163
+ . concat ( & scalar ( metadata. primitive ( ) ) , cx)
164
+ . ok_or_else ( || error ( cx, LayoutError :: SizeOverflow ( ty) ) ) ?
165
+ . pad_to_align ( )
166
+ } else {
167
+ // No metadata, this is a thin pointer.
168
+ data_ptr
169
+ }
160
170
}
161
171
162
172
ty:: Dynamic ( _, _, ty:: DynStar ) => {
@@ -165,10 +175,15 @@ fn naive_layout_of_uncached<'tcx>(
165
175
}
166
176
167
177
// Arrays and slices.
168
- ty:: Array ( element, _count) => {
178
+ ty:: Array ( element, count) => {
179
+ let count = compute_array_count ( cx, count)
180
+ . ok_or_else ( || error ( cx, LayoutError :: Unknown ( ty) ) ) ?;
169
181
let element = cx. naive_layout_of ( element) ?;
170
182
NaiveLayout {
171
- min_size : Size :: ZERO , // TODO(reference_niches): proper array size
183
+ min_size : element
184
+ . min_size
185
+ . checked_mul ( count, cx)
186
+ . ok_or_else ( || error ( cx, LayoutError :: SizeOverflow ( ty) ) ) ?,
172
187
min_align : element. min_align ,
173
188
}
174
189
}
@@ -311,72 +326,13 @@ fn layout_of_uncached<'tcx>(
311
326
data_ptr. valid_range_mut ( ) . start = 1 ;
312
327
}
313
328
314
- let pointee = tcx. normalize_erasing_regions ( param_env, pointee) ;
315
- if pointee. is_sized ( tcx, param_env) {
316
- return Ok ( tcx. mk_layout ( LayoutS :: scalar ( cx, data_ptr) ) ) ;
317
- }
318
-
319
- let metadata = if let Some ( metadata_def_id) = tcx. lang_items ( ) . metadata_type ( )
320
- // Projection eagerly bails out when the pointee references errors,
321
- // fall back to structurally deducing metadata.
322
- && !pointee. references_error ( )
323
- {
324
- let pointee_metadata = Ty :: new_projection ( tcx, metadata_def_id, [ pointee] ) ;
325
- let metadata_ty = match tcx. try_normalize_erasing_regions (
326
- param_env,
327
- pointee_metadata,
328
- ) {
329
- Ok ( metadata_ty) => metadata_ty,
330
- Err ( mut err) => {
331
- // Usually `<Ty as Pointee>::Metadata` can't be normalized because
332
- // its struct tail cannot be normalized either, so try to get a
333
- // more descriptive layout error here, which will lead to less confusing
334
- // diagnostics.
335
- match tcx. try_normalize_erasing_regions (
336
- param_env,
337
- tcx. struct_tail_without_normalization ( pointee) ,
338
- ) {
339
- Ok ( _) => { } ,
340
- Err ( better_err) => {
341
- err = better_err;
342
- }
343
- }
344
- return Err ( error ( cx, LayoutError :: NormalizationFailure ( pointee, err) ) ) ;
345
- } ,
346
- } ;
347
-
348
- let metadata_layout = cx. layout_of ( metadata_ty) ?;
349
- // If the metadata is a 1-zst, then the pointer is thin.
350
- if metadata_layout. is_zst ( ) && metadata_layout. align . abi . bytes ( ) == 1 {
351
- return Ok ( tcx. mk_layout ( LayoutS :: scalar ( cx, data_ptr) ) ) ;
352
- }
353
-
354
- let Abi :: Scalar ( metadata) = metadata_layout. abi else {
355
- return Err ( error ( cx, LayoutError :: Unknown ( pointee) ) ) ;
356
- } ;
357
-
358
- metadata
329
+ if let Some ( metadata) = ptr_metadata_scalar ( cx, pointee) ? {
330
+ // Effectively a (ptr, meta) tuple.
331
+ tcx. mk_layout ( cx. scalar_pair ( data_ptr, metadata) )
359
332
} else {
360
- let unsized_part = tcx. struct_tail_erasing_lifetimes ( pointee, param_env) ;
361
-
362
- match unsized_part. kind ( ) {
363
- ty:: Foreign ( ..) => {
364
- return Ok ( tcx. mk_layout ( LayoutS :: scalar ( cx, data_ptr) ) ) ;
365
- }
366
- ty:: Slice ( _) | ty:: Str => scalar_unit ( Int ( dl. ptr_sized_integer ( ) , false ) ) ,
367
- ty:: Dynamic ( ..) => {
368
- let mut vtable = scalar_unit ( Pointer ( AddressSpace :: DATA ) ) ;
369
- vtable. valid_range_mut ( ) . start = 1 ;
370
- vtable
371
- }
372
- _ => {
373
- return Err ( error ( cx, LayoutError :: Unknown ( pointee) ) ) ;
374
- }
375
- }
376
- } ;
377
-
378
- // Effectively a (ptr, meta) tuple.
379
- tcx. mk_layout ( cx. scalar_pair ( data_ptr, metadata) )
333
+ // No metadata, this is a thin pointer.
334
+ tcx. mk_layout ( LayoutS :: scalar ( cx, data_ptr) )
335
+ }
380
336
}
381
337
382
338
ty:: Dynamic ( _, _, ty:: DynStar ) => {
@@ -388,16 +344,8 @@ fn layout_of_uncached<'tcx>(
388
344
}
389
345
390
346
// Arrays and slices.
391
- ty:: Array ( element, mut count) => {
392
- if count. has_projections ( ) {
393
- count = tcx. normalize_erasing_regions ( param_env, count) ;
394
- if count. has_projections ( ) {
395
- return Err ( error ( cx, LayoutError :: Unknown ( ty) ) ) ;
396
- }
397
- }
398
-
399
- let count = count
400
- . try_eval_target_usize ( tcx, param_env)
347
+ ty:: Array ( element, count) => {
348
+ let count = compute_array_count ( cx, count)
401
349
. ok_or_else ( || error ( cx, LayoutError :: Unknown ( ty) ) ) ?;
402
350
let element = cx. layout_of ( element) ?;
403
351
let size = element
@@ -733,6 +681,93 @@ fn layout_of_uncached<'tcx>(
733
681
} )
734
682
}
735
683
684
+ fn compute_array_count < ' tcx > (
685
+ cx : & LayoutCx < ' tcx , TyCtxt < ' tcx > > ,
686
+ mut count : ty:: Const < ' tcx > ,
687
+ ) -> Option < u64 > {
688
+ let LayoutCx { tcx, param_env } = * cx;
689
+ if count. has_projections ( ) {
690
+ count = tcx. normalize_erasing_regions ( param_env, count) ;
691
+ if count. has_projections ( ) {
692
+ return None ;
693
+ }
694
+ }
695
+
696
+ count. try_eval_target_usize ( tcx, param_env)
697
+ }
698
+
699
+ fn ptr_metadata_scalar < ' tcx > (
700
+ cx : & LayoutCx < ' tcx , TyCtxt < ' tcx > > ,
701
+ pointee : Ty < ' tcx > ,
702
+ ) -> Result < Option < Scalar > , & ' tcx LayoutError < ' tcx > > {
703
+ let dl = cx. data_layout ( ) ;
704
+ let scalar_unit = |value : Primitive | {
705
+ let size = value. size ( dl) ;
706
+ assert ! ( size. bits( ) <= 128 ) ;
707
+ Scalar :: Initialized { value, valid_range : WrappingRange :: full ( size) }
708
+ } ;
709
+
710
+ let LayoutCx { tcx, param_env } = * cx;
711
+
712
+ let pointee = tcx. normalize_erasing_regions ( param_env, pointee) ;
713
+ if pointee. is_sized ( tcx, param_env) {
714
+ return Ok ( None ) ;
715
+ }
716
+
717
+ if let Some ( metadata_def_id) = tcx. lang_items ( ) . metadata_type ( )
718
+ // Projection eagerly bails out when the pointee references errors,
719
+ // fall back to structurally deducing metadata.
720
+ && !pointee. references_error ( )
721
+ {
722
+ let pointee_metadata = Ty :: new_projection ( tcx, metadata_def_id, [ pointee] ) ;
723
+ let metadata_ty = match tcx. try_normalize_erasing_regions (
724
+ param_env,
725
+ pointee_metadata,
726
+ ) {
727
+ Ok ( metadata_ty) => metadata_ty,
728
+ Err ( mut err) => {
729
+ // Usually `<Ty as Pointee>::Metadata` can't be normalized because
730
+ // its struct tail cannot be normalized either, so try to get a
731
+ // more descriptive layout error here, which will lead to less confusing
732
+ // diagnostics.
733
+ match tcx. try_normalize_erasing_regions (
734
+ param_env,
735
+ tcx. struct_tail_without_normalization ( pointee) ,
736
+ ) {
737
+ Ok ( _) => { } ,
738
+ Err ( better_err) => {
739
+ err = better_err;
740
+ }
741
+ }
742
+ return Err ( error ( cx, LayoutError :: NormalizationFailure ( pointee, err) ) ) ;
743
+ } ,
744
+ } ;
745
+
746
+ let metadata_layout = cx. layout_of ( metadata_ty) ?;
747
+
748
+ if metadata_layout. is_zst ( ) && metadata_layout. align . abi . bytes ( ) == 1 {
749
+ Ok ( None ) // If the metadata is a 1-zst, then the pointer is thin.
750
+ } else if let Abi :: Scalar ( metadata) = metadata_layout. abi {
751
+ Ok ( Some ( metadata) )
752
+ } else {
753
+ Err ( error ( cx, LayoutError :: Unknown ( pointee) ) )
754
+ }
755
+ } else {
756
+ let unsized_part = tcx. struct_tail_erasing_lifetimes ( pointee, param_env) ;
757
+
758
+ match unsized_part. kind ( ) {
759
+ ty:: Foreign ( ..) => Ok ( None ) ,
760
+ ty:: Slice ( _) | ty:: Str => Ok ( Some ( scalar_unit ( Int ( dl. ptr_sized_integer ( ) , false ) ) ) ) ,
761
+ ty:: Dynamic ( ..) => {
762
+ let mut vtable = scalar_unit ( Pointer ( AddressSpace :: DATA ) ) ;
763
+ vtable. valid_range_mut ( ) . start = 1 ;
764
+ Ok ( Some ( vtable) )
765
+ }
766
+ _ => Err ( error ( cx, LayoutError :: Unknown ( pointee) ) ) ,
767
+ }
768
+ }
769
+ }
770
+
736
771
/// Overlap eligibility and variant assignment for each GeneratorSavedLocal.
737
772
#[ derive( Clone , Debug , PartialEq ) ]
738
773
enum SavedLocalEligibility {
0 commit comments