@@ -729,64 +729,59 @@ pub trait LayoutCalculator {
729
729
align = align. max ( AbiAndPrefAlign :: new ( repr_align) ) ;
730
730
}
731
731
732
- let optimize = !repr. inhibit_union_abi_opt ( ) ;
732
+ let mut optimize = !repr. inhibit_union_abi_opt ( ) ;
733
733
let mut size = Size :: ZERO ;
734
- let mut abi = None ;
735
- let mut biggest_zst_align = align;
736
- let mut biggest_non_zst_align = align;
734
+ let mut common_non_zst_abi_and_align: Option < ( Abi , AbiAndPrefAlign ) > = None ;
737
735
let only_variant = & variants[ FIRST_VARIANT ] ;
738
736
for field in only_variant {
739
- assert ! ( ! field. 0 . is_unsized ( ) ) ;
737
+ assert ! ( field. 0 . is_sized ( ) ) ;
740
738
741
- if optimize {
742
- // If all non-ZST fields have the same ABI, forward this ABI
743
- if field. 0 . is_zst ( ) {
744
- biggest_zst_align = biggest_zst_align. max ( field. align ( ) ) ;
745
- } else {
746
- biggest_non_zst_align = biggest_non_zst_align. max ( field. align ( ) ) ;
747
- // Discard valid range information and allow undef
748
- let field_abi = match field. abi ( ) {
749
- Abi :: Scalar ( x) => Abi :: Scalar ( x. to_union ( ) ) ,
750
- Abi :: ScalarPair ( x, y) => Abi :: ScalarPair ( x. to_union ( ) , y. to_union ( ) ) ,
751
- Abi :: Vector { element : x, count } => {
752
- Abi :: Vector { element : x. to_union ( ) , count }
753
- }
754
- Abi :: Uninhabited | Abi :: Aggregate { .. } => Abi :: Aggregate { sized : true } ,
755
- } ;
739
+ if !field. 0 . is_zst ( ) && optimize {
740
+ // Discard valid range information and allow undef
741
+ let field_abi = field. abi ( ) . to_union ( ) ;
756
742
757
- if let Some ( abi) = & mut abi {
758
- if * abi != field_abi {
759
- // different fields have different ABI: reset to Aggregate
760
- * abi = Abi :: Aggregate { sized : true } ;
761
- }
743
+ if let Some ( ( abi, align) ) = & mut common_non_zst_abi_and_align {
744
+ if * abi != field_abi {
745
+ // Different fields have different ABI: disable opt
746
+ optimize = false ;
762
747
} else {
763
- abi = Some ( field_abi) ;
748
+ // Fields with the same non-Aggregate ABI should also
749
+ // have the same alignment
750
+ if !matches ! ( abi, Abi :: Aggregate { .. } ) {
751
+ assert_eq ! (
752
+ align. abi,
753
+ field. align( ) . abi,
754
+ "non-Aggregate field with matching ABI but differing alignment"
755
+ ) ;
756
+ }
764
757
}
758
+ } else {
759
+ common_non_zst_abi_and_align = Some ( ( field_abi, field. align ( ) ) ) ;
765
760
}
766
761
}
767
762
768
763
align = align. max ( field. align ( ) ) ;
769
764
size = cmp:: max ( size, field. size ( ) ) ;
770
765
}
771
766
772
- let abi = match abi {
773
- None => Abi :: Aggregate { sized : true } ,
774
- Some ( non_zst_abi) => {
775
- if biggest_zst_align. abi > biggest_non_zst_align. abi {
776
- // If a zst has a bigger alignment than the non-zst fields,
777
- // we cannot use scalar layout, because scalar(pair)s can't be
778
- // more aligned than their primitive.
767
+ if let Some ( pack) = repr. pack {
768
+ align = align. min ( AbiAndPrefAlign :: new ( pack) ) ;
769
+ }
770
+
771
+ // If all non-ZST fields have the same ABI, we may forward that ABI
772
+ // for the union as a whole, unless otherwise inhibited.
773
+ let abi = match ( optimize, common_non_zst_abi_and_align) {
774
+ ( false , _) | ( _, None ) => Abi :: Aggregate { sized : true } ,
775
+ ( true , Some ( ( abi, _) ) ) => {
776
+ if abi. inherent_align ( dl) . map ( |a| a. abi ) != Some ( align. abi ) {
777
+ // Mismatched alignment: disable opt
779
778
Abi :: Aggregate { sized : true }
780
779
} else {
781
- non_zst_abi
780
+ abi
782
781
}
783
782
}
784
783
} ;
785
784
786
- if let Some ( pack) = repr. pack {
787
- align = align. min ( AbiAndPrefAlign :: new ( pack) ) ;
788
- }
789
-
790
785
Some ( LayoutS {
791
786
variants : Variants :: Single { index : FIRST_VARIANT } ,
792
787
fields : FieldsShape :: Union ( NonZeroUsize :: new ( only_variant. len ( ) ) ?) ,
0 commit comments