Revert "Stabilize arbitrary_enum_discriminant
"
This reverts commit 7a62f29f31
.
This commit is contained in:
parent
c34ac8747c
commit
8485e6fdec
21 changed files with 221 additions and 13 deletions
|
@ -1,11 +1,11 @@
|
||||||
use rustc_ast as ast;
|
use rustc_ast as ast;
|
||||||
use rustc_ast::visit::{self, AssocCtxt, FnCtxt, FnKind, Visitor};
|
use rustc_ast::visit::{self, AssocCtxt, FnCtxt, FnKind, Visitor};
|
||||||
use rustc_ast::{AssocTyConstraint, AssocTyConstraintKind, NodeId};
|
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_errors::struct_span_err;
|
||||||
use rustc_feature::{AttributeGate, BUILTIN_ATTRIBUTE_MAP};
|
use rustc_feature::{AttributeGate, BUILTIN_ATTRIBUTE_MAP};
|
||||||
use rustc_feature::{Features, GateIssue};
|
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_session::Session;
|
||||||
use rustc_span::source_map::Spanned;
|
use rustc_span::source_map::Spanned;
|
||||||
use rustc_span::symbol::sym;
|
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) {
|
fn check_gat(&self, generics: &ast::Generics, span: Span) {
|
||||||
if !generics.params.is_empty() {
|
if !generics.params.is_empty() {
|
||||||
gate_feature_post!(
|
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 {
|
ast::ItemKind::Impl(box ast::ImplKind {
|
||||||
polarity, defaultness, ref of_trait, ..
|
polarity, defaultness, ref of_trait, ..
|
||||||
}) => {
|
}) => {
|
||||||
|
|
|
@ -3,6 +3,8 @@ An `enum` with a discriminant must specify a `#[repr(inttype)]`.
|
||||||
Erroneous code example:
|
Erroneous code example:
|
||||||
|
|
||||||
```compile_fail,E0732
|
```compile_fail,E0732
|
||||||
|
#![feature(arbitrary_enum_discriminant)]
|
||||||
|
|
||||||
enum Enum { // error!
|
enum Enum { // error!
|
||||||
Unit = 1,
|
Unit = 1,
|
||||||
Tuple() = 2,
|
Tuple() = 2,
|
||||||
|
@ -18,6 +20,8 @@ is a well-defined way to extract a variant's discriminant from a value;
|
||||||
for instance:
|
for instance:
|
||||||
|
|
||||||
```
|
```
|
||||||
|
#![feature(arbitrary_enum_discriminant)]
|
||||||
|
|
||||||
#[repr(u8)]
|
#[repr(u8)]
|
||||||
enum Enum {
|
enum Enum {
|
||||||
Unit = 3,
|
Unit = 3,
|
||||||
|
|
|
@ -293,8 +293,6 @@ declare_features! (
|
||||||
(accepted, const_fn_transmute, "1.56.0", Some(53605), None),
|
(accepted, const_fn_transmute, "1.56.0", Some(53605), None),
|
||||||
/// Allows accessing fields of unions inside `const` functions.
|
/// Allows accessing fields of unions inside `const` functions.
|
||||||
(accepted, const_fn_union, "1.56.0", Some(51909), None),
|
(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]`.
|
/// Allows macro attributes to observe output of `#[derive]`.
|
||||||
(accepted, macro_attributes_in_derive_output, "1.57.0", Some(81119), None),
|
(accepted, macro_attributes_in_derive_output, "1.57.0", Some(81119), None),
|
||||||
/// Allows panicking during const eval (producing compile-time errors).
|
/// Allows panicking during const eval (producing compile-time errors).
|
||||||
|
|
|
@ -464,6 +464,9 @@ declare_features! (
|
||||||
/// Allows #[repr(transparent)] on unions (RFC 2645).
|
/// Allows #[repr(transparent)] on unions (RFC 2645).
|
||||||
(active, transparent_unions, "1.37.0", Some(60405), None),
|
(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.
|
/// Allows `async || body` closures.
|
||||||
(active, async_closure, "1.37.0", Some(62290), None),
|
(active, async_closure, "1.37.0", Some(62290), None),
|
||||||
|
|
||||||
|
|
|
@ -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 is_unit = |var: &hir::Variant<'_>| matches!(var.data, hir::VariantData::Unit(..));
|
||||||
|
|
||||||
let has_disr = |var: &hir::Variant<'_>| var.disr_expr.is_some();
|
let has_disr = |var: &hir::Variant<'_>| var.disr_expr.is_some();
|
||||||
|
|
|
@ -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());
|
||||||
|
```
|
|
@ -1,4 +1,5 @@
|
||||||
#![crate_type="lib"]
|
#![crate_type="lib"]
|
||||||
|
#![feature(arbitrary_enum_discriminant)]
|
||||||
|
|
||||||
enum Enum {
|
enum Enum {
|
||||||
//~^ ERROR `#[repr(inttype)]` must be specified
|
//~^ ERROR `#[repr(inttype)]` must be specified
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
error[E0732]: `#[repr(inttype)]` must be specified
|
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 | / enum Enum {
|
||||||
LL | |
|
LL | |
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
// run-pass
|
// run-pass
|
||||||
#![feature(const_raw_ptr_deref, test)]
|
#![feature(arbitrary_enum_discriminant, const_raw_ptr_deref, test)]
|
||||||
|
|
||||||
extern crate test;
|
extern crate test;
|
||||||
|
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
// run-pass
|
// run-pass
|
||||||
#![allow(stable_features)]
|
#![allow(stable_features)]
|
||||||
#![feature(core, core_intrinsics)]
|
#![feature(arbitrary_enum_discriminant, core, core_intrinsics)]
|
||||||
|
|
||||||
extern crate core;
|
extern crate core;
|
||||||
use core::intrinsics::discriminant_value;
|
use core::intrinsics::discriminant_value;
|
||||||
|
|
|
@ -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
|
||||||
|
}
|
|
@ -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`.
|
|
@ -1,4 +1,4 @@
|
||||||
#![feature(core_intrinsics)]
|
#![feature(arbitrary_enum_discriminant, core_intrinsics)]
|
||||||
|
|
||||||
extern crate core;
|
extern crate core;
|
||||||
use core::intrinsics::discriminant_value;
|
use core::intrinsics::discriminant_value;
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
#![feature(core_intrinsics)]
|
#![feature(arbitrary_enum_discriminant, core_intrinsics)]
|
||||||
|
|
||||||
extern crate core;
|
extern crate core;
|
||||||
use core::intrinsics::discriminant_value;
|
use core::intrinsics::discriminant_value;
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
// run-pass
|
// run-pass
|
||||||
#![feature(repr128)]
|
#![feature(repr128, arbitrary_enum_discriminant)]
|
||||||
//~^ WARN the feature `repr128` is incomplete
|
//~^ WARN the feature `repr128` is incomplete
|
||||||
|
|
||||||
#[derive(PartialEq, Debug)]
|
#[derive(PartialEq, Debug)]
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
warning: the feature `repr128` is incomplete and may not be safe to use and/or cause compiler crashes
|
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
|
--> $DIR/issue-70509-partial_eq.rs:2:12
|
||||||
|
|
|
|
||||||
LL | #![feature(repr128)]
|
LL | #![feature(repr128, arbitrary_enum_discriminant)]
|
||||||
| ^^^^^^^
|
| ^^^^^^^
|
||||||
|
|
|
|
||||||
= note: `#[warn(incomplete_features)]` on by default
|
= note: `#[warn(incomplete_features)]` on by default
|
||||||
|
|
|
@ -6,7 +6,7 @@
|
||||||
|
|
||||||
// This test checks panic emitted from `mem::{uninitialized,zeroed}`.
|
// This test checks panic emitted from `mem::{uninitialized,zeroed}`.
|
||||||
|
|
||||||
#![feature(never_type)]
|
#![feature(never_type, arbitrary_enum_discriminant)]
|
||||||
#![allow(deprecated, invalid_value)]
|
#![allow(deprecated, invalid_value)]
|
||||||
|
|
||||||
use std::{
|
use std::{
|
||||||
|
|
7
src/test/ui/parser/issue-17383.rs
Normal file
7
src/test/ui/parser/issue-17383.rs
Normal file
|
@ -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() {}
|
15
src/test/ui/parser/issue-17383.stderr
Normal file
15
src/test/ui/parser/issue-17383.stderr
Normal file
|
@ -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`.
|
12
src/test/ui/parser/tag-variant-disr-non-nullary.rs
Normal file
12
src/test/ui/parser/tag-variant-disr-non-nullary.rs
Normal file
|
@ -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() {}
|
25
src/test/ui/parser/tag-variant-disr-non-nullary.stderr
Normal file
25
src/test/ui/parser/tag-variant-disr-non-nullary.stderr
Normal file
|
@ -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`.
|
Loading…
Add table
Add a link
Reference in a new issue