@@ -44,7 +44,7 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> {
44
44
}
45
45
}
46
46
47
- /// Read discriminant, return the runtime value as well as the variant index.
47
+ /// Read discriminant, return the variant index.
48
48
/// Can also legally be called on non-enums (e.g. through the discriminant_value intrinsic)!
49
49
///
50
50
/// Will never return an uninhabited variant.
@@ -65,21 +65,17 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> {
65
65
// We use "tag" to refer to how the discriminant is encoded in memory, which can be either
66
66
// straight-forward (`TagEncoding::Direct`) or with a niche (`TagEncoding::Niche`).
67
67
let ( tag_scalar_layout, tag_encoding, tag_field) = match op. layout ( ) . variants {
68
+ Variants :: Empty => {
69
+ throw_ub ! ( UninhabitedEnumVariantRead ( None ) ) ;
70
+ }
68
71
Variants :: Single { index } => {
69
- // Do some extra checks on enums.
70
- if ty. is_enum ( ) {
71
- // Hilariously, `Single` is used even for 0-variant enums.
72
- // (See https://github.com/rust-lang/rust/issues/89765).
73
- if ty. ty_adt_def ( ) . unwrap ( ) . variants ( ) . is_empty ( ) {
74
- throw_ub ! ( UninhabitedEnumVariantRead ( index) )
75
- }
72
+ if op. layout ( ) . is_uninhabited ( ) {
76
73
// For consistency with `write_discriminant`, and to make sure that
77
74
// `project_downcast` cannot fail due to strange layouts, we declare immediate UB
78
- // for uninhabited variants.
79
- if op. layout ( ) . for_variant ( self , index) . is_uninhabited ( ) {
80
- throw_ub ! ( UninhabitedEnumVariantRead ( index) )
81
- }
75
+ // for uninhabited enums.
76
+ throw_ub ! ( UninhabitedEnumVariantRead ( Some ( index) ) ) ;
82
77
}
78
+ // Since the type is inhabited, there must be an index.
83
79
return interp_ok ( index) ;
84
80
}
85
81
Variants :: Multiple { tag, ref tag_encoding, tag_field, .. } => {
@@ -199,11 +195,13 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> {
199
195
// `uninhabited_enum_branching` MIR pass. It also ensures consistency with
200
196
// `write_discriminant`.
201
197
if op. layout ( ) . for_variant ( self , index) . is_uninhabited ( ) {
202
- throw_ub ! ( UninhabitedEnumVariantRead ( index) )
198
+ throw_ub ! ( UninhabitedEnumVariantRead ( Some ( index) ) )
203
199
}
204
200
interp_ok ( index)
205
201
}
206
202
203
+ /// Read discriminant, return the user-visible discriminant.
204
+ /// Can also legally be called on non-enums (e.g. through the discriminant_value intrinsic)!
207
205
pub fn discriminant_for_variant (
208
206
& self ,
209
207
ty : Ty < ' tcx > ,
@@ -243,6 +241,7 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> {
243
241
}
244
242
245
243
match layout. variants {
244
+ abi:: Variants :: Empty => unreachable ! ( "we already handled uninhabited types" ) ,
246
245
abi:: Variants :: Single { .. } => {
247
246
// The tag of a `Single` enum is like the tag of the niched
248
247
// variant: there's no tag as the discriminant is encoded
0 commit comments