Skip to content

Commit 313e71a

Browse files
committed
Auto merge of #89884 - Mark-Simulacrum:revert-enum-discr, r=wesleywiser
Revert enum discriminants Reverts stabilization of arbitrary enum discriminants per #88621 (comment). Reopens #60553.
2 parents e1e9319 + 2284082 commit 313e71a

22 files changed

+221
-16
lines changed

RELEASES.md

-3
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,6 @@ Language
66

77
- [The 2021 Edition is now stable.][rust#88100]
88
See [the edition guide][rust-2021-edition-guide] for more details.
9-
- [You can now specify explicit discriminant values on any Rust enum.][rust#86860]
109
- [The pattern in `binding @ pattern` can now also introduce new bindings.][rust#85305]
1110
- [Union field access is permitted in `const fn`.][rust#85769]
1211

@@ -51,8 +50,6 @@ Stabilised APIs
5150
---------------
5251

5352
- [`std::os::unix::fs::chroot`]
54-
- [`Iterator::intersperse`]
55-
- [`Iterator::intersperse_with`]
5653
- [`UnsafeCell::raw_get`]
5754
- [`BufWriter::into_parts`]
5855
- [`core::panic::{UnwindSafe, RefUnwindSafe, AssertUnwindSafe}`]

compiler/rustc_ast_passes/src/feature_gate.rs

+62-2
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,11 @@
11
use rustc_ast as ast;
22
use rustc_ast::visit::{self, AssocCtxt, FnCtxt, FnKind, Visitor};
33
use rustc_ast::{AssocTyConstraint, AssocTyConstraintKind, NodeId};
4-
use rustc_ast::{PatKind, RangeEnd};
4+
use rustc_ast::{PatKind, RangeEnd, VariantData};
55
use rustc_errors::struct_span_err;
66
use rustc_feature::{AttributeGate, BUILTIN_ATTRIBUTE_MAP};
77
use rustc_feature::{Features, GateIssue};
8-
use rustc_session::parse::feature_err_issue;
8+
use rustc_session::parse::{feature_err, feature_err_issue};
99
use rustc_session::Session;
1010
use rustc_span::source_map::Spanned;
1111
use rustc_span::symbol::sym;
@@ -218,6 +218,46 @@ impl<'a> PostExpansionVisitor<'a> {
218218
}
219219
}
220220

221+
fn maybe_report_invalid_custom_discriminants(&self, variants: &[ast::Variant]) {
222+
let has_fields = variants.iter().any(|variant| match variant.data {
223+
VariantData::Tuple(..) | VariantData::Struct(..) => true,
224+
VariantData::Unit(..) => false,
225+
});
226+
227+
let discriminant_spans = variants
228+
.iter()
229+
.filter(|variant| match variant.data {
230+
VariantData::Tuple(..) | VariantData::Struct(..) => false,
231+
VariantData::Unit(..) => true,
232+
})
233+
.filter_map(|variant| variant.disr_expr.as_ref().map(|c| c.value.span))
234+
.collect::<Vec<_>>();
235+
236+
if !discriminant_spans.is_empty() && has_fields {
237+
let mut err = feature_err(
238+
&self.sess.parse_sess,
239+
sym::arbitrary_enum_discriminant,
240+
discriminant_spans.clone(),
241+
"custom discriminant values are not allowed in enums with tuple or struct variants",
242+
);
243+
for sp in discriminant_spans {
244+
err.span_label(sp, "disallowed custom discriminant");
245+
}
246+
for variant in variants.iter() {
247+
match &variant.data {
248+
VariantData::Struct(..) => {
249+
err.span_label(variant.span, "struct variant defined here");
250+
}
251+
VariantData::Tuple(..) => {
252+
err.span_label(variant.span, "tuple variant defined here");
253+
}
254+
VariantData::Unit(..) => {}
255+
}
256+
}
257+
err.emit();
258+
}
259+
}
260+
221261
fn check_gat(&self, generics: &ast::Generics, span: Span) {
222262
if !generics.params.is_empty() {
223263
gate_feature_post!(
@@ -363,6 +403,26 @@ impl<'a> Visitor<'a> for PostExpansionVisitor<'a> {
363403
}
364404
}
365405

406+
ast::ItemKind::Enum(ast::EnumDef { ref variants, .. }, ..) => {
407+
for variant in variants {
408+
match (&variant.data, &variant.disr_expr) {
409+
(ast::VariantData::Unit(..), _) => {}
410+
(_, Some(disr_expr)) => gate_feature_post!(
411+
&self,
412+
arbitrary_enum_discriminant,
413+
disr_expr.value.span,
414+
"discriminants on non-unit variants are experimental"
415+
),
416+
_ => {}
417+
}
418+
}
419+
420+
let has_feature = self.features.arbitrary_enum_discriminant;
421+
if !has_feature && !i.span.allows_unstable(sym::arbitrary_enum_discriminant) {
422+
self.maybe_report_invalid_custom_discriminants(&variants);
423+
}
424+
}
425+
366426
ast::ItemKind::Impl(box ast::ImplKind {
367427
polarity, defaultness, ref of_trait, ..
368428
}) => {

compiler/rustc_error_codes/src/error_codes/E0732.md

+4
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,8 @@ An `enum` with a discriminant must specify a `#[repr(inttype)]`.
33
Erroneous code example:
44

55
```compile_fail,E0732
6+
#![feature(arbitrary_enum_discriminant)]
7+
68
enum Enum { // error!
79
Unit = 1,
810
Tuple() = 2,
@@ -18,6 +20,8 @@ is a well-defined way to extract a variant's discriminant from a value;
1820
for instance:
1921

2022
```
23+
#![feature(arbitrary_enum_discriminant)]
24+
2125
#[repr(u8)]
2226
enum Enum {
2327
Unit = 3,

compiler/rustc_feature/src/accepted.rs

-2
Original file line numberDiff line numberDiff line change
@@ -293,8 +293,6 @@ declare_features! (
293293
(accepted, const_fn_transmute, "1.56.0", Some(53605), None),
294294
/// Allows accessing fields of unions inside `const` functions.
295295
(accepted, const_fn_union, "1.56.0", Some(51909), None),
296-
/// Allows explicit discriminants on non-unit enum variants.
297-
(accepted, arbitrary_enum_discriminant, "1.56.0", Some(60553), None),
298296
/// Allows macro attributes to observe output of `#[derive]`.
299297
(accepted, macro_attributes_in_derive_output, "1.57.0", Some(81119), None),
300298
/// Allows panicking during const eval (producing compile-time errors).

compiler/rustc_feature/src/active.rs

+3
Original file line numberDiff line numberDiff line change
@@ -464,6 +464,9 @@ declare_features! (
464464
/// Allows #[repr(transparent)] on unions (RFC 2645).
465465
(active, transparent_unions, "1.37.0", Some(60405), None),
466466

467+
/// Allows explicit discriminants on non-unit enum variants.
468+
(active, arbitrary_enum_discriminant, "1.37.0", Some(60553), None),
469+
467470
/// Allows `async || body` closures.
468471
(active, async_closure, "1.37.0", Some(62290), None),
469472

compiler/rustc_typeck/src/check/check.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -1374,7 +1374,7 @@ fn check_enum<'tcx>(
13741374
}
13751375
}
13761376

1377-
if tcx.adt_def(def_id).repr.int.is_none() {
1377+
if tcx.adt_def(def_id).repr.int.is_none() && tcx.features().arbitrary_enum_discriminant {
13781378
let is_unit = |var: &hir::Variant<'_>| matches!(var.data, hir::VariantData::Unit(..));
13791379

13801380
let has_disr = |var: &hir::Variant<'_>| var.disr_expr.is_some();
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
# `arbitrary_enum_discriminant`
2+
3+
The tracking issue for this feature is: [#60553]
4+
5+
[#60553]: https://github.com/rust-lang/rust/issues/60553
6+
7+
------------------------
8+
9+
The `arbitrary_enum_discriminant` feature permits tuple-like and
10+
struct-like enum variants with `#[repr(<int-type>)]` to have explicit discriminants.
11+
12+
## Examples
13+
14+
```rust
15+
#![feature(arbitrary_enum_discriminant)]
16+
17+
#[allow(dead_code)]
18+
#[repr(u8)]
19+
enum Enum {
20+
Unit = 3,
21+
Tuple(u16) = 2,
22+
Struct {
23+
a: u8,
24+
b: u16,
25+
} = 1,
26+
}
27+
28+
impl Enum {
29+
fn tag(&self) -> u8 {
30+
unsafe { *(self as *const Self as *const u8) }
31+
}
32+
}
33+
34+
assert_eq!(3, Enum::Unit.tag());
35+
assert_eq!(2, Enum::Tuple(5).tag());
36+
assert_eq!(1, Enum::Struct{a: 7, b: 11}.tag());
37+
```

src/test/ui/enum-discriminant/arbitrary_enum_discriminant-no-repr.rs

+1
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
#![crate_type="lib"]
2+
#![feature(arbitrary_enum_discriminant)]
23

34
enum Enum {
45
//~^ ERROR `#[repr(inttype)]` must be specified

src/test/ui/enum-discriminant/arbitrary_enum_discriminant-no-repr.stderr

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
error[E0732]: `#[repr(inttype)]` must be specified
2-
--> $DIR/arbitrary_enum_discriminant-no-repr.rs:3:1
2+
--> $DIR/arbitrary_enum_discriminant-no-repr.rs:4:1
33
|
44
LL | / enum Enum {
55
LL | |

src/test/ui/enum-discriminant/arbitrary_enum_discriminant.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
// run-pass
2-
#![feature(const_raw_ptr_deref, test)]
2+
#![feature(arbitrary_enum_discriminant, const_raw_ptr_deref, test)]
33

44
extern crate test;
55

src/test/ui/enum-discriminant/discriminant_value.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
// run-pass
22
#![allow(stable_features)]
3-
#![feature(core, core_intrinsics)]
3+
#![feature(arbitrary_enum_discriminant, core, core_intrinsics)]
44

55
extern crate core;
66
use core::intrinsics::discriminant_value;
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
#![crate_type="lib"]
2+
3+
enum Enum {
4+
Unit = 1,
5+
//~^ ERROR custom discriminant values are not allowed in enums with tuple or struct variants
6+
Tuple() = 2,
7+
//~^ ERROR discriminants on non-unit variants are experimental
8+
Struct{} = 3,
9+
//~^ ERROR discriminants on non-unit variants are experimental
10+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
error[E0658]: discriminants on non-unit variants are experimental
2+
--> $DIR/feature-gate-arbitrary_enum_discriminant.rs:6:13
3+
|
4+
LL | Tuple() = 2,
5+
| ^
6+
|
7+
= note: see issue #60553 <https://github.com/rust-lang/rust/issues/60553> for more information
8+
= help: add `#![feature(arbitrary_enum_discriminant)]` to the crate attributes to enable
9+
10+
error[E0658]: discriminants on non-unit variants are experimental
11+
--> $DIR/feature-gate-arbitrary_enum_discriminant.rs:8:14
12+
|
13+
LL | Struct{} = 3,
14+
| ^
15+
|
16+
= note: see issue #60553 <https://github.com/rust-lang/rust/issues/60553> for more information
17+
= help: add `#![feature(arbitrary_enum_discriminant)]` to the crate attributes to enable
18+
19+
error[E0658]: custom discriminant values are not allowed in enums with tuple or struct variants
20+
--> $DIR/feature-gate-arbitrary_enum_discriminant.rs:4:10
21+
|
22+
LL | Unit = 1,
23+
| ^ disallowed custom discriminant
24+
LL |
25+
LL | Tuple() = 2,
26+
| ----------- tuple variant defined here
27+
LL |
28+
LL | Struct{} = 3,
29+
| ------------ struct variant defined here
30+
|
31+
= note: see issue #60553 <https://github.com/rust-lang/rust/issues/60553> for more information
32+
= help: add `#![feature(arbitrary_enum_discriminant)]` to the crate attributes to enable
33+
34+
error: aborting due to 3 previous errors
35+
36+
For more information about this error, try `rustc --explain E0658`.

src/test/ui/enum-discriminant/issue-70453-generics-in-discr-ice-2.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
#![feature(core_intrinsics)]
1+
#![feature(arbitrary_enum_discriminant, core_intrinsics)]
22

33
extern crate core;
44
use core::intrinsics::discriminant_value;

src/test/ui/enum-discriminant/issue-70453-polymorphic-ctfe.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
#![feature(core_intrinsics)]
1+
#![feature(arbitrary_enum_discriminant, core_intrinsics)]
22

33
extern crate core;
44
use core::intrinsics::discriminant_value;

src/test/ui/enum-discriminant/issue-70509-partial_eq.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
// run-pass
2-
#![feature(repr128)]
2+
#![feature(repr128, arbitrary_enum_discriminant)]
33
//~^ WARN the feature `repr128` is incomplete
44

55
#[derive(PartialEq, Debug)]

src/test/ui/enum-discriminant/issue-70509-partial_eq.stderr

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
warning: the feature `repr128` is incomplete and may not be safe to use and/or cause compiler crashes
22
--> $DIR/issue-70509-partial_eq.rs:2:12
33
|
4-
LL | #![feature(repr128)]
4+
LL | #![feature(repr128, arbitrary_enum_discriminant)]
55
| ^^^^^^^
66
|
77
= note: `#[warn(incomplete_features)]` on by default

src/test/ui/intrinsics/panic-uninitialized-zeroed.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66

77
// This test checks panic emitted from `mem::{uninitialized,zeroed}`.
88

9-
#![feature(never_type)]
9+
#![feature(never_type, arbitrary_enum_discriminant)]
1010
#![allow(deprecated, invalid_value)]
1111

1212
use std::{

src/test/ui/parser/issue-17383.rs

+7
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
enum X {
2+
A = 3,
3+
//~^ ERROR custom discriminant values are not allowed in enums with tuple or struct variants
4+
B(usize)
5+
}
6+
7+
fn main() {}

src/test/ui/parser/issue-17383.stderr

+15
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
error[E0658]: custom discriminant values are not allowed in enums with tuple or struct variants
2+
--> $DIR/issue-17383.rs:2:9
3+
|
4+
LL | A = 3,
5+
| ^ disallowed custom discriminant
6+
LL |
7+
LL | B(usize)
8+
| -------- tuple variant defined here
9+
|
10+
= note: see issue #60553 <https://github.com/rust-lang/rust/issues/60553> for more information
11+
= help: add `#![feature(arbitrary_enum_discriminant)]` to the crate attributes to enable
12+
13+
error: aborting due to previous error
14+
15+
For more information about this error, try `rustc --explain E0658`.
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
enum Color {
2+
Red = 0xff0000,
3+
//~^ ERROR custom discriminant values are not allowed in enums with tuple or struct variants
4+
Green = 0x00ff00,
5+
Blue = 0x0000ff,
6+
Black = 0x000000,
7+
White = 0xffffff,
8+
Other(usize),
9+
Other2(usize, usize),
10+
}
11+
12+
fn main() {}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
error[E0658]: custom discriminant values are not allowed in enums with tuple or struct variants
2+
--> $DIR/tag-variant-disr-non-nullary.rs:2:11
3+
|
4+
LL | Red = 0xff0000,
5+
| ^^^^^^^^ disallowed custom discriminant
6+
LL |
7+
LL | Green = 0x00ff00,
8+
| ^^^^^^^^ disallowed custom discriminant
9+
LL | Blue = 0x0000ff,
10+
| ^^^^^^^^ disallowed custom discriminant
11+
LL | Black = 0x000000,
12+
| ^^^^^^^^ disallowed custom discriminant
13+
LL | White = 0xffffff,
14+
| ^^^^^^^^ disallowed custom discriminant
15+
LL | Other(usize),
16+
| ------------ tuple variant defined here
17+
LL | Other2(usize, usize),
18+
| -------------------- tuple variant defined here
19+
|
20+
= note: see issue #60553 <https://github.com/rust-lang/rust/issues/60553> for more information
21+
= help: add `#![feature(arbitrary_enum_discriminant)]` to the crate attributes to enable
22+
23+
error: aborting due to previous error
24+
25+
For more information about this error, try `rustc --explain E0658`.

0 commit comments

Comments
 (0)