mirror of
https://github.com/rust-lang/rust.git
synced 2024-11-22 06:44:35 +00:00
Rollup merge of #95710 - fee1-dead-contrib:stabilize_arbitrary_enum_discriminant, r=joshtriplett
Stabilize arbitrary_enum_discriminant, take 2 Documentation has been updated in https://github.com/rust-lang/reference/pull/1055. cc #86860 for previous stabilization report. Not yet marks https://github.com/rust-lang/rust/issues/60553 as done: need documentation in the rust reference.
This commit is contained in:
commit
5b6455318a
@ -1,7 +1,7 @@
|
||||
use rustc_ast as ast;
|
||||
use rustc_ast::visit::{self, AssocCtxt, FnCtxt, FnKind, Visitor};
|
||||
use rustc_ast::{AssocConstraint, AssocConstraintKind, NodeId};
|
||||
use rustc_ast::{PatKind, RangeEnd, VariantData};
|
||||
use rustc_ast::{PatKind, RangeEnd};
|
||||
use rustc_errors::{struct_span_err, Applicability, StashKey};
|
||||
use rustc_feature::{AttributeGate, BuiltinAttribute, Features, GateIssue, BUILTIN_ATTRIBUTE_MAP};
|
||||
use rustc_session::parse::{feature_err, feature_err_issue, feature_warn};
|
||||
@ -116,46 +116,6 @@ 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();
|
||||
}
|
||||
}
|
||||
|
||||
/// Feature gate `impl Trait` inside `type Alias = $type_expr;`.
|
||||
fn check_impl_trait(&self, ty: &ast::Ty) {
|
||||
struct ImplTraitVisitor<'a> {
|
||||
@ -273,26 +233,6 @@ 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::Impl { polarity, defaultness, ref of_trait, .. }) => {
|
||||
if let ast::ImplPolarity::Negative(span) = polarity {
|
||||
gate_feature_post!(
|
||||
|
@ -3,8 +3,6 @@ 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,
|
||||
@ -20,8 +18,6 @@ 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,
|
||||
|
@ -53,6 +53,8 @@ declare_features! (
|
||||
(accepted, abi_sysv64, "1.24.0", Some(36167), None),
|
||||
/// Allows using ADX intrinsics from `core::arch::{x86, x86_64}`.
|
||||
(accepted, adx_target_feature, "1.61.0", Some(44839), None),
|
||||
/// Allows explicit discriminants on non-unit enum variants.
|
||||
(accepted, arbitrary_enum_discriminant, "CURRENT_RUSTC_VERSION", Some(60553), None),
|
||||
/// Allows using `sym` operands in inline assembly.
|
||||
(accepted, asm_sym, "CURRENT_RUSTC_VERSION", Some(93333), None),
|
||||
/// Allows the definition of associated constants in `trait` or `impl` blocks.
|
||||
|
@ -292,8 +292,6 @@ declare_features! (
|
||||
(incomplete, adt_const_params, "1.56.0", Some(95174), None),
|
||||
/// Allows defining an `#[alloc_error_handler]`.
|
||||
(active, alloc_error_handler, "1.29.0", Some(51540), None),
|
||||
/// Allows explicit discriminants on non-unit enum variants.
|
||||
(active, arbitrary_enum_discriminant, "1.37.0", Some(60553), None),
|
||||
/// Allows trait methods with arbitrary self types.
|
||||
(active, arbitrary_self_types, "1.23.0", Some(44874), None),
|
||||
/// Allows using `const` operands in inline assembly.
|
||||
|
@ -1180,7 +1180,7 @@ fn check_enum<'tcx>(tcx: TyCtxt<'tcx>, vs: &'tcx [hir::Variant<'tcx>], def_id: L
|
||||
}
|
||||
}
|
||||
|
||||
if tcx.adt_def(def_id).repr().int.is_none() && tcx.features().arbitrary_enum_discriminant {
|
||||
if tcx.adt_def(def_id).repr().int.is_none() {
|
||||
let is_unit = |var: &hir::Variant<'_>| matches!(var.data, hir::VariantData::Unit(..));
|
||||
|
||||
let has_disr = |var: &hir::Variant<'_>| var.disr_expr.is_some();
|
||||
|
@ -1,37 +0,0 @@
|
||||
# `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,5 +1,3 @@
|
||||
#![feature(arbitrary_enum_discriminant)]
|
||||
|
||||
#[repr(u8)]
|
||||
enum Kind2 {
|
||||
Foo() = 1,
|
||||
|
@ -1,5 +1,5 @@
|
||||
error[E0605]: non-primitive cast: `Kind2` as `u8`
|
||||
--> $DIR/issue-88621.rs:11:13
|
||||
--> $DIR/issue-88621.rs:9:13
|
||||
|
|
||||
LL | let _ = Kind2::Foo() as u8;
|
||||
| ^^^^^^^^^^^^^^^^^^ an `as` expression can only be used to convert between primitive types or to coerce to a specific trait object
|
||||
|
@ -1,5 +1,4 @@
|
||||
#![crate_type="lib"]
|
||||
#![feature(arbitrary_enum_discriminant)]
|
||||
|
||||
enum Enum {
|
||||
//~^ ERROR `#[repr(inttype)]` must be specified
|
||||
|
@ -1,5 +1,5 @@
|
||||
error[E0732]: `#[repr(inttype)]` must be specified
|
||||
--> $DIR/arbitrary_enum_discriminant-no-repr.rs:4:1
|
||||
--> $DIR/arbitrary_enum_discriminant-no-repr.rs:3:1
|
||||
|
|
||||
LL | enum Enum {
|
||||
| ^^^^^^^^^
|
||||
|
@ -1,5 +1,5 @@
|
||||
// run-pass
|
||||
#![feature(arbitrary_enum_discriminant, test)]
|
||||
#![feature(test)]
|
||||
|
||||
extern crate test;
|
||||
|
||||
|
@ -1,6 +1,6 @@
|
||||
// run-pass
|
||||
#![allow(stable_features)]
|
||||
#![feature(arbitrary_enum_discriminant, core, core_intrinsics)]
|
||||
#![feature(core, core_intrinsics)]
|
||||
|
||||
extern crate core;
|
||||
use core::intrinsics::discriminant_value;
|
||||
|
@ -1,10 +0,0 @@
|
||||
#![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
|
||||
}
|
@ -1,36 +0,0 @@
|
||||
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(arbitrary_enum_discriminant, core_intrinsics)]
|
||||
#![feature(core_intrinsics)]
|
||||
|
||||
extern crate core;
|
||||
use core::intrinsics::discriminant_value;
|
||||
|
@ -1,4 +1,4 @@
|
||||
#![feature(arbitrary_enum_discriminant, core_intrinsics)]
|
||||
#![feature(core_intrinsics)]
|
||||
|
||||
extern crate core;
|
||||
use core::intrinsics::discriminant_value;
|
||||
|
@ -1,5 +1,5 @@
|
||||
// run-pass
|
||||
#![feature(repr128, arbitrary_enum_discriminant)]
|
||||
#![feature(repr128)]
|
||||
//~^ WARN the feature `repr128` is incomplete
|
||||
|
||||
#[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
|
||||
--> $DIR/issue-70509-partial_eq.rs:2:12
|
||||
|
|
||||
LL | #![feature(repr128, arbitrary_enum_discriminant)]
|
||||
LL | #![feature(repr128)]
|
||||
| ^^^^^^^
|
||||
|
|
||||
= note: see issue #56071 <https://github.com/rust-lang/rust/issues/56071> for more information
|
||||
|
@ -7,7 +7,7 @@
|
||||
|
||||
// This test checks panic emitted from `mem::{uninitialized,zeroed}`.
|
||||
|
||||
#![feature(never_type, arbitrary_enum_discriminant)]
|
||||
#![feature(never_type)]
|
||||
#![allow(deprecated, invalid_value)]
|
||||
|
||||
use std::{
|
||||
|
@ -4,7 +4,7 @@
|
||||
// immediately, so that we get more errors listed at a time.
|
||||
|
||||
#![feature(trace_macros, concat_idents)]
|
||||
#![feature(stmt_expr_attributes, arbitrary_enum_discriminant)]
|
||||
#![feature(stmt_expr_attributes)]
|
||||
|
||||
use std::arch::asm;
|
||||
|
||||
|
@ -1,7 +0,0 @@
|
||||
enum X {
|
||||
A = 3,
|
||||
//~^ ERROR custom discriminant values are not allowed in enums with tuple or struct variants
|
||||
B(usize)
|
||||
}
|
||||
|
||||
fn main() {}
|
@ -1,15 +0,0 @@
|
||||
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`.
|
@ -1,12 +0,0 @@
|
||||
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() {}
|
@ -1,25 +0,0 @@
|
||||
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`.
|
@ -2,7 +2,6 @@
|
||||
//! The payloads of an enum variant should be ordered after its tag.
|
||||
|
||||
#![crate_type = "lib"]
|
||||
#![feature(arbitrary_enum_discriminant)]
|
||||
#![feature(transmutability)]
|
||||
#![allow(dead_code)]
|
||||
|
||||
|
@ -2,7 +2,6 @@
|
||||
//! an enum with a multi-byte tag.
|
||||
|
||||
#![crate_type = "lib"]
|
||||
#![feature(arbitrary_enum_discriminant)]
|
||||
#![feature(transmutability)]
|
||||
#![allow(dead_code)]
|
||||
|
||||
|
@ -1,12 +1,12 @@
|
||||
error[E0277]: `Src` cannot be safely transmuted into `Unexpected` in the defining scope of `assert::Context`.
|
||||
--> $DIR/should_respect_endianness.rs:37:36
|
||||
--> $DIR/should_respect_endianness.rs:36:36
|
||||
|
|
||||
LL | assert::is_transmutable::<Src, Unexpected>();
|
||||
| ^^^^^^^^^^ `Src` cannot be safely transmuted into `Unexpected` in the defining scope of `assert::Context`.
|
||||
|
|
||||
= help: the trait `BikeshedIntrinsicFrom<Src, assert::Context, Assume { alignment: true, lifetimes: true, safety: true, validity: true }>` is not implemented for `Unexpected`
|
||||
note: required by a bound in `is_transmutable`
|
||||
--> $DIR/should_respect_endianness.rs:15:14
|
||||
--> $DIR/should_respect_endianness.rs:14:14
|
||||
|
|
||||
LL | pub fn is_transmutable<Src, Dst>()
|
||||
| --------------- required by a bound in this
|
||||
|
Loading…
Reference in New Issue
Block a user