@@ -309,7 +309,8 @@ impl<'tcx> LayoutCalculator for LayoutCx<'tcx, TyCtxt<'tcx>> {
309
309
#[ derive( Copy , Clone , Debug ) ]
310
310
pub enum SizeSkeleton < ' tcx > {
311
311
/// Any statically computable Layout.
312
- Known ( Size ) ,
312
+ /// Alignment can be `None` if unknown.
313
+ Known ( Size , Option < Align > ) ,
313
314
314
315
/// This is a generic const expression (i.e. N * 2), which may contain some parameters.
315
316
/// It must be of type usize, and represents the size of a type in bytes.
@@ -339,7 +340,12 @@ impl<'tcx> SizeSkeleton<'tcx> {
339
340
// First try computing a static layout.
340
341
let err = match tcx. layout_of ( param_env. and ( ty) ) {
341
342
Ok ( layout) => {
342
- return Ok ( SizeSkeleton :: Known ( layout. size ) ) ;
343
+ if layout. abi . is_sized ( ) {
344
+ return Ok ( SizeSkeleton :: Known ( layout. size , Some ( layout. align . abi ) ) ) ;
345
+ } else {
346
+ // Just to be safe, don't claim a known layout for unsized types.
347
+ return Err ( tcx. arena . alloc ( LayoutError :: Unknown ( ty) ) ) ;
348
+ }
343
349
}
344
350
Err ( err @ LayoutError :: Unknown ( _) ) => err,
345
351
// We can't extract SizeSkeleton info from other layout errors
@@ -389,19 +395,20 @@ impl<'tcx> SizeSkeleton<'tcx> {
389
395
ty:: Array ( inner, len) if tcx. features ( ) . transmute_generic_consts => {
390
396
let len_eval = len. try_eval_target_usize ( tcx, param_env) ;
391
397
if len_eval == Some ( 0 ) {
392
- return Ok ( SizeSkeleton :: Known ( Size :: from_bytes ( 0 ) ) ) ;
398
+ return Ok ( SizeSkeleton :: Known ( Size :: from_bytes ( 0 ) , None ) ) ;
393
399
}
394
400
395
401
match SizeSkeleton :: compute ( inner, tcx, param_env) ? {
396
402
// This may succeed because the multiplication of two types may overflow
397
403
// but a single size of a nested array will not.
398
- SizeSkeleton :: Known ( s) => {
404
+ SizeSkeleton :: Known ( s, a ) => {
399
405
if let Some ( c) = len_eval {
400
406
let size = s
401
407
. bytes ( )
402
408
. checked_mul ( c)
403
409
. ok_or_else ( || & * tcx. arena . alloc ( LayoutError :: SizeOverflow ( ty) ) ) ?;
404
- return Ok ( SizeSkeleton :: Known ( Size :: from_bytes ( size) ) ) ;
410
+ // Alignment is unchanged by arrays.
411
+ return Ok ( SizeSkeleton :: Known ( Size :: from_bytes ( size) , a) ) ;
405
412
}
406
413
Err ( tcx. arena . alloc ( LayoutError :: Unknown ( ty) ) )
407
414
}
@@ -427,8 +434,10 @@ impl<'tcx> SizeSkeleton<'tcx> {
427
434
for field in fields {
428
435
let field = field?;
429
436
match field {
430
- SizeSkeleton :: Known ( size) => {
431
- if size. bytes ( ) > 0 {
437
+ SizeSkeleton :: Known ( size, align) => {
438
+ let is_1zst = size. bytes ( ) == 0
439
+ && align. is_some_and ( |align| align. bytes ( ) == 1 ) ;
440
+ if !is_1zst {
432
441
return Err ( err) ;
433
442
}
434
443
}
@@ -492,7 +501,7 @@ impl<'tcx> SizeSkeleton<'tcx> {
492
501
493
502
pub fn same_size ( self , other : SizeSkeleton < ' tcx > ) -> bool {
494
503
match ( self , other) {
495
- ( SizeSkeleton :: Known ( a) , SizeSkeleton :: Known ( b) ) => a == b,
504
+ ( SizeSkeleton :: Known ( a, _ ) , SizeSkeleton :: Known ( b, _ ) ) => a == b,
496
505
( SizeSkeleton :: Pointer { tail : a, .. } , SizeSkeleton :: Pointer { tail : b, .. } ) => {
497
506
a == b
498
507
}
0 commit comments