about summary refs log tree commit diff
diff options
context:
space:
mode:
authorMark Rousskov <mark.simulacrum@gmail.com>2021-10-14 10:57:56 -0400
committerMark Rousskov <mark.simulacrum@gmail.com>2021-10-14 10:57:56 -0400
commit8485e6fdece723152c024228284ca76592108f72 (patch)
tree00c6722fdb3d86360d83ab0551450894f3590224
parentc34ac8747ca96d09cb08b8f5adddead826e77c06 (diff)
downloadrust-8485e6fdece723152c024228284ca76592108f72.tar.gz
rust-8485e6fdece723152c024228284ca76592108f72.zip
Revert "Stabilize `arbitrary_enum_discriminant`"
This reverts commit 7a62f29f3171767090949778ce0f161e930706b9.
-rw-r--r--compiler/rustc_ast_passes/src/feature_gate.rs64
-rw-r--r--compiler/rustc_error_codes/src/error_codes/E0732.md4
-rw-r--r--compiler/rustc_feature/src/accepted.rs2
-rw-r--r--compiler/rustc_feature/src/active.rs3
-rw-r--r--compiler/rustc_typeck/src/check/check.rs2
-rw-r--r--src/doc/unstable-book/src/language-features/arbitrary-enum-discriminant.md37
-rw-r--r--src/test/ui/enum-discriminant/arbitrary_enum_discriminant-no-repr.rs1
-rw-r--r--src/test/ui/enum-discriminant/arbitrary_enum_discriminant-no-repr.stderr2
-rw-r--r--src/test/ui/enum-discriminant/arbitrary_enum_discriminant.rs2
-rw-r--r--src/test/ui/enum-discriminant/discriminant_value.rs2
-rw-r--r--src/test/ui/enum-discriminant/feature-gate-arbitrary_enum_discriminant.rs10
-rw-r--r--src/test/ui/enum-discriminant/feature-gate-arbitrary_enum_discriminant.stderr36
-rw-r--r--src/test/ui/enum-discriminant/issue-70453-generics-in-discr-ice-2.rs2
-rw-r--r--src/test/ui/enum-discriminant/issue-70453-polymorphic-ctfe.rs2
-rw-r--r--src/test/ui/enum-discriminant/issue-70509-partial_eq.rs2
-rw-r--r--src/test/ui/enum-discriminant/issue-70509-partial_eq.stderr2
-rw-r--r--src/test/ui/intrinsics/panic-uninitialized-zeroed.rs2
-rw-r--r--src/test/ui/parser/issue-17383.rs7
-rw-r--r--src/test/ui/parser/issue-17383.stderr15
-rw-r--r--src/test/ui/parser/tag-variant-disr-non-nullary.rs12
-rw-r--r--src/test/ui/parser/tag-variant-disr-non-nullary.stderr25
21 files changed, 221 insertions, 13 deletions
diff --git a/compiler/rustc_ast_passes/src/feature_gate.rs b/compiler/rustc_ast_passes/src/feature_gate.rs
index bce5cd8174d..91b4597a9bb 100644
--- a/compiler/rustc_ast_passes/src/feature_gate.rs
+++ b/compiler/rustc_ast_passes/src/feature_gate.rs
@@ -1,11 +1,11 @@
 use rustc_ast as ast;
 use rustc_ast::visit::{self, AssocCtxt, FnCtxt, FnKind, Visitor};
 use rustc_ast::{AssocTyConstraint, AssocTyConstraintKind, NodeId};
-use rustc_ast::{PatKind, RangeEnd};
+use rustc_ast::{PatKind, RangeEnd, VariantData};
 use rustc_errors::struct_span_err;
 use rustc_feature::{AttributeGate, BUILTIN_ATTRIBUTE_MAP};
 use rustc_feature::{Features, GateIssue};
-use rustc_session::parse::feature_err_issue;
+use rustc_session::parse::{feature_err, feature_err_issue};
 use rustc_session::Session;
 use rustc_span::source_map::Spanned;
 use rustc_span::symbol::sym;
@@ -218,6 +218,46 @@ impl<'a> PostExpansionVisitor<'a> {
         }
     }
 
+    fn maybe_report_invalid_custom_discriminants(&self, variants: &[ast::Variant]) {
+        let has_fields = variants.iter().any(|variant| match variant.data {
+            VariantData::Tuple(..) | VariantData::Struct(..) => true,
+            VariantData::Unit(..) => false,
+        });
+
+        let discriminant_spans = variants
+            .iter()
+            .filter(|variant| match variant.data {
+                VariantData::Tuple(..) | VariantData::Struct(..) => false,
+                VariantData::Unit(..) => true,
+            })
+            .filter_map(|variant| variant.disr_expr.as_ref().map(|c| c.value.span))
+            .collect::<Vec<_>>();
+
+        if !discriminant_spans.is_empty() && has_fields {
+            let mut err = feature_err(
+                &self.sess.parse_sess,
+                sym::arbitrary_enum_discriminant,
+                discriminant_spans.clone(),
+                "custom discriminant values are not allowed in enums with tuple or struct variants",
+            );
+            for sp in discriminant_spans {
+                err.span_label(sp, "disallowed custom discriminant");
+            }
+            for variant in variants.iter() {
+                match &variant.data {
+                    VariantData::Struct(..) => {
+                        err.span_label(variant.span, "struct variant defined here");
+                    }
+                    VariantData::Tuple(..) => {
+                        err.span_label(variant.span, "tuple variant defined here");
+                    }
+                    VariantData::Unit(..) => {}
+                }
+            }
+            err.emit();
+        }
+    }
+
     fn check_gat(&self, generics: &ast::Generics, span: Span) {
         if !generics.params.is_empty() {
             gate_feature_post!(
@@ -363,6 +403,26 @@ impl<'a> Visitor<'a> for PostExpansionVisitor<'a> {
                 }
             }
 
+            ast::ItemKind::Enum(ast::EnumDef { ref variants, .. }, ..) => {
+                for variant in variants {
+                    match (&variant.data, &variant.disr_expr) {
+                        (ast::VariantData::Unit(..), _) => {}
+                        (_, Some(disr_expr)) => gate_feature_post!(
+                            &self,
+                            arbitrary_enum_discriminant,
+                            disr_expr.value.span,
+                            "discriminants on non-unit variants are experimental"
+                        ),
+                        _ => {}
+                    }
+                }
+
+                let has_feature = self.features.arbitrary_enum_discriminant;
+                if !has_feature && !i.span.allows_unstable(sym::arbitrary_enum_discriminant) {
+                    self.maybe_report_invalid_custom_discriminants(&variants);
+                }
+            }
+
             ast::ItemKind::Impl(box ast::ImplKind {
                 polarity, defaultness, ref of_trait, ..
             }) => {
diff --git a/compiler/rustc_error_codes/src/error_codes/E0732.md b/compiler/rustc_error_codes/src/error_codes/E0732.md
index 9536fdbf0df..7347e6654c5 100644
--- a/compiler/rustc_error_codes/src/error_codes/E0732.md
+++ b/compiler/rustc_error_codes/src/error_codes/E0732.md
@@ -3,6 +3,8 @@ An `enum` with a discriminant must specify a `#[repr(inttype)]`.
 Erroneous code example:
 
 ```compile_fail,E0732
+#![feature(arbitrary_enum_discriminant)]
+
 enum Enum { // error!
     Unit = 1,
     Tuple() = 2,
@@ -18,6 +20,8 @@ is a well-defined way to extract a variant's discriminant from a value;
 for instance:
 
 ```
+#![feature(arbitrary_enum_discriminant)]
+
 #[repr(u8)]
 enum Enum {
     Unit = 3,
diff --git a/compiler/rustc_feature/src/accepted.rs b/compiler/rustc_feature/src/accepted.rs
index 55ec3703df8..0d7a2afb636 100644
--- a/compiler/rustc_feature/src/accepted.rs
+++ b/compiler/rustc_feature/src/accepted.rs
@@ -293,8 +293,6 @@ declare_features! (
     (accepted, const_fn_transmute, "1.56.0", Some(53605), None),
     /// Allows accessing fields of unions inside `const` functions.
     (accepted, const_fn_union, "1.56.0", Some(51909), None),
-    /// Allows explicit discriminants on non-unit enum variants.
-    (accepted, arbitrary_enum_discriminant, "1.56.0", Some(60553), None),
     /// Allows macro attributes to observe output of `#[derive]`.
     (accepted, macro_attributes_in_derive_output, "1.57.0", Some(81119), None),
     /// Allows panicking during const eval (producing compile-time errors).
diff --git a/compiler/rustc_feature/src/active.rs b/compiler/rustc_feature/src/active.rs
index a2fadb13a57..f7c0597909e 100644
--- a/compiler/rustc_feature/src/active.rs
+++ b/compiler/rustc_feature/src/active.rs
@@ -464,6 +464,9 @@ declare_features! (
     /// Allows #[repr(transparent)] on unions (RFC 2645).
     (active, transparent_unions, "1.37.0", Some(60405), None),
 
+    /// Allows explicit discriminants on non-unit enum variants.
+    (active, arbitrary_enum_discriminant, "1.37.0", Some(60553), None),
+
     /// Allows `async || body` closures.
     (active, async_closure, "1.37.0", Some(62290), None),
 
diff --git a/compiler/rustc_typeck/src/check/check.rs b/compiler/rustc_typeck/src/check/check.rs
index db50c5d891e..66316214e5e 100644
--- a/compiler/rustc_typeck/src/check/check.rs
+++ b/compiler/rustc_typeck/src/check/check.rs
@@ -1374,7 +1374,7 @@ fn check_enum<'tcx>(
         }
     }
 
-    if tcx.adt_def(def_id).repr.int.is_none() {
+    if tcx.adt_def(def_id).repr.int.is_none() && tcx.features().arbitrary_enum_discriminant {
         let is_unit = |var: &hir::Variant<'_>| matches!(var.data, hir::VariantData::Unit(..));
 
         let has_disr = |var: &hir::Variant<'_>| var.disr_expr.is_some();
diff --git a/src/doc/unstable-book/src/language-features/arbitrary-enum-discriminant.md b/src/doc/unstable-book/src/language-features/arbitrary-enum-discriminant.md
new file mode 100644
index 00000000000..e0bb782270e
--- /dev/null
+++ b/src/doc/unstable-book/src/language-features/arbitrary-enum-discriminant.md
@@ -0,0 +1,37 @@
+# `arbitrary_enum_discriminant`
+
+The tracking issue for this feature is: [#60553]
+
+[#60553]: https://github.com/rust-lang/rust/issues/60553
+
+------------------------
+
+The `arbitrary_enum_discriminant` feature permits tuple-like and
+struct-like enum variants with `#[repr(<int-type>)]` to have explicit discriminants.
+
+## Examples
+
+```rust
+#![feature(arbitrary_enum_discriminant)]
+
+#[allow(dead_code)]
+#[repr(u8)]
+enum Enum {
+    Unit = 3,
+    Tuple(u16) = 2,
+    Struct {
+        a: u8,
+        b: u16,
+    } = 1,
+}
+
+impl Enum {
+    fn tag(&self) -> u8 {
+        unsafe { *(self as *const Self as *const u8) }
+    }
+}
+
+assert_eq!(3, Enum::Unit.tag());
+assert_eq!(2, Enum::Tuple(5).tag());
+assert_eq!(1, Enum::Struct{a: 7, b: 11}.tag());
+```
diff --git a/src/test/ui/enum-discriminant/arbitrary_enum_discriminant-no-repr.rs b/src/test/ui/enum-discriminant/arbitrary_enum_discriminant-no-repr.rs
index a6e5f70fdef..4da7b5ab24b 100644
--- a/src/test/ui/enum-discriminant/arbitrary_enum_discriminant-no-repr.rs
+++ b/src/test/ui/enum-discriminant/arbitrary_enum_discriminant-no-repr.rs
@@ -1,4 +1,5 @@
 #![crate_type="lib"]
+#![feature(arbitrary_enum_discriminant)]
 
 enum Enum {
 //~^ ERROR `#[repr(inttype)]` must be specified
diff --git a/src/test/ui/enum-discriminant/arbitrary_enum_discriminant-no-repr.stderr b/src/test/ui/enum-discriminant/arbitrary_enum_discriminant-no-repr.stderr
index 7af063c591d..2db5372da0c 100644
--- a/src/test/ui/enum-discriminant/arbitrary_enum_discriminant-no-repr.stderr
+++ b/src/test/ui/enum-discriminant/arbitrary_enum_discriminant-no-repr.stderr
@@ -1,5 +1,5 @@
 error[E0732]: `#[repr(inttype)]` must be specified
-  --> $DIR/arbitrary_enum_discriminant-no-repr.rs:3:1
+  --> $DIR/arbitrary_enum_discriminant-no-repr.rs:4:1
    |
 LL | / enum Enum {
 LL | |
diff --git a/src/test/ui/enum-discriminant/arbitrary_enum_discriminant.rs b/src/test/ui/enum-discriminant/arbitrary_enum_discriminant.rs
index 360bddb7bd1..f2270602d87 100644
--- a/src/test/ui/enum-discriminant/arbitrary_enum_discriminant.rs
+++ b/src/test/ui/enum-discriminant/arbitrary_enum_discriminant.rs
@@ -1,5 +1,5 @@
 // run-pass
-#![feature(const_raw_ptr_deref, test)]
+#![feature(arbitrary_enum_discriminant, const_raw_ptr_deref, test)]
 
 extern crate test;
 
diff --git a/src/test/ui/enum-discriminant/discriminant_value.rs b/src/test/ui/enum-discriminant/discriminant_value.rs
index 7ed1d9660a6..eb60aaf4b2d 100644
--- a/src/test/ui/enum-discriminant/discriminant_value.rs
+++ b/src/test/ui/enum-discriminant/discriminant_value.rs
@@ -1,6 +1,6 @@
 // run-pass
 #![allow(stable_features)]
-#![feature(core, core_intrinsics)]
+#![feature(arbitrary_enum_discriminant, core, core_intrinsics)]
 
 extern crate core;
 use core::intrinsics::discriminant_value;
diff --git a/src/test/ui/enum-discriminant/feature-gate-arbitrary_enum_discriminant.rs b/src/test/ui/enum-discriminant/feature-gate-arbitrary_enum_discriminant.rs
new file mode 100644
index 00000000000..3e90af4d36a
--- /dev/null
+++ b/src/test/ui/enum-discriminant/feature-gate-arbitrary_enum_discriminant.rs
@@ -0,0 +1,10 @@
+#![crate_type="lib"]
+
+enum Enum {
+  Unit = 1,
+  //~^ ERROR custom discriminant values are not allowed in enums with tuple or struct variants
+  Tuple() = 2,
+  //~^ ERROR discriminants on non-unit variants are experimental
+  Struct{} = 3,
+  //~^ ERROR discriminants on non-unit variants are experimental
+}
diff --git a/src/test/ui/enum-discriminant/feature-gate-arbitrary_enum_discriminant.stderr b/src/test/ui/enum-discriminant/feature-gate-arbitrary_enum_discriminant.stderr
new file mode 100644
index 00000000000..b5f61e6e991
--- /dev/null
+++ b/src/test/ui/enum-discriminant/feature-gate-arbitrary_enum_discriminant.stderr
@@ -0,0 +1,36 @@
+error[E0658]: discriminants on non-unit variants are experimental
+  --> $DIR/feature-gate-arbitrary_enum_discriminant.rs:6:13
+   |
+LL |   Tuple() = 2,
+   |             ^
+   |
+   = note: see issue #60553 <https://github.com/rust-lang/rust/issues/60553> for more information
+   = help: add `#![feature(arbitrary_enum_discriminant)]` to the crate attributes to enable
+
+error[E0658]: discriminants on non-unit variants are experimental
+  --> $DIR/feature-gate-arbitrary_enum_discriminant.rs:8:14
+   |
+LL |   Struct{} = 3,
+   |              ^
+   |
+   = note: see issue #60553 <https://github.com/rust-lang/rust/issues/60553> for more information
+   = help: add `#![feature(arbitrary_enum_discriminant)]` to the crate attributes to enable
+
+error[E0658]: custom discriminant values are not allowed in enums with tuple or struct variants
+  --> $DIR/feature-gate-arbitrary_enum_discriminant.rs:4:10
+   |
+LL |   Unit = 1,
+   |          ^ disallowed custom discriminant
+LL |
+LL |   Tuple() = 2,
+   |   ----------- tuple variant defined here
+LL |
+LL |   Struct{} = 3,
+   |   ------------ struct variant defined here
+   |
+   = note: see issue #60553 <https://github.com/rust-lang/rust/issues/60553> for more information
+   = help: add `#![feature(arbitrary_enum_discriminant)]` to the crate attributes to enable
+
+error: aborting due to 3 previous errors
+
+For more information about this error, try `rustc --explain E0658`.
diff --git a/src/test/ui/enum-discriminant/issue-70453-generics-in-discr-ice-2.rs b/src/test/ui/enum-discriminant/issue-70453-generics-in-discr-ice-2.rs
index ad9fcc25b41..f927dd18903 100644
--- a/src/test/ui/enum-discriminant/issue-70453-generics-in-discr-ice-2.rs
+++ b/src/test/ui/enum-discriminant/issue-70453-generics-in-discr-ice-2.rs
@@ -1,4 +1,4 @@
-#![feature(core_intrinsics)]
+#![feature(arbitrary_enum_discriminant, core_intrinsics)]
 
 extern crate core;
 use core::intrinsics::discriminant_value;
diff --git a/src/test/ui/enum-discriminant/issue-70453-polymorphic-ctfe.rs b/src/test/ui/enum-discriminant/issue-70453-polymorphic-ctfe.rs
index 42a062239d3..e62582fb516 100644
--- a/src/test/ui/enum-discriminant/issue-70453-polymorphic-ctfe.rs
+++ b/src/test/ui/enum-discriminant/issue-70453-polymorphic-ctfe.rs
@@ -1,4 +1,4 @@
-#![feature(core_intrinsics)]
+#![feature(arbitrary_enum_discriminant, core_intrinsics)]
 
 extern crate core;
 use core::intrinsics::discriminant_value;
diff --git a/src/test/ui/enum-discriminant/issue-70509-partial_eq.rs b/src/test/ui/enum-discriminant/issue-70509-partial_eq.rs
index 3adac7b7262..ae389e11466 100644
--- a/src/test/ui/enum-discriminant/issue-70509-partial_eq.rs
+++ b/src/test/ui/enum-discriminant/issue-70509-partial_eq.rs
@@ -1,5 +1,5 @@
 // run-pass
-#![feature(repr128)]
+#![feature(repr128, arbitrary_enum_discriminant)]
 //~^ WARN the feature `repr128` is incomplete
 
 #[derive(PartialEq, Debug)]
diff --git a/src/test/ui/enum-discriminant/issue-70509-partial_eq.stderr b/src/test/ui/enum-discriminant/issue-70509-partial_eq.stderr
index 04fb13f37a0..5bf6ea56ebc 100644
--- a/src/test/ui/enum-discriminant/issue-70509-partial_eq.stderr
+++ b/src/test/ui/enum-discriminant/issue-70509-partial_eq.stderr
@@ -1,7 +1,7 @@
 warning: the feature `repr128` is incomplete and may not be safe to use and/or cause compiler crashes
   --> $DIR/issue-70509-partial_eq.rs:2:12
    |
-LL | #![feature(repr128)]
+LL | #![feature(repr128, arbitrary_enum_discriminant)]
    |            ^^^^^^^
    |
    = note: `#[warn(incomplete_features)]` on by default
diff --git a/src/test/ui/intrinsics/panic-uninitialized-zeroed.rs b/src/test/ui/intrinsics/panic-uninitialized-zeroed.rs
index 50f1a2f25b9..324bba15e43 100644
--- a/src/test/ui/intrinsics/panic-uninitialized-zeroed.rs
+++ b/src/test/ui/intrinsics/panic-uninitialized-zeroed.rs
@@ -6,7 +6,7 @@
 
 // This test checks panic emitted from `mem::{uninitialized,zeroed}`.
 
-#![feature(never_type)]
+#![feature(never_type, arbitrary_enum_discriminant)]
 #![allow(deprecated, invalid_value)]
 
 use std::{
diff --git a/src/test/ui/parser/issue-17383.rs b/src/test/ui/parser/issue-17383.rs
new file mode 100644
index 00000000000..7bf0e64f2c0
--- /dev/null
+++ b/src/test/ui/parser/issue-17383.rs
@@ -0,0 +1,7 @@
+enum X {
+    A = 3,
+    //~^ ERROR custom discriminant values are not allowed in enums with tuple or struct variants
+    B(usize)
+}
+
+fn main() {}
diff --git a/src/test/ui/parser/issue-17383.stderr b/src/test/ui/parser/issue-17383.stderr
new file mode 100644
index 00000000000..265d6e14866
--- /dev/null
+++ b/src/test/ui/parser/issue-17383.stderr
@@ -0,0 +1,15 @@
+error[E0658]: custom discriminant values are not allowed in enums with tuple or struct variants
+  --> $DIR/issue-17383.rs:2:9
+   |
+LL |     A = 3,
+   |         ^ disallowed custom discriminant
+LL |
+LL |     B(usize)
+   |     -------- tuple variant defined here
+   |
+   = note: see issue #60553 <https://github.com/rust-lang/rust/issues/60553> for more information
+   = help: add `#![feature(arbitrary_enum_discriminant)]` to the crate attributes to enable
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0658`.
diff --git a/src/test/ui/parser/tag-variant-disr-non-nullary.rs b/src/test/ui/parser/tag-variant-disr-non-nullary.rs
new file mode 100644
index 00000000000..a9cfdd549c7
--- /dev/null
+++ b/src/test/ui/parser/tag-variant-disr-non-nullary.rs
@@ -0,0 +1,12 @@
+enum Color {
+    Red = 0xff0000,
+    //~^ ERROR custom discriminant values are not allowed in enums with tuple or struct variants
+    Green = 0x00ff00,
+    Blue = 0x0000ff,
+    Black = 0x000000,
+    White = 0xffffff,
+    Other(usize),
+    Other2(usize, usize),
+}
+
+fn main() {}
diff --git a/src/test/ui/parser/tag-variant-disr-non-nullary.stderr b/src/test/ui/parser/tag-variant-disr-non-nullary.stderr
new file mode 100644
index 00000000000..79f044a0675
--- /dev/null
+++ b/src/test/ui/parser/tag-variant-disr-non-nullary.stderr
@@ -0,0 +1,25 @@
+error[E0658]: custom discriminant values are not allowed in enums with tuple or struct variants
+  --> $DIR/tag-variant-disr-non-nullary.rs:2:11
+   |
+LL |     Red = 0xff0000,
+   |           ^^^^^^^^ disallowed custom discriminant
+LL |
+LL |     Green = 0x00ff00,
+   |             ^^^^^^^^ disallowed custom discriminant
+LL |     Blue = 0x0000ff,
+   |            ^^^^^^^^ disallowed custom discriminant
+LL |     Black = 0x000000,
+   |             ^^^^^^^^ disallowed custom discriminant
+LL |     White = 0xffffff,
+   |             ^^^^^^^^ disallowed custom discriminant
+LL |     Other(usize),
+   |     ------------ tuple variant defined here
+LL |     Other2(usize, usize),
+   |     -------------------- tuple variant defined here
+   |
+   = note: see issue #60553 <https://github.com/rust-lang/rust/issues/60553> for more information
+   = help: add `#![feature(arbitrary_enum_discriminant)]` to the crate attributes to enable
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0658`.