@@ -310,10 +310,10 @@ impl<Cx: HasDataLayout> LayoutCalculator<Cx> {
310
310
let mut align = if repr. pack . is_some ( ) { dl. i8_align } else { dl. aggregate_align } ;
311
311
let mut max_repr_align = repr. align ;
312
312
313
- // If all the non-ZST fields have the same ABI and union ABI optimizations aren't
314
- // 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.
315
315
struct AbiMismatch ;
316
- 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 ( ) {
317
317
// Can't optimize
318
318
Err ( AbiMismatch )
319
319
} else {
@@ -337,14 +337,14 @@ impl<Cx: HasDataLayout> LayoutCalculator<Cx> {
337
337
continue ;
338
338
}
339
339
340
- if let Ok ( common) = common_non_zst_abi_and_align {
340
+ if let Ok ( common) = common_non_zst_repr_and_align {
341
341
// Discard valid range information and allow undef
342
342
let field_abi = field. backend_repr . to_union ( ) ;
343
343
344
344
if let Some ( ( common_abi, common_align) ) = common {
345
345
if common_abi != field_abi {
346
346
// Different fields have different ABI: disable opt
347
- common_non_zst_abi_and_align = Err ( AbiMismatch ) ;
347
+ common_non_zst_repr_and_align = Err ( AbiMismatch ) ;
348
348
} else {
349
349
// Fields with the same non-Aggregate ABI should also
350
350
// have the same alignment
@@ -357,7 +357,7 @@ impl<Cx: HasDataLayout> LayoutCalculator<Cx> {
357
357
}
358
358
} else {
359
359
// First non-ZST field: record its ABI and alignment
360
- 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 ) ) ) ;
361
361
}
362
362
}
363
363
}
@@ -376,16 +376,25 @@ impl<Cx: HasDataLayout> LayoutCalculator<Cx> {
376
376
377
377
// If all non-ZST fields have the same ABI, we may forward that ABI
378
378
// for the union as a whole, unless otherwise inhibited.
379
- let abi = match common_non_zst_abi_and_align {
379
+ let backend_repr = match common_non_zst_repr_and_align {
380
380
Err ( AbiMismatch ) | Ok ( None ) => BackendRepr :: Memory { sized : true } ,
381
- Ok ( Some ( ( abi, _) ) ) => {
382
- if abi. inherent_align ( dl) . map ( |a| a. abi ) != Some ( align. abi ) {
383
- // 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
+ {
384
386
BackendRepr :: Memory { sized : true }
385
- } else {
386
- abi
387
387
}
388
- }
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
+ } ,
389
398
} ;
390
399
391
400
let Some ( union_field_count) = NonZeroUsize :: new ( only_variant. len ( ) ) else {
@@ -400,7 +409,7 @@ impl<Cx: HasDataLayout> LayoutCalculator<Cx> {
400
409
Ok ( LayoutData {
401
410
variants : Variants :: Single { index : only_variant_idx } ,
402
411
fields : FieldsShape :: Union ( union_field_count) ,
403
- backend_repr : abi ,
412
+ backend_repr,
404
413
largest_niche : None ,
405
414
uninhabited : false ,
406
415
align,
0 commit comments