diff options
| author | Dylan DPC <dylan.dpc@gmail.com> | 2020-10-17 03:27:12 +0200 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2020-10-17 03:27:12 +0200 |
| commit | 496e2feed684afc3eb43a3e4ac933fc61a5a8305 (patch) | |
| tree | d0ba4cb48e0ab2b17ec2e35adf5efa86eef03ada | |
| parent | f1b97ee7f8ffb1a814944b85c7e05a1555a7eda5 (diff) | |
| parent | 990a39596cf3b33e550f2045f78a62970f8d78f8 (diff) | |
| download | rust-496e2feed684afc3eb43a3e4ac933fc61a5a8305.tar.gz rust-496e2feed684afc3eb43a3e4ac933fc61a5a8305.zip | |
Rollup merge of #76199 - Mark-Simulacrum:void-zero, r=nikomatsakis
Permit uninhabited enums to cast into ints This essentially reverts part of #6204; it is unclear why that [commit](https://github.com/rust-lang/rust/pull/6204/commits/c0f587de34f30b060df8a88c4068740e587b9340) was introduced, and I suspect no one remembers. The changed code was only called from casting checks and appears to not affect any callers of that code (other than permitting this one case). Fixes #75647.
| -rw-r--r-- | compiler/rustc_middle/src/ty/mod.rs | 4 | ||||
| -rw-r--r-- | compiler/rustc_mir/src/interpret/cast.rs | 7 | ||||
| -rw-r--r-- | src/test/ui/uninhabited/uninhabited-enum-cast.rs | 4 | ||||
| -rw-r--r-- | src/test/ui/uninhabited/uninhabited-enum-cast.stderr | 9 |
4 files changed, 12 insertions, 12 deletions
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`. |
