make no-variant types a dedicated Variants variant
This commit is contained in:
parent
21de42bf8d
commit
e023590de4
53 changed files with 246 additions and 495 deletions
|
@ -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)
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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,
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue