make no-variant types a dedicated Variants variant

This commit is contained in:
Ralf Jung 2024-12-01 17:33:01 +01:00
parent 21de42bf8d
commit e023590de4
53 changed files with 246 additions and 495 deletions

View file

@ -206,7 +206,7 @@ impl<'a, Ty> TyAndLayout<'a, Ty> {
let (mut result, mut total) = from_fields_at(*self, Size::ZERO)?;
match &self.variants {
abi::Variants::Single { .. } => {}
abi::Variants::Single { .. } | abi::Variants::Empty => {}
abi::Variants::Multiple { variants, .. } => {
// Treat enum variants like union members.
// HACK(eddyb) pretend the `enum` field (discriminant)

View file

@ -120,7 +120,7 @@ impl<Cx: HasDataLayout> LayoutCalculator<Cx> {
.max_by_key(|niche| niche.available(dl));
LayoutData {
variants: Variants::Single { index: Some(VariantIdx::new(0)) },
variants: Variants::Single { index: VariantIdx::new(0) },
fields: FieldsShape::Arbitrary {
offsets: [Size::ZERO, b_offset].into(),
memory_index: [0, 1].into(),
@ -213,8 +213,9 @@ impl<Cx: HasDataLayout> LayoutCalculator<Cx> {
&self,
) -> LayoutData<FieldIdx, VariantIdx> {
let dl = self.cx.data_layout();
// This is also used for uninhabited enums, so we use `Variants::Empty`.
LayoutData {
variants: Variants::Single { index: None },
variants: Variants::Empty,
fields: FieldsShape::Primitive,
backend_repr: BackendRepr::Uninhabited,
largest_niche: None,
@ -385,7 +386,7 @@ impl<Cx: HasDataLayout> LayoutCalculator<Cx> {
};
Ok(LayoutData {
variants: Variants::Single { index: Some(only_variant_idx) },
variants: Variants::Single { index: only_variant_idx },
fields: FieldsShape::Union(union_field_count),
backend_repr: abi,
largest_niche: None,
@ -424,7 +425,7 @@ impl<Cx: HasDataLayout> LayoutCalculator<Cx> {
};
let mut st = self.univariant(&variants[v], repr, kind)?;
st.variants = Variants::Single { index: Some(v) };
st.variants = Variants::Single { index: v };
if is_unsafe_cell {
let hide_niches = |scalar: &mut _| match scalar {
@ -543,7 +544,7 @@ impl<Cx: HasDataLayout> LayoutCalculator<Cx> {
.iter_enumerated()
.map(|(j, v)| {
let mut st = self.univariant(v, repr, StructKind::AlwaysSized).ok()?;
st.variants = Variants::Single { index: Some(j) };
st.variants = Variants::Single { index: j };
align = align.max(st.align);
max_repr_align = max_repr_align.max(st.max_repr_align);
@ -736,7 +737,7 @@ impl<Cx: HasDataLayout> LayoutCalculator<Cx> {
repr,
StructKind::Prefixed(min_ity.size(), prefix_align),
)?;
st.variants = Variants::Single { index: Some(i) };
st.variants = Variants::Single { index: i };
// Find the first field we can't move later
// to make room for a larger discriminant.
for field_idx in st.fields.index_by_increasing_offset() {
@ -1004,8 +1005,8 @@ impl<Cx: HasDataLayout> LayoutCalculator<Cx> {
Variants::Multiple { tag, tag_encoding, tag_field, .. } => {
Variants::Multiple { tag, tag_encoding, tag_field, variants: best_layout.variants }
}
Variants::Single { .. } => {
panic!("encountered a single-variant enum during multi-variant layout")
Variants::Single { .. } | Variants::Empty => {
panic!("encountered a single-variant or empty enum during multi-variant layout")
}
};
Ok(best_layout.layout)
@ -1344,7 +1345,7 @@ impl<Cx: HasDataLayout> LayoutCalculator<Cx> {
};
Ok(LayoutData {
variants: Variants::Single { index: Some(VariantIdx::new(0)) },
variants: Variants::Single { index: VariantIdx::new(0) },
fields: FieldsShape::Arbitrary { offsets, memory_index },
backend_repr: abi,
largest_niche,

View file

@ -1504,11 +1504,13 @@ impl BackendRepr {
#[derive(PartialEq, Eq, Hash, Clone, Debug)]
#[cfg_attr(feature = "nightly", derive(HashStable_Generic))]
pub enum Variants<FieldIdx: Idx, VariantIdx: Idx> {
/// A type with no valid variants. Must be uninhabited.
Empty,
/// Single enum variants, structs/tuples, unions, and all non-ADTs.
Single {
/// Always `Some(0)` for types without variants (i.e., everything except for `!`, enums, and
/// generators). `None` indicates an uninhabited type; this is used for zero-variant enums.
index: Option<VariantIdx>,
/// Always `0` for types that cannot have multiple variants.
index: VariantIdx,
},
/// Enum-likes with more than one variant: each variant comes with
@ -1706,7 +1708,7 @@ impl<FieldIdx: Idx, VariantIdx: Idx> LayoutData<FieldIdx, VariantIdx> {
let size = scalar.size(cx);
let align = scalar.align(cx);
LayoutData {
variants: Variants::Single { index: Some(VariantIdx::new(0)) },
variants: Variants::Single { index: VariantIdx::new(0) },
fields: FieldsShape::Primitive,
backend_repr: BackendRepr::Scalar(scalar),
largest_niche,