1
Fork 0

Rollup merge of #133702 - RalfJung:single-variant, r=oli-obk

Variants::Single: do not use invalid VariantIdx for uninhabited enums

~~Stacked on top of https://github.com/rust-lang/rust/pull/133681, only the last commit is new.~~

Currently, `Variants::Single` for an empty enum contains a `VariantIdx` of 0; looking that up in the enum variant list will ICE. That's quite confusing. So let's fix that by adding a new `Variants::Empty` case for types that have 0 variants.

try-job: i686-msvc
This commit is contained in:
许杰友 Jieyou Xu (Joe) 2024-12-19 16:48:07 +08:00 committed by GitHub
commit 2a43ce03fb
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
33 changed files with 186 additions and 165 deletions

View file

@ -392,7 +392,7 @@ pub enum UndefinedBehaviorInfo<'tcx> {
/// A discriminant of an uninhabited enum variant is written.
UninhabitedEnumVariantWritten(VariantIdx),
/// An uninhabited enum variant is projected.
UninhabitedEnumVariantRead(VariantIdx),
UninhabitedEnumVariantRead(Option<VariantIdx>),
/// Trying to set discriminant to the niched variant, but the value does not match.
InvalidNichedEnumVariantWritten { enum_ty: Ty<'tcx> },
/// ABI-incompatible argument types.

View file

@ -734,21 +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 == 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 } => {
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() {
@ -902,6 +903,7 @@ 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)
@ -927,6 +929,7 @@ where
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, .. } => {