@@ -310,10 +310,10 @@ impl<Cx: HasDataLayout> LayoutCalculator<Cx> {
310310 let mut align = if repr. pack . is_some ( ) { dl. i8_align } else { dl. aggregate_align } ;
311311 let mut max_repr_align = repr. align ;
312312
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.
315315 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 ( ) {
317317 // Can't optimize
318318 Err ( AbiMismatch )
319319 } else {
@@ -337,14 +337,14 @@ impl<Cx: HasDataLayout> LayoutCalculator<Cx> {
337337 continue ;
338338 }
339339
340- if let Ok ( common) = common_non_zst_abi_and_align {
340+ if let Ok ( common) = common_non_zst_repr_and_align {
341341 // Discard valid range information and allow undef
342342 let field_abi = field. backend_repr . to_union ( ) ;
343343
344344 if let Some ( ( common_abi, common_align) ) = common {
345345 if common_abi != field_abi {
346346 // 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 ) ;
348348 } else {
349349 // Fields with the same non-Aggregate ABI should also
350350 // have the same alignment
@@ -357,7 +357,7 @@ impl<Cx: HasDataLayout> LayoutCalculator<Cx> {
357357 }
358358 } else {
359359 // 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 ) ) ) ;
361361 }
362362 }
363363 }
@@ -376,16 +376,25 @@ impl<Cx: HasDataLayout> LayoutCalculator<Cx> {
376376
377377 // If all non-ZST fields have the same ABI, we may forward that ABI
378378 // 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 {
380380 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+ {
384386 BackendRepr :: Memory { sized : true }
385- } else {
386- abi
387387 }
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+ } ,
389398 } ;
390399
391400 let Some ( union_field_count) = NonZeroUsize :: new ( only_variant. len ( ) ) else {
@@ -400,7 +409,7 @@ impl<Cx: HasDataLayout> LayoutCalculator<Cx> {
400409 Ok ( LayoutData {
401410 variants : Variants :: Single { index : only_variant_idx } ,
402411 fields : FieldsShape :: Union ( union_field_count) ,
403- backend_repr : abi ,
412+ backend_repr,
404413 largest_niche : None ,
405414 uninhabited : false ,
406415 align,
0 commit comments