Skip to content

Commit 4f4f22b

Browse files
committed
Incorporate review feedback from 103926.
1 parent a380053 commit 4f4f22b

File tree

1 file changed

+33
-38
lines changed

1 file changed

+33
-38
lines changed

compiler/rustc_abi/src/layout.rs

Lines changed: 33 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -729,64 +729,59 @@ pub trait LayoutCalculator {
729729
align = align.max(AbiAndPrefAlign::new(repr_align));
730730
}
731731

732-
let optimize = !repr.inhibit_union_abi_opt();
732+
let mut optimize = !repr.inhibit_union_abi_opt();
733733
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;
737735
let only_variant = &variants[FIRST_VARIANT];
738736
for field in only_variant {
739-
assert!(!field.0.is_unsized());
737+
assert!(field.0.is_sized());
740738

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();
756742

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;
762747
} 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+
}
764757
}
758+
} else {
759+
common_non_zst_abi_and_align = Some((field_abi, field.align()));
765760
}
766761
}
767762

768763
align = align.max(field.align());
769764
size = cmp::max(size, field.size());
770765
}
771766

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
779778
Abi::Aggregate { sized: true }
780779
} else {
781-
non_zst_abi
780+
abi
782781
}
783782
}
784783
};
785784

786-
if let Some(pack) = repr.pack {
787-
align = align.min(AbiAndPrefAlign::new(pack));
788-
}
789-
790785
Some(LayoutS {
791786
variants: Variants::Single { index: FIRST_VARIANT },
792787
fields: FieldsShape::Union(NonZeroUsize::new(only_variant.len())?),

0 commit comments

Comments
 (0)