Skip to content

Commit d97ab9d

Browse files
authored
Rollup merge of rust-lang#133702 - RalfJung:single-variant, r=oli-obk
Variants::Single: do not use invalid VariantIdx for uninhabited enums ~~Stacked on top of rust-lang#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.
2 parents 37e7459 + 397ae3c commit d97ab9d

File tree

33 files changed

+185
-164
lines changed

33 files changed

+185
-164
lines changed

compiler/rustc_abi/src/callconv.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -206,7 +206,7 @@ impl<'a, Ty> TyAndLayout<'a, Ty> {
206206
let (mut result, mut total) = from_fields_at(*self, Size::ZERO)?;
207207

208208
match &self.variants {
209-
abi::Variants::Single { .. } => {}
209+
abi::Variants::Single { .. } | abi::Variants::Empty => {}
210210
abi::Variants::Multiple { variants, .. } => {
211211
// Treat enum variants like union members.
212212
// HACK(eddyb) pretend the `enum` field (discriminant)

compiler/rustc_abi/src/layout.rs

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -213,8 +213,9 @@ impl<Cx: HasDataLayout> LayoutCalculator<Cx> {
213213
&self,
214214
) -> LayoutData<FieldIdx, VariantIdx> {
215215
let dl = self.cx.data_layout();
216+
// This is also used for uninhabited enums, so we use `Variants::Empty`.
216217
LayoutData {
217-
variants: Variants::Single { index: VariantIdx::new(0) },
218+
variants: Variants::Empty,
218219
fields: FieldsShape::Primitive,
219220
backend_repr: BackendRepr::Uninhabited,
220221
largest_niche: None,
@@ -1004,8 +1005,8 @@ impl<Cx: HasDataLayout> LayoutCalculator<Cx> {
10041005
Variants::Multiple { tag, tag_encoding, tag_field, .. } => {
10051006
Variants::Multiple { tag, tag_encoding, tag_field, variants: best_layout.variants }
10061007
}
1007-
Variants::Single { .. } => {
1008-
panic!("encountered a single-variant enum during multi-variant layout")
1008+
Variants::Single { .. } | Variants::Empty => {
1009+
panic!("encountered a single-variant or empty enum during multi-variant layout")
10091010
}
10101011
};
10111012
Ok(best_layout.layout)

compiler/rustc_abi/src/lib.rs

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1504,10 +1504,12 @@ impl BackendRepr {
15041504
#[derive(PartialEq, Eq, Hash, Clone, Debug)]
15051505
#[cfg_attr(feature = "nightly", derive(HashStable_Generic))]
15061506
pub enum Variants<FieldIdx: Idx, VariantIdx: Idx> {
1507+
/// A type with no valid variants. Must be uninhabited.
1508+
Empty,
1509+
15071510
/// Single enum variants, structs/tuples, unions, and all non-ADTs.
15081511
Single {
1509-
/// Always 0 for non-enums/generators.
1510-
/// For enums without a variant, this is an invalid index!
1512+
/// Always `0` for types that cannot have multiple variants.
15111513
index: VariantIdx,
15121514
},
15131515

compiler/rustc_codegen_cranelift/src/discriminant.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ pub(crate) fn codegen_set_discriminant<'tcx>(
1818
return;
1919
}
2020
match layout.variants {
21+
Variants::Empty => unreachable!("we already handled uninhabited types"),
2122
Variants::Single { index } => {
2223
assert_eq!(index, variant_index);
2324
}
@@ -85,6 +86,7 @@ pub(crate) fn codegen_get_discriminant<'tcx>(
8586
}
8687

8788
let (tag_scalar, tag_field, tag_encoding) = match &layout.variants {
89+
Variants::Empty => unreachable!("we already handled uninhabited types"),
8890
Variants::Single { index } => {
8991
let discr_val = layout
9092
.ty

compiler/rustc_codegen_llvm/src/debuginfo/metadata/enums/cpp_like.rs

Lines changed: 11 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -212,21 +212,17 @@ pub(super) fn build_enum_type_di_node<'ll, 'tcx>(
212212
),
213213
|cx, enum_type_di_node| {
214214
match enum_type_and_layout.variants {
215-
Variants::Single { index: variant_index } => {
216-
if enum_adt_def.variants().is_empty() {
217-
// Uninhabited enums have Variants::Single. We don't generate
218-
// any members for them.
219-
return smallvec![];
220-
}
221-
222-
build_single_variant_union_fields(
223-
cx,
224-
enum_adt_def,
225-
enum_type_and_layout,
226-
enum_type_di_node,
227-
variant_index,
228-
)
215+
Variants::Empty => {
216+
// We don't generate any members for uninhabited types.
217+
return smallvec![];
229218
}
219+
Variants::Single { index: variant_index } => build_single_variant_union_fields(
220+
cx,
221+
enum_adt_def,
222+
enum_type_and_layout,
223+
enum_type_di_node,
224+
variant_index,
225+
),
230226
Variants::Multiple {
231227
tag_encoding: TagEncoding::Direct,
232228
ref variants,
@@ -303,6 +299,7 @@ pub(super) fn build_coroutine_di_node<'ll, 'tcx>(
303299
)
304300
}
305301
Variants::Single { .. }
302+
| Variants::Empty
306303
| Variants::Multiple { tag_encoding: TagEncoding::Niche { .. }, .. } => {
307304
bug!(
308305
"Encountered coroutine with non-direct-tag layout: {:?}",

compiler/rustc_codegen_llvm/src/debuginfo/metadata/enums/mod.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -392,7 +392,7 @@ fn compute_discriminant_value<'ll, 'tcx>(
392392
variant_index: VariantIdx,
393393
) -> DiscrResult {
394394
match enum_type_and_layout.layout.variants() {
395-
&Variants::Single { .. } => DiscrResult::NoDiscriminant,
395+
&Variants::Single { .. } | &Variants::Empty => DiscrResult::NoDiscriminant,
396396
&Variants::Multiple { tag_encoding: TagEncoding::Direct, .. } => DiscrResult::Value(
397397
enum_type_and_layout.ty.discriminant_for_variant(cx.tcx, variant_index).unwrap().val,
398398
),

compiler/rustc_codegen_llvm/src/debuginfo/metadata/enums/native.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -358,8 +358,8 @@ fn build_discr_member_di_node<'ll, 'tcx>(
358358
let containing_scope = enum_or_coroutine_type_di_node;
359359

360360
match enum_or_coroutine_type_and_layout.layout.variants() {
361-
// A single-variant enum has no discriminant.
362-
&Variants::Single { .. } => None,
361+
// A single-variant or no-variant enum has no discriminant.
362+
&Variants::Single { .. } | &Variants::Empty => None,
363363

364364
&Variants::Multiple { tag_field, .. } => {
365365
let tag_base_type = tag_base_type(cx.tcx, enum_or_coroutine_type_and_layout);

compiler/rustc_codegen_llvm/src/type_of.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,7 @@ fn uncached_llvm_type<'a, 'tcx>(
3838
if let (&ty::Adt(def, _), &Variants::Single { index }) =
3939
(layout.ty.kind(), &layout.variants)
4040
{
41-
if def.is_enum() && !def.variants().is_empty() {
41+
if def.is_enum() {
4242
write!(&mut name, "::{}", def.variant(index).name).unwrap();
4343
}
4444
}

compiler/rustc_codegen_ssa/src/debuginfo/mod.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -65,8 +65,8 @@ fn tag_base_type_opt<'tcx>(
6565
});
6666

6767
match enum_type_and_layout.layout.variants() {
68-
// A single-variant enum has no discriminant.
69-
Variants::Single { .. } => None,
68+
// A single-variant or no-variant enum has no discriminant.
69+
Variants::Single { .. } | Variants::Empty => None,
7070

7171
Variants::Multiple { tag_encoding: TagEncoding::Niche { .. }, tag, .. } => {
7272
// Niche tags are always normalized to unsized integers of the correct size.

compiler/rustc_codegen_ssa/src/mir/place.rs

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -243,6 +243,7 @@ impl<'a, 'tcx, V: CodegenObject> PlaceRef<'tcx, V> {
243243
return bx.cx().const_poison(cast_to);
244244
}
245245
let (tag_scalar, tag_encoding, tag_field) = match self.layout.variants {
246+
Variants::Empty => unreachable!("we already handled uninhabited types"),
246247
Variants::Single { index } => {
247248
let discr_val = self
248249
.layout
@@ -365,9 +366,9 @@ impl<'a, 'tcx, V: CodegenObject> PlaceRef<'tcx, V> {
365366
return;
366367
}
367368
match self.layout.variants {
368-
Variants::Single { index } => {
369-
assert_eq!(index, variant_index);
370-
}
369+
Variants::Empty => unreachable!("we already handled uninhabited types"),
370+
Variants::Single { index } => assert_eq!(index, variant_index),
371+
371372
Variants::Multiple { tag_encoding: TagEncoding::Direct, tag_field, .. } => {
372373
let ptr = self.project_field(bx, tag_field);
373374
let to =

0 commit comments

Comments
 (0)