diff --git a/compiler/rustc_middle/src/ty/mod.rs b/compiler/rustc_middle/src/ty/mod.rs index 275888b0ce2..bc84eccfcf5 100644 --- a/compiler/rustc_middle/src/ty/mod.rs +++ b/compiler/rustc_middle/src/ty/mod.rs @@ -2436,8 +2436,10 @@ impl<'tcx> AdtDef { self.variants.iter().flat_map(|v| v.fields.iter()) } + /// Whether the ADT lacks fields. Note that this includes uninhabited enums, + /// e.g., `enum Void {}` is considered payload free as well. pub fn is_payloadfree(&self) -> bool { - !self.variants.is_empty() && self.variants.iter().all(|v| v.fields.is_empty()) + self.variants.iter().all(|v| v.fields.is_empty()) } /// Return a `VariantDef` given a variant id. diff --git a/compiler/rustc_mir/src/interpret/cast.rs b/compiler/rustc_mir/src/interpret/cast.rs index 0e16b0caefa..affeae546b2 100644 --- a/compiler/rustc_mir/src/interpret/cast.rs +++ b/compiler/rustc_mir/src/interpret/cast.rs @@ -139,9 +139,14 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { // # First handle non-scalar source values. - // Handle cast from a univariant (ZST) enum. + // Handle cast from a ZST enum (0 or 1 variants). match src.layout.variants { Variants::Single { index } => { + if src.layout.abi.is_uninhabited() { + // This is dead code, because an uninhabited enum is UB to + // instantiate. + throw_ub!(Unreachable); + } if let Some(discr) = src.layout.ty.discriminant_for_variant(*self.tcx, index) { assert!(src.layout.is_zst()); let discr_layout = self.layout_of(discr.ty)?; diff --git a/src/test/ui/uninhabited/uninhabited-enum-cast.rs b/src/test/ui/uninhabited/uninhabited-enum-cast.rs index 7e178e054cc..5a75c94c42f 100644 --- a/src/test/ui/uninhabited/uninhabited-enum-cast.rs +++ b/src/test/ui/uninhabited/uninhabited-enum-cast.rs @@ -1,7 +1,9 @@ +// check-pass + enum E {} fn f(e: E) { - println!("{}", (e as isize).to_string()); //~ ERROR non-primitive cast + println!("{}", (e as isize).to_string()); } fn main() {} diff --git a/src/test/ui/uninhabited/uninhabited-enum-cast.stderr b/src/test/ui/uninhabited/uninhabited-enum-cast.stderr deleted file mode 100644 index a9f10dfec99..00000000000 --- a/src/test/ui/uninhabited/uninhabited-enum-cast.stderr +++ /dev/null @@ -1,9 +0,0 @@ -error[E0605]: non-primitive cast: `E` as `isize` - --> $DIR/uninhabited-enum-cast.rs:4:20 - | -LL | println!("{}", (e as isize).to_string()); - | ^^^^^^^^^^^^ an `as` expression can only be used to convert between primitive types or to coerce to a specific trait object - -error: aborting due to previous error - -For more information about this error, try `rustc --explain E0605`.