1
Fork 0

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

@ -734,23 +734,22 @@ where
let layout = match this.variants {
Variants::Single { index }
// If all variants but one are uninhabited, the variant layout is the enum layout.
if index == Some(variant_index) &&
// Don't confuse variants of uninhabited enums with the enum itself.
// For more details see https://github.com/rust-lang/rust/issues/69763.
this.fields != FieldsShape::Primitive =>
if index == variant_index =>
{
this.layout
}
Variants::Single { index } => {
// `Single` variant enums *can* have other variants, but those are uninhabited.
Variants::Single { .. } | Variants::Empty => {
// Single-variant and no-variant enums *can* have other variants, but those are
// uninhabited. Produce a layout that has the right fields for that variant, so that
// the rest of the compiler can project fields etc as usual.
let tcx = cx.tcx();
let typing_env = cx.typing_env();
// Deny calling for_variant more than once for non-Single enums.
if let Ok(original_layout) = tcx.layout_of(typing_env.as_query_input(this.ty)) {
assert_eq!(original_layout.variants, Variants::Single { index });
assert_eq!(original_layout.variants, this.variants);
}
let fields = match this.ty.kind() {
@ -760,7 +759,7 @@ where
_ => bug!("`ty_and_layout_for_variant` on unexpected type {}", this.ty),
};
tcx.mk_layout(LayoutData {
variants: Variants::Single { index: Some(variant_index) },
variants: Variants::Single { index: variant_index },
fields: match NonZero::new(fields) {
Some(fields) => FieldsShape::Union(fields),
None => FieldsShape::Arbitrary { offsets: IndexVec::new(), memory_index: IndexVec::new() },
@ -777,7 +776,7 @@ where
Variants::Multiple { ref variants, .. } => cx.tcx().mk_layout(variants[variant_index].clone()),
};
assert_eq!(*layout.variants(), Variants::Single { index: Some(variant_index) });
assert_eq!(*layout.variants(), Variants::Single { index: variant_index });
TyAndLayout { ty: this.ty, layout }
}
@ -904,10 +903,11 @@ where
),
ty::Coroutine(def_id, args) => match this.variants {
Variants::Empty => unreachable!(),
Variants::Single { index } => TyMaybeWithLayout::Ty(
args.as_coroutine()
.state_tys(def_id, tcx)
.nth(index.unwrap().as_usize())
.nth(index.as_usize())
.unwrap()
.nth(i)
.unwrap(),
@ -926,10 +926,10 @@ where
ty::Adt(def, args) => {
match this.variants {
Variants::Single { index } => {
let field =
&def.variant(index.unwrap()).fields[FieldIdx::from_usize(i)];
let field = &def.variant(index).fields[FieldIdx::from_usize(i)];
TyMaybeWithLayout::Ty(field.ty(tcx, args))
}
Variants::Empty => panic!("there is no field in Variants::Empty types"),
// Discriminant field for enums (where applicable).
Variants::Multiple { tag, .. } => {