From 8485e6fdece723152c024228284ca76592108f72 Mon Sep 17 00:00:00 2001 From: Mark Rousskov Date: Thu, 14 Oct 2021 10:57:56 -0400 Subject: [PATCH 1/2] Revert "Stabilize `arbitrary_enum_discriminant`" This reverts commit 7a62f29f3171767090949778ce0f161e930706b9. --- compiler/rustc_ast_passes/src/feature_gate.rs | 64 ++++++++++++++++++- .../src/error_codes/E0732.md | 4 ++ compiler/rustc_feature/src/accepted.rs | 2 - compiler/rustc_feature/src/active.rs | 3 + compiler/rustc_typeck/src/check/check.rs | 2 +- .../arbitrary-enum-discriminant.md | 37 +++++++++++ .../arbitrary_enum_discriminant-no-repr.rs | 1 + ...arbitrary_enum_discriminant-no-repr.stderr | 2 +- .../arbitrary_enum_discriminant.rs | 2 +- .../enum-discriminant/discriminant_value.rs | 2 +- ...eature-gate-arbitrary_enum_discriminant.rs | 10 +++ ...re-gate-arbitrary_enum_discriminant.stderr | 36 +++++++++++ .../issue-70453-generics-in-discr-ice-2.rs | 2 +- .../issue-70453-polymorphic-ctfe.rs | 2 +- .../issue-70509-partial_eq.rs | 2 +- .../issue-70509-partial_eq.stderr | 2 +- .../intrinsics/panic-uninitialized-zeroed.rs | 2 +- src/test/ui/parser/issue-17383.rs | 7 ++ src/test/ui/parser/issue-17383.stderr | 15 +++++ .../ui/parser/tag-variant-disr-non-nullary.rs | 12 ++++ .../tag-variant-disr-non-nullary.stderr | 25 ++++++++ 21 files changed, 221 insertions(+), 13 deletions(-) create mode 100644 src/doc/unstable-book/src/language-features/arbitrary-enum-discriminant.md create mode 100644 src/test/ui/enum-discriminant/feature-gate-arbitrary_enum_discriminant.rs create mode 100644 src/test/ui/enum-discriminant/feature-gate-arbitrary_enum_discriminant.stderr create mode 100644 src/test/ui/parser/issue-17383.rs create mode 100644 src/test/ui/parser/issue-17383.stderr create mode 100644 src/test/ui/parser/tag-variant-disr-non-nullary.rs create mode 100644 src/test/ui/parser/tag-variant-disr-non-nullary.stderr diff --git a/compiler/rustc_ast_passes/src/feature_gate.rs b/compiler/rustc_ast_passes/src/feature_gate.rs index bce5cd8174d08..91b4597a9bb1f 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::>(); + + 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 9536fdbf0df87..7347e6654c5b3 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 55ec3703df8f8..0d7a2afb6367d 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 a2fadb13a5741..f7c0597909e8b 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 db50c5d891e13..66316214e5e66 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 0000000000000..e0bb782270e22 --- /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()]` 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 a6e5f70fdefa6..4da7b5ab24b29 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 7af063c591d56..2db5372da0c6e 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 360bddb7bd1e4..f2270602d87eb 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 7ed1d9660a69c..eb60aaf4b2d04 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 0000000000000..3e90af4d36af3 --- /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 0000000000000..b5f61e6e991d8 --- /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 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 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 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 ad9fcc25b4127..f927dd189038a 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 42a062239d34a..e62582fb5161a 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 3adac7b72621c..ae389e1146645 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 04fb13f37a006..5bf6ea56ebc77 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 50f1a2f25b95d..324bba15e4350 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 0000000000000..7bf0e64f2c0a3 --- /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 0000000000000..265d6e1486614 --- /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 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 0000000000000..a9cfdd549c752 --- /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 0000000000000..79f044a0675b7 --- /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 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`. From 2284082ae8e9d422fdacfa7c229d2676d61470a5 Mon Sep 17 00:00:00 2001 From: Mark Rousskov Date: Thu, 14 Oct 2021 10:58:16 -0400 Subject: [PATCH 2/2] Drop reverted stabilizations from release notes --- RELEASES.md | 3 --- 1 file changed, 3 deletions(-) diff --git a/RELEASES.md b/RELEASES.md index 63af8ebac195a..52d823d8acac4 100644 --- a/RELEASES.md +++ b/RELEASES.md @@ -6,7 +6,6 @@ Language - [The 2021 Edition is now stable.][rust#88100] See [the edition guide][rust-2021-edition-guide] for more details. -- [You can now specify explicit discriminant values on any Rust enum.][rust#86860] - [The pattern in `binding @ pattern` can now also introduce new bindings.][rust#85305] - [Union field access is permitted in `const fn`.][rust#85769] @@ -51,8 +50,6 @@ Stabilised APIs --------------- - [`std::os::unix::fs::chroot`] -- [`Iterator::intersperse`] -- [`Iterator::intersperse_with`] - [`UnsafeCell::raw_get`] - [`BufWriter::into_parts`] - [`core::panic::{UnwindSafe, RefUnwindSafe, AssertUnwindSafe}`]