about summary refs log tree commit diff
diff options
context:
space:
mode:
authorDylan DPC <dylan.dpc@gmail.com>2020-10-17 03:27:12 +0200
committerGitHub <noreply@github.com>2020-10-17 03:27:12 +0200
commit496e2feed684afc3eb43a3e4ac933fc61a5a8305 (patch)
treed0ba4cb48e0ab2b17ec2e35adf5efa86eef03ada
parentf1b97ee7f8ffb1a814944b85c7e05a1555a7eda5 (diff)
parent990a39596cf3b33e550f2045f78a62970f8d78f8 (diff)
downloadrust-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.rs4
-rw-r--r--compiler/rustc_mir/src/interpret/cast.rs7
-rw-r--r--src/test/ui/uninhabited/uninhabited-enum-cast.rs4
-rw-r--r--src/test/ui/uninhabited/uninhabited-enum-cast.stderr9
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`.