@@ -130,6 +130,7 @@ impl<Cx: HasDataLayout> LayoutCalculator<Cx> {
130
130
} ,
131
131
backend_repr : BackendRepr :: ScalarPair ( a, b) ,
132
132
largest_niche,
133
+ uninhabited : false ,
133
134
align,
134
135
size,
135
136
max_repr_align : None ,
@@ -221,8 +222,9 @@ impl<Cx: HasDataLayout> LayoutCalculator<Cx> {
221
222
LayoutData {
222
223
variants : Variants :: Empty ,
223
224
fields : FieldsShape :: Primitive ,
224
- backend_repr : BackendRepr :: Uninhabited ,
225
+ backend_repr : BackendRepr :: Memory { sized : true } ,
225
226
largest_niche : None ,
227
+ uninhabited : true ,
226
228
align : dl. i8_align ,
227
229
size : Size :: ZERO ,
228
230
max_repr_align : None ,
@@ -308,10 +310,10 @@ impl<Cx: HasDataLayout> LayoutCalculator<Cx> {
308
310
let mut align = if repr. pack . is_some ( ) { dl. i8_align } else { dl. aggregate_align } ;
309
311
let mut max_repr_align = repr. align ;
310
312
311
- // If all the non-ZST fields have the same ABI and union ABI optimizations aren't
312
- // disabled, we can use that common ABI for the union as a whole.
313
+ // If all the non-ZST fields have the same repr and union repr optimizations aren't
314
+ // disabled, we can use that common repr for the union as a whole.
313
315
struct AbiMismatch ;
314
- let mut common_non_zst_abi_and_align = if repr. inhibits_union_abi_opt ( ) {
316
+ let mut common_non_zst_repr_and_align = if repr. inhibits_union_abi_opt ( ) {
315
317
// Can't optimize
316
318
Err ( AbiMismatch )
317
319
} else {
@@ -335,14 +337,14 @@ impl<Cx: HasDataLayout> LayoutCalculator<Cx> {
335
337
continue ;
336
338
}
337
339
338
- if let Ok ( common) = common_non_zst_abi_and_align {
340
+ if let Ok ( common) = common_non_zst_repr_and_align {
339
341
// Discard valid range information and allow undef
340
342
let field_abi = field. backend_repr . to_union ( ) ;
341
343
342
344
if let Some ( ( common_abi, common_align) ) = common {
343
345
if common_abi != field_abi {
344
346
// Different fields have different ABI: disable opt
345
- common_non_zst_abi_and_align = Err ( AbiMismatch ) ;
347
+ common_non_zst_repr_and_align = Err ( AbiMismatch ) ;
346
348
} else {
347
349
// Fields with the same non-Aggregate ABI should also
348
350
// have the same alignment
@@ -355,7 +357,7 @@ impl<Cx: HasDataLayout> LayoutCalculator<Cx> {
355
357
}
356
358
} else {
357
359
// First non-ZST field: record its ABI and alignment
358
- common_non_zst_abi_and_align = Ok ( Some ( ( field_abi, field. align . abi ) ) ) ;
360
+ common_non_zst_repr_and_align = Ok ( Some ( ( field_abi, field. align . abi ) ) ) ;
359
361
}
360
362
}
361
363
}
@@ -374,16 +376,25 @@ impl<Cx: HasDataLayout> LayoutCalculator<Cx> {
374
376
375
377
// If all non-ZST fields have the same ABI, we may forward that ABI
376
378
// for the union as a whole, unless otherwise inhibited.
377
- let abi = match common_non_zst_abi_and_align {
379
+ let backend_repr = match common_non_zst_repr_and_align {
378
380
Err ( AbiMismatch ) | Ok ( None ) => BackendRepr :: Memory { sized : true } ,
379
- Ok ( Some ( ( abi, _) ) ) => {
380
- if abi. inherent_align ( dl) . map ( |a| a. abi ) != Some ( align. abi ) {
381
- // Mismatched alignment (e.g. union is #[repr(packed)]): disable opt
381
+ Ok ( Some ( ( repr, _) ) ) => match repr {
382
+ // Mismatched alignment (e.g. union is #[repr(packed)]): disable opt
383
+ BackendRepr :: Scalar ( _) | BackendRepr :: ScalarPair ( _, _)
384
+ if repr. scalar_align ( dl) . unwrap ( ) != align. abi =>
385
+ {
382
386
BackendRepr :: Memory { sized : true }
383
- } else {
384
- abi
385
387
}
386
- }
388
+ // Vectors require at least element alignment, else disable the opt
389
+ BackendRepr :: Vector { element, count : _ } if element. align ( dl) . abi > align. abi => {
390
+ BackendRepr :: Memory { sized : true }
391
+ }
392
+ // the alignment tests passed and we can use this
393
+ BackendRepr :: Scalar ( ..)
394
+ | BackendRepr :: ScalarPair ( ..)
395
+ | BackendRepr :: Vector { .. }
396
+ | BackendRepr :: Memory { .. } => repr,
397
+ } ,
387
398
} ;
388
399
389
400
let Some ( union_field_count) = NonZeroUsize :: new ( only_variant. len ( ) ) else {
@@ -398,8 +409,9 @@ impl<Cx: HasDataLayout> LayoutCalculator<Cx> {
398
409
Ok ( LayoutData {
399
410
variants : Variants :: Single { index : only_variant_idx } ,
400
411
fields : FieldsShape :: Union ( union_field_count) ,
401
- backend_repr : abi ,
412
+ backend_repr,
402
413
largest_niche : None ,
414
+ uninhabited : false ,
403
415
align,
404
416
size : size. align_to ( align. abi ) ,
405
417
max_repr_align,
@@ -447,7 +459,6 @@ impl<Cx: HasDataLayout> LayoutCalculator<Cx> {
447
459
Scalar :: Union { .. } => { }
448
460
} ;
449
461
match & mut st. backend_repr {
450
- BackendRepr :: Uninhabited => { }
451
462
BackendRepr :: Scalar ( scalar) => hide_niches ( scalar) ,
452
463
BackendRepr :: ScalarPair ( a, b) => {
453
464
hide_niches ( a) ;
@@ -639,9 +650,8 @@ impl<Cx: HasDataLayout> LayoutCalculator<Cx> {
639
650
let same_size = size == variant_layouts[ largest_variant_index] . size ;
640
651
let same_align = align == variant_layouts[ largest_variant_index] . align ;
641
652
642
- let abi = if variant_layouts. iter ( ) . all ( |v| v. is_uninhabited ( ) ) {
643
- BackendRepr :: Uninhabited
644
- } else if same_size && same_align && others_zst {
653
+ let uninhabited = variant_layouts. iter ( ) . all ( |v| v. is_uninhabited ( ) ) ;
654
+ let abi = if same_size && same_align && others_zst {
645
655
match variant_layouts[ largest_variant_index] . backend_repr {
646
656
// When the total alignment and size match, we can use the
647
657
// same ABI as the scalar variant with the reserved niche.
@@ -683,6 +693,7 @@ impl<Cx: HasDataLayout> LayoutCalculator<Cx> {
683
693
} ,
684
694
backend_repr : abi,
685
695
largest_niche,
696
+ uninhabited,
686
697
size,
687
698
align,
688
699
max_repr_align,
@@ -853,9 +864,8 @@ impl<Cx: HasDataLayout> LayoutCalculator<Cx> {
853
864
} ;
854
865
let mut abi = BackendRepr :: Memory { sized : true } ;
855
866
856
- if layout_variants. iter ( ) . all ( |v| v. is_uninhabited ( ) ) {
857
- abi = BackendRepr :: Uninhabited ;
858
- } else if tag. size ( dl) == size {
867
+ let uninhabited = layout_variants. iter ( ) . all ( |v| v. is_uninhabited ( ) ) ;
868
+ if tag. size ( dl) == size {
859
869
// Make sure we only use scalar layout when the enum is entirely its
860
870
// own tag (i.e. it has no padding nor any non-ZST variant fields).
861
871
abi = BackendRepr :: Scalar ( tag) ;
@@ -995,6 +1005,7 @@ impl<Cx: HasDataLayout> LayoutCalculator<Cx> {
995
1005
memory_index : [ 0 ] . into ( ) ,
996
1006
} ,
997
1007
largest_niche,
1008
+ uninhabited,
998
1009
backend_repr : abi,
999
1010
align,
1000
1011
size,
@@ -1355,9 +1366,7 @@ impl<Cx: HasDataLayout> LayoutCalculator<Cx> {
1355
1366
_ => { }
1356
1367
}
1357
1368
}
1358
- if fields. iter ( ) . any ( |f| f. is_uninhabited ( ) ) {
1359
- abi = BackendRepr :: Uninhabited ;
1360
- }
1369
+ let uninhabited = fields. iter ( ) . any ( |f| f. is_uninhabited ( ) ) ;
1361
1370
1362
1371
let unadjusted_abi_align = if repr. transparent ( ) {
1363
1372
match layout_of_single_non_zst_field {
@@ -1378,6 +1387,7 @@ impl<Cx: HasDataLayout> LayoutCalculator<Cx> {
1378
1387
fields : FieldsShape :: Arbitrary { offsets, memory_index } ,
1379
1388
backend_repr : abi,
1380
1389
largest_niche,
1390
+ uninhabited,
1381
1391
align,
1382
1392
size,
1383
1393
max_repr_align,
0 commit comments