@@ -130,6 +130,7 @@ impl<Cx: HasDataLayout> LayoutCalculator<Cx> {
130130 } ,
131131 backend_repr : BackendRepr :: ScalarPair ( a, b) ,
132132 largest_niche,
133+ uninhabited : false ,
133134 align,
134135 size,
135136 max_repr_align : None ,
@@ -221,8 +222,9 @@ impl<Cx: HasDataLayout> LayoutCalculator<Cx> {
221222 LayoutData {
222223 variants : Variants :: Empty ,
223224 fields : FieldsShape :: Primitive ,
224- backend_repr : BackendRepr :: Uninhabited ,
225+ backend_repr : BackendRepr :: Memory { sized : true } ,
225226 largest_niche : None ,
227+ uninhabited : true ,
226228 align : dl. i8_align ,
227229 size : Size :: ZERO ,
228230 max_repr_align : None ,
@@ -308,10 +310,10 @@ impl<Cx: HasDataLayout> LayoutCalculator<Cx> {
308310 let mut align = if repr. pack . is_some ( ) { dl. i8_align } else { dl. aggregate_align } ;
309311 let mut max_repr_align = repr. align ;
310312
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.
313315 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 ( ) {
315317 // Can't optimize
316318 Err ( AbiMismatch )
317319 } else {
@@ -335,14 +337,14 @@ impl<Cx: HasDataLayout> LayoutCalculator<Cx> {
335337 continue ;
336338 }
337339
338- if let Ok ( common) = common_non_zst_abi_and_align {
340+ if let Ok ( common) = common_non_zst_repr_and_align {
339341 // Discard valid range information and allow undef
340342 let field_abi = field. backend_repr . to_union ( ) ;
341343
342344 if let Some ( ( common_abi, common_align) ) = common {
343345 if common_abi != field_abi {
344346 // 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 ) ;
346348 } else {
347349 // Fields with the same non-Aggregate ABI should also
348350 // have the same alignment
@@ -355,7 +357,7 @@ impl<Cx: HasDataLayout> LayoutCalculator<Cx> {
355357 }
356358 } else {
357359 // 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 ) ) ) ;
359361 }
360362 }
361363 }
@@ -374,16 +376,25 @@ impl<Cx: HasDataLayout> LayoutCalculator<Cx> {
374376
375377 // If all non-ZST fields have the same ABI, we may forward that ABI
376378 // 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 {
378380 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+ {
382386 BackendRepr :: Memory { sized : true }
383- } else {
384- abi
385387 }
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+ } ,
387398 } ;
388399
389400 let Some ( union_field_count) = NonZeroUsize :: new ( only_variant. len ( ) ) else {
@@ -398,8 +409,9 @@ impl<Cx: HasDataLayout> LayoutCalculator<Cx> {
398409 Ok ( LayoutData {
399410 variants : Variants :: Single { index : only_variant_idx } ,
400411 fields : FieldsShape :: Union ( union_field_count) ,
401- backend_repr : abi ,
412+ backend_repr,
402413 largest_niche : None ,
414+ uninhabited : false ,
403415 align,
404416 size : size. align_to ( align. abi ) ,
405417 max_repr_align,
@@ -447,7 +459,6 @@ impl<Cx: HasDataLayout> LayoutCalculator<Cx> {
447459 Scalar :: Union { .. } => { }
448460 } ;
449461 match & mut st. backend_repr {
450- BackendRepr :: Uninhabited => { }
451462 BackendRepr :: Scalar ( scalar) => hide_niches ( scalar) ,
452463 BackendRepr :: ScalarPair ( a, b) => {
453464 hide_niches ( a) ;
@@ -639,9 +650,8 @@ impl<Cx: HasDataLayout> LayoutCalculator<Cx> {
639650 let same_size = size == variant_layouts[ largest_variant_index] . size ;
640651 let same_align = align == variant_layouts[ largest_variant_index] . align ;
641652
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 {
645655 match variant_layouts[ largest_variant_index] . backend_repr {
646656 // When the total alignment and size match, we can use the
647657 // same ABI as the scalar variant with the reserved niche.
@@ -683,6 +693,7 @@ impl<Cx: HasDataLayout> LayoutCalculator<Cx> {
683693 } ,
684694 backend_repr : abi,
685695 largest_niche,
696+ uninhabited,
686697 size,
687698 align,
688699 max_repr_align,
@@ -853,9 +864,8 @@ impl<Cx: HasDataLayout> LayoutCalculator<Cx> {
853864 } ;
854865 let mut abi = BackendRepr :: Memory { sized : true } ;
855866
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 {
859869 // Make sure we only use scalar layout when the enum is entirely its
860870 // own tag (i.e. it has no padding nor any non-ZST variant fields).
861871 abi = BackendRepr :: Scalar ( tag) ;
@@ -995,6 +1005,7 @@ impl<Cx: HasDataLayout> LayoutCalculator<Cx> {
9951005 memory_index : [ 0 ] . into ( ) ,
9961006 } ,
9971007 largest_niche,
1008+ uninhabited,
9981009 backend_repr : abi,
9991010 align,
10001011 size,
@@ -1355,9 +1366,7 @@ impl<Cx: HasDataLayout> LayoutCalculator<Cx> {
13551366 _ => { }
13561367 }
13571368 }
1358- if fields. iter ( ) . any ( |f| f. is_uninhabited ( ) ) {
1359- abi = BackendRepr :: Uninhabited ;
1360- }
1369+ let uninhabited = fields. iter ( ) . any ( |f| f. is_uninhabited ( ) ) ;
13611370
13621371 let unadjusted_abi_align = if repr. transparent ( ) {
13631372 match layout_of_single_non_zst_field {
@@ -1378,6 +1387,7 @@ impl<Cx: HasDataLayout> LayoutCalculator<Cx> {
13781387 fields : FieldsShape :: Arbitrary { offsets, memory_index } ,
13791388 backend_repr : abi,
13801389 largest_niche,
1390+ uninhabited,
13811391 align,
13821392 size,
13831393 max_repr_align,
0 commit comments