summaryrefslogtreecommitdiffstats
path: root/src/test/ui/enum
diff options
context:
space:
mode:
authorDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-17 12:02:58 +0000
committerDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-17 12:02:58 +0000
commit698f8c2f01ea549d77d7dc3338a12e04c11057b9 (patch)
tree173a775858bd501c378080a10dca74132f05bc50 /src/test/ui/enum
parentInitial commit. (diff)
downloadrustc-698f8c2f01ea549d77d7dc3338a12e04c11057b9.tar.xz
rustc-698f8c2f01ea549d77d7dc3338a12e04c11057b9.zip
Adding upstream version 1.64.0+dfsg1.upstream/1.64.0+dfsg1
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to '')
-rw-r--r--src/test/ui/enum-discriminant/actually_not_an_enum-discriminant.rs49
-rw-r--r--src/test/ui/enum-discriminant/arbitrary_enum_discriminant-no-repr.rs9
-rw-r--r--src/test/ui/enum-discriminant/arbitrary_enum_discriminant-no-repr.stderr9
-rw-r--r--src/test/ui/enum-discriminant/arbitrary_enum_discriminant.rs43
-rw-r--r--src/test/ui/enum-discriminant/discriminant_size.rs54
-rw-r--r--src/test/ui/enum-discriminant/discriminant_size.stderr11
-rw-r--r--src/test/ui/enum-discriminant/discriminant_value-wrapper.rs20
-rw-r--r--src/test/ui/enum-discriminant/discriminant_value.rs82
-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/forbidden-discriminant-kind-impl.rs14
-rw-r--r--src/test/ui/enum-discriminant/forbidden-discriminant-kind-impl.stderr9
-rw-r--r--src/test/ui/enum-discriminant/issue-43398.rs14
-rw-r--r--src/test/ui/enum-discriminant/issue-43398.stderr11
-rw-r--r--src/test/ui/enum-discriminant/issue-51582.rs18
-rw-r--r--src/test/ui/enum-discriminant/issue-70453-generics-in-discr-ice-2.rs16
-rw-r--r--src/test/ui/enum-discriminant/issue-70453-generics-in-discr-ice-2.stderr11
-rw-r--r--src/test/ui/enum-discriminant/issue-70453-generics-in-discr-ice.rs17
-rw-r--r--src/test/ui/enum-discriminant/issue-70453-generics-in-discr-ice.stderr21
-rw-r--r--src/test/ui/enum-discriminant/issue-70453-polymorphic-ctfe.rs16
-rw-r--r--src/test/ui/enum-discriminant/issue-70453-polymorphic-ctfe.stderr11
-rw-r--r--src/test/ui/enum-discriminant/issue-70509-partial_eq.rs18
-rw-r--r--src/test/ui/enum-discriminant/issue-70509-partial_eq.stderr11
-rw-r--r--src/test/ui/enum-discriminant/issue-90038.rs21
-rw-r--r--src/test/ui/enum-discriminant/niche-prefer-zero.rs14
-rw-r--r--src/test/ui/enum-discriminant/niche.rs109
-rw-r--r--src/test/ui/enum-discriminant/repr128.rs45
-rw-r--r--src/test/ui/enum-discriminant/repr128.stderr11
-rw-r--r--src/test/ui/enum/enum-and-module-in-same-scope.rs10
-rw-r--r--src/test/ui/enum/enum-and-module-in-same-scope.stderr14
-rw-r--r--src/test/ui/enum/enum-discrim-autosizing.rs14
-rw-r--r--src/test/ui/enum/enum-discrim-autosizing.stderr15
-rw-r--r--src/test/ui/enum/enum-discrim-too-small.rs38
-rw-r--r--src/test/ui/enum/enum-discrim-too-small.stderr35
-rw-r--r--src/test/ui/enum/enum-discrim-too-small2.rs37
-rw-r--r--src/test/ui/enum/enum-discrim-too-small2.stderr43
-rw-r--r--src/test/ui/enum/enum-in-scope.rs7
-rw-r--r--src/test/ui/enum/enum-in-scope.stderr12
-rw-r--r--src/test/ui/enum/enum-size-variance.rs35
-rw-r--r--src/test/ui/enum/enum-size-variance.stderr14
-rw-r--r--src/test/ui/enum/enum-to-float-cast-2.rs18
-rw-r--r--src/test/ui/enum/enum-to-float-cast-2.stderr19
-rw-r--r--src/test/ui/enum/enum-to-float-cast.rs21
-rw-r--r--src/test/ui/enum/enum-to-float-cast.stderr19
-rw-r--r--src/test/ui/enum/enum-variant-type-2.rs9
-rw-r--r--src/test/ui/enum/enum-variant-type-2.stderr12
-rw-r--r--src/test/ui/enum/issue-42747.rs46
-rw-r--r--src/test/ui/enum/issue-67945-1.rs8
-rw-r--r--src/test/ui/enum/issue-67945-1.stderr21
-rw-r--r--src/test/ui/enum/issue-67945-2.rs8
-rw-r--r--src/test/ui/enum/issue-67945-2.stderr21
-rw-r--r--src/test/ui/enum/nested-enum.rs8
-rw-r--r--src/test/ui/enum/nested-enum.stderr26
-rw-r--r--src/test/ui/enum/suggest-default-attribute.rs8
-rw-r--r--src/test/ui/enum/suggest-default-attribute.stderr14
-rw-r--r--src/test/ui/enum/union-in-enum.rs13
56 files changed, 1255 insertions, 0 deletions
diff --git a/src/test/ui/enum-discriminant/actually_not_an_enum-discriminant.rs b/src/test/ui/enum-discriminant/actually_not_an_enum-discriminant.rs
new file mode 100644
index 000000000..6a566ab3a
--- /dev/null
+++ b/src/test/ui/enum-discriminant/actually_not_an_enum-discriminant.rs
@@ -0,0 +1,49 @@
+// run-pass
+#![feature(core_intrinsics)]
+
+use std::intrinsics::discriminant_value;
+
+struct Zst;
+
+struct Struct {
+ _a: u32,
+}
+
+union Union {
+ _a: u32,
+}
+
+fn check(v: u8) {
+ assert_eq!(v, 0);
+}
+
+pub fn generic<T>()
+where
+ for<'a> T: Fn(&'a isize),
+{
+ let v: Vec<T> = Vec::new();
+ let _: u8 = discriminant_value(&v);
+}
+
+fn main() {
+ // check that we use `u8` as the discriminant value
+ // for everything that is not an enum.
+ check(discriminant_value(&true));
+ check(discriminant_value(&'a'));
+ check(discriminant_value(&7));
+ check(discriminant_value(&7.0));
+ check(discriminant_value(&Zst));
+ check(discriminant_value(&Struct { _a: 7 }));
+ check(discriminant_value(&Union { _a: 7 }));
+ check(discriminant_value(&[7, 77]));
+ check(discriminant_value(&(7 as *const ())));
+ check(discriminant_value(&(7 as *mut ())));
+ check(discriminant_value(&&7));
+ check(discriminant_value(&&mut 7));
+ check(discriminant_value(&check));
+ let fn_ptr: fn(u8) = check;
+ check(discriminant_value(&fn_ptr));
+ let hrtb: for<'a> fn(&'a str) -> &'a str = |x| x;
+ check(discriminant_value(&hrtb));
+ check(discriminant_value(&(7, 77, 777)));
+}
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
new file mode 100644
index 000000000..4da7b5ab2
--- /dev/null
+++ b/src/test/ui/enum-discriminant/arbitrary_enum_discriminant-no-repr.rs
@@ -0,0 +1,9 @@
+#![crate_type="lib"]
+#![feature(arbitrary_enum_discriminant)]
+
+enum Enum {
+//~^ ERROR `#[repr(inttype)]` must be specified
+ Unit = 1,
+ Tuple() = 2,
+ Struct{} = 3,
+}
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
new file mode 100644
index 000000000..803bb06fc
--- /dev/null
+++ b/src/test/ui/enum-discriminant/arbitrary_enum_discriminant-no-repr.stderr
@@ -0,0 +1,9 @@
+error[E0732]: `#[repr(inttype)]` must be specified
+ --> $DIR/arbitrary_enum_discriminant-no-repr.rs:4:1
+ |
+LL | enum Enum {
+ | ^^^^^^^^^
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0732`.
diff --git a/src/test/ui/enum-discriminant/arbitrary_enum_discriminant.rs b/src/test/ui/enum-discriminant/arbitrary_enum_discriminant.rs
new file mode 100644
index 000000000..ccc423e4a
--- /dev/null
+++ b/src/test/ui/enum-discriminant/arbitrary_enum_discriminant.rs
@@ -0,0 +1,43 @@
+// run-pass
+#![feature(arbitrary_enum_discriminant, test)]
+
+extern crate test;
+
+use test::black_box;
+
+#[allow(dead_code)]
+#[repr(u8)]
+enum Enum {
+ Unit = 3,
+ Tuple(u16) = 2,
+ Struct {
+ a: u8,
+ b: u16,
+ } = 1,
+}
+
+impl Enum {
+ const unsafe fn tag(&self) -> u8 {
+ *(self as *const Self as *const u8)
+ }
+}
+
+fn main() {
+ const UNIT: Enum = Enum::Unit;
+ const TUPLE: Enum = Enum::Tuple(5);
+ const STRUCT: Enum = Enum::Struct{a: 7, b: 11};
+
+ // Ensure discriminants are correct during runtime execution
+ assert_eq!(3, unsafe { black_box(UNIT).tag() });
+ assert_eq!(2, unsafe { black_box(TUPLE).tag() });
+ assert_eq!(1, unsafe { black_box(STRUCT).tag() });
+
+ // Ensure discriminants are correct during CTFE
+ const UNIT_TAG: u8 = unsafe { UNIT.tag() };
+ const TUPLE_TAG: u8 = unsafe { TUPLE.tag() };
+ const STRUCT_TAG: u8 = unsafe { STRUCT.tag() };
+
+ assert_eq!(3, UNIT_TAG);
+ assert_eq!(2, TUPLE_TAG);
+ assert_eq!(1, STRUCT_TAG);
+}
diff --git a/src/test/ui/enum-discriminant/discriminant_size.rs b/src/test/ui/enum-discriminant/discriminant_size.rs
new file mode 100644
index 000000000..b939a70df
--- /dev/null
+++ b/src/test/ui/enum-discriminant/discriminant_size.rs
@@ -0,0 +1,54 @@
+// run-pass
+#![feature(core_intrinsics, repr128)]
+//~^ WARN the feature `repr128` is incomplete
+
+use std::intrinsics::discriminant_value;
+
+enum E1 {
+ A,
+ B,
+}
+
+#[repr(i8)]
+enum E2 {
+ A = 7,
+ B = -2,
+}
+
+#[repr(C)]
+enum E3 {
+ A = 42,
+ B = 100,
+}
+
+#[repr(i128)]
+enum E4 {
+ A = 0x1223_3445_5667_7889,
+ B = -0x1223_3445_5667_7889,
+}
+
+fn main() {
+ let mut target: [isize; 3] = [0, 0, 0];
+ target[1] = discriminant_value(&E1::A);
+ assert_eq!(target, [0, 0, 0]);
+ target[1] = discriminant_value(&E1::B);
+ assert_eq!(target, [0, 1, 0]);
+
+ let mut target: [i8; 3] = [0, 0, 0];
+ target[1] = discriminant_value(&E2::A);
+ assert_eq!(target, [0, 7, 0]);
+ target[1] = discriminant_value(&E2::B);
+ assert_eq!(target, [0, -2, 0]);
+
+ let mut target: [isize; 3] = [0, 0, 0];
+ target[1] = discriminant_value(&E3::A);
+ assert_eq!(target, [0, 42, 0]);
+ target[1] = discriminant_value(&E3::B);
+ assert_eq!(target, [0, 100, 0]);
+
+ let mut target: [i128; 3] = [0, 0, 0];
+ target[1] = discriminant_value(&E4::A);
+ assert_eq!(target, [0, 0x1223_3445_5667_7889, 0]);
+ target[1] = discriminant_value(&E4::B);
+ assert_eq!(target, [0, -0x1223_3445_5667_7889, 0]);
+}
diff --git a/src/test/ui/enum-discriminant/discriminant_size.stderr b/src/test/ui/enum-discriminant/discriminant_size.stderr
new file mode 100644
index 000000000..efc7d9984
--- /dev/null
+++ b/src/test/ui/enum-discriminant/discriminant_size.stderr
@@ -0,0 +1,11 @@
+warning: the feature `repr128` is incomplete and may not be safe to use and/or cause compiler crashes
+ --> $DIR/discriminant_size.rs:2:29
+ |
+LL | #![feature(core_intrinsics, repr128)]
+ | ^^^^^^^
+ |
+ = note: `#[warn(incomplete_features)]` on by default
+ = note: see issue #56071 <https://github.com/rust-lang/rust/issues/56071> for more information
+
+warning: 1 warning emitted
+
diff --git a/src/test/ui/enum-discriminant/discriminant_value-wrapper.rs b/src/test/ui/enum-discriminant/discriminant_value-wrapper.rs
new file mode 100644
index 000000000..8e162d5c4
--- /dev/null
+++ b/src/test/ui/enum-discriminant/discriminant_value-wrapper.rs
@@ -0,0 +1,20 @@
+// run-pass
+
+#![allow(enum_intrinsics_non_enums)]
+
+use std::mem;
+
+#[allow(unused_tuple_struct_fields)]
+enum ADT {
+ First(u32, u32),
+ Second(u64)
+}
+
+pub fn main() {
+ assert!(mem::discriminant(&ADT::First(0,0)) == mem::discriminant(&ADT::First(1,1)));
+ assert!(mem::discriminant(&ADT::Second(5)) == mem::discriminant(&ADT::Second(6)));
+ assert!(mem::discriminant(&ADT::First(2,2)) != mem::discriminant(&ADT::Second(2)));
+
+ let _ = mem::discriminant(&10);
+ let _ = mem::discriminant(&"test");
+}
diff --git a/src/test/ui/enum-discriminant/discriminant_value.rs b/src/test/ui/enum-discriminant/discriminant_value.rs
new file mode 100644
index 000000000..65ab411db
--- /dev/null
+++ b/src/test/ui/enum-discriminant/discriminant_value.rs
@@ -0,0 +1,82 @@
+// run-pass
+#![allow(stable_features)]
+#![feature(arbitrary_enum_discriminant, core, core_intrinsics)]
+
+extern crate core;
+use core::intrinsics::discriminant_value;
+
+enum CLike1 {
+ A,
+ B,
+ C,
+ D
+}
+
+enum CLike2 {
+ A = 5,
+ B = 2,
+ C = 19,
+ D
+}
+
+#[repr(i8)]
+enum CLike3 {
+ A = 5,
+ B,
+ C = -1,
+ D
+}
+
+#[allow(unused_tuple_struct_fields)]
+enum ADT {
+ First(u32, u32),
+ Second(u64)
+}
+
+enum NullablePointer {
+ Something(#[allow(unused_tuple_struct_fields)] &'static u32),
+ Nothing
+}
+
+static CONST : u32 = 0xBEEF;
+
+#[allow(dead_code)]
+#[repr(isize)]
+enum Mixed {
+ Unit = 3,
+ Tuple(u16) = 2,
+ Struct {
+ a: u8,
+ b: u16,
+ } = 1,
+}
+
+pub fn main() {
+ assert_eq!(discriminant_value(&CLike1::A), 0isize);
+ assert_eq!(discriminant_value(&CLike1::B), 1);
+ assert_eq!(discriminant_value(&CLike1::C), 2);
+ assert_eq!(discriminant_value(&CLike1::D), 3);
+
+ assert_eq!(discriminant_value(&CLike2::A), 5isize);
+ assert_eq!(discriminant_value(&CLike2::B), 2);
+ assert_eq!(discriminant_value(&CLike2::C), 19);
+ assert_eq!(discriminant_value(&CLike2::D), 20);
+
+ assert_eq!(discriminant_value(&CLike3::A), 5i8);
+ assert_eq!(discriminant_value(&CLike3::B), 6);
+ assert_eq!(discriminant_value(&CLike3::C), -1);
+ assert_eq!(discriminant_value(&CLike3::D), 0);
+
+ assert_eq!(discriminant_value(&ADT::First(0,0)), 0isize);
+ assert_eq!(discriminant_value(&ADT::Second(5)), 1);
+
+ assert_eq!(discriminant_value(&NullablePointer::Nothing), 1isize);
+ assert_eq!(discriminant_value(&NullablePointer::Something(&CONST)), 0);
+
+ assert_eq!(discriminant_value(&10), 0u8);
+ assert_eq!(discriminant_value(&"test"), 0u8);
+
+ assert_eq!(discriminant_value(&Mixed::Unit), 3isize);
+ assert_eq!(discriminant_value(&Mixed::Tuple(5)), 2);
+ assert_eq!(discriminant_value(&Mixed::Struct{a: 7, b: 11}), 1);
+}
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 000000000..3e90af4d3
--- /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 000000000..b5f61e6e9
--- /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/forbidden-discriminant-kind-impl.rs b/src/test/ui/enum-discriminant/forbidden-discriminant-kind-impl.rs
new file mode 100644
index 000000000..4760ca548
--- /dev/null
+++ b/src/test/ui/enum-discriminant/forbidden-discriminant-kind-impl.rs
@@ -0,0 +1,14 @@
+#![feature(discriminant_kind)]
+
+use std::marker::DiscriminantKind;
+
+enum Uninhabited {}
+
+struct NewType;
+
+impl DiscriminantKind for NewType {
+ //~^ ERROR explicit impls for the `DiscriminantKind` trait are not permitted
+ type Discriminant = Uninhabited;
+}
+
+fn main() {}
diff --git a/src/test/ui/enum-discriminant/forbidden-discriminant-kind-impl.stderr b/src/test/ui/enum-discriminant/forbidden-discriminant-kind-impl.stderr
new file mode 100644
index 000000000..38cfd13b9
--- /dev/null
+++ b/src/test/ui/enum-discriminant/forbidden-discriminant-kind-impl.stderr
@@ -0,0 +1,9 @@
+error[E0322]: explicit impls for the `DiscriminantKind` trait are not permitted
+ --> $DIR/forbidden-discriminant-kind-impl.rs:9:1
+ |
+LL | impl DiscriminantKind for NewType {
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ impl of `DiscriminantKind` not allowed
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0322`.
diff --git a/src/test/ui/enum-discriminant/issue-43398.rs b/src/test/ui/enum-discriminant/issue-43398.rs
new file mode 100644
index 000000000..581db033f
--- /dev/null
+++ b/src/test/ui/enum-discriminant/issue-43398.rs
@@ -0,0 +1,14 @@
+// run-pass
+
+#![feature(core_intrinsics)]
+#![feature(repr128)]
+//~^ WARN the feature `repr128` is incomplete
+
+#[repr(i128)]
+enum Big { A, B }
+
+fn main() {
+ println!("{} {:?}",
+ std::intrinsics::discriminant_value(&Big::A),
+ std::mem::discriminant(&Big::B));
+}
diff --git a/src/test/ui/enum-discriminant/issue-43398.stderr b/src/test/ui/enum-discriminant/issue-43398.stderr
new file mode 100644
index 000000000..9a394153b
--- /dev/null
+++ b/src/test/ui/enum-discriminant/issue-43398.stderr
@@ -0,0 +1,11 @@
+warning: the feature `repr128` is incomplete and may not be safe to use and/or cause compiler crashes
+ --> $DIR/issue-43398.rs:4:12
+ |
+LL | #![feature(repr128)]
+ | ^^^^^^^
+ |
+ = note: `#[warn(incomplete_features)]` on by default
+ = note: see issue #56071 <https://github.com/rust-lang/rust/issues/56071> for more information
+
+warning: 1 warning emitted
+
diff --git a/src/test/ui/enum-discriminant/issue-51582.rs b/src/test/ui/enum-discriminant/issue-51582.rs
new file mode 100644
index 000000000..40a70c623
--- /dev/null
+++ b/src/test/ui/enum-discriminant/issue-51582.rs
@@ -0,0 +1,18 @@
+// run-pass
+#![feature(core_intrinsics)]
+
+#[repr(i8)]
+pub enum Enum {
+ VariantA,
+ VariantB,
+}
+
+fn make_b() -> Enum { Enum::VariantB }
+
+fn main() {
+ assert_eq!(1, make_b() as i8);
+ assert_eq!(1, make_b() as u8);
+ assert_eq!(1, make_b() as i32);
+ assert_eq!(1, make_b() as u32);
+ assert_eq!(1, std::intrinsics::discriminant_value(&make_b()));
+}
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
new file mode 100644
index 000000000..f927dd189
--- /dev/null
+++ b/src/test/ui/enum-discriminant/issue-70453-generics-in-discr-ice-2.rs
@@ -0,0 +1,16 @@
+#![feature(arbitrary_enum_discriminant, core_intrinsics)]
+
+extern crate core;
+use core::intrinsics::discriminant_value;
+
+#[repr(usize)]
+enum MyWeirdOption<T> {
+ None = 0,
+ Some(T) = std::mem::size_of::<T>(),
+ //~^ ERROR generic parameters may not be used in const operations
+}
+
+fn main() {
+ assert_eq!(discriminant_value(&MyWeirdOption::<u8>::None), 0);
+ assert_eq!(discriminant_value(&MyWeirdOption::Some(0u8)), 1);
+}
diff --git a/src/test/ui/enum-discriminant/issue-70453-generics-in-discr-ice-2.stderr b/src/test/ui/enum-discriminant/issue-70453-generics-in-discr-ice-2.stderr
new file mode 100644
index 000000000..e4e10468d
--- /dev/null
+++ b/src/test/ui/enum-discriminant/issue-70453-generics-in-discr-ice-2.stderr
@@ -0,0 +1,11 @@
+error: generic parameters may not be used in const operations
+ --> $DIR/issue-70453-generics-in-discr-ice-2.rs:9:35
+ |
+LL | Some(T) = std::mem::size_of::<T>(),
+ | ^ cannot perform const operation using `T`
+ |
+ = note: type parameters may not be used in const expressions
+ = help: use `#![feature(generic_const_exprs)]` to allow generic const expressions
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/enum-discriminant/issue-70453-generics-in-discr-ice.rs b/src/test/ui/enum-discriminant/issue-70453-generics-in-discr-ice.rs
new file mode 100644
index 000000000..a0fb788a5
--- /dev/null
+++ b/src/test/ui/enum-discriminant/issue-70453-generics-in-discr-ice.rs
@@ -0,0 +1,17 @@
+#![feature(core_intrinsics)]
+
+extern crate core;
+use core::intrinsics::discriminant_value;
+
+#[repr(usize)]
+enum MyWeirdOption<T> {
+//~^ ERROR parameter `T` is never used
+ None = 0,
+ Some = std::mem::size_of::<T>(),
+ //~^ ERROR generic parameters may not be used in const operations
+}
+
+fn main() {
+ assert_eq!(discriminant_value(&MyWeirdOption::<u8>::None), 0);
+ assert_eq!(discriminant_value(&MyWeirdOption::<u8>::Some), 1);
+}
diff --git a/src/test/ui/enum-discriminant/issue-70453-generics-in-discr-ice.stderr b/src/test/ui/enum-discriminant/issue-70453-generics-in-discr-ice.stderr
new file mode 100644
index 000000000..7ea8a3912
--- /dev/null
+++ b/src/test/ui/enum-discriminant/issue-70453-generics-in-discr-ice.stderr
@@ -0,0 +1,21 @@
+error: generic parameters may not be used in const operations
+ --> $DIR/issue-70453-generics-in-discr-ice.rs:10:32
+ |
+LL | Some = std::mem::size_of::<T>(),
+ | ^ cannot perform const operation using `T`
+ |
+ = note: type parameters may not be used in const expressions
+ = help: use `#![feature(generic_const_exprs)]` to allow generic const expressions
+
+error[E0392]: parameter `T` is never used
+ --> $DIR/issue-70453-generics-in-discr-ice.rs:7:20
+ |
+LL | enum MyWeirdOption<T> {
+ | ^ unused parameter
+ |
+ = help: consider removing `T`, referring to it in a field, or using a marker such as `PhantomData`
+ = help: if you intended `T` to be a const parameter, use `const T: usize` instead
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0392`.
diff --git a/src/test/ui/enum-discriminant/issue-70453-polymorphic-ctfe.rs b/src/test/ui/enum-discriminant/issue-70453-polymorphic-ctfe.rs
new file mode 100644
index 000000000..e62582fb5
--- /dev/null
+++ b/src/test/ui/enum-discriminant/issue-70453-polymorphic-ctfe.rs
@@ -0,0 +1,16 @@
+#![feature(arbitrary_enum_discriminant, core_intrinsics)]
+
+extern crate core;
+use core::intrinsics::discriminant_value;
+
+#[repr(usize)]
+enum MyWeirdOption<T> {
+ None = 0,
+ Some(T) = core::mem::size_of::<*mut T>(),
+ //~^ ERROR generic parameters may not be used
+}
+
+fn main() {
+ assert_eq!(discriminant_value(&MyWeirdOption::<()>::None), 0);
+ assert_eq!(discriminant_value(&MyWeirdOption::Some(())), core::mem::size_of::<usize>());
+}
diff --git a/src/test/ui/enum-discriminant/issue-70453-polymorphic-ctfe.stderr b/src/test/ui/enum-discriminant/issue-70453-polymorphic-ctfe.stderr
new file mode 100644
index 000000000..0a7a63160
--- /dev/null
+++ b/src/test/ui/enum-discriminant/issue-70453-polymorphic-ctfe.stderr
@@ -0,0 +1,11 @@
+error: generic parameters may not be used in const operations
+ --> $DIR/issue-70453-polymorphic-ctfe.rs:9:41
+ |
+LL | Some(T) = core::mem::size_of::<*mut T>(),
+ | ^ cannot perform const operation using `T`
+ |
+ = note: type parameters may not be used in const expressions
+ = help: use `#![feature(generic_const_exprs)]` to allow generic const expressions
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/enum-discriminant/issue-70509-partial_eq.rs b/src/test/ui/enum-discriminant/issue-70509-partial_eq.rs
new file mode 100644
index 000000000..ae389e114
--- /dev/null
+++ b/src/test/ui/enum-discriminant/issue-70509-partial_eq.rs
@@ -0,0 +1,18 @@
+// run-pass
+#![feature(repr128, arbitrary_enum_discriminant)]
+//~^ WARN the feature `repr128` is incomplete
+
+#[derive(PartialEq, Debug)]
+#[repr(i128)]
+enum Test {
+ A(Box<u64>) = 0,
+ B(usize) = u64::MAX as i128 + 1,
+}
+
+fn main() {
+ assert_ne!(Test::A(Box::new(2)), Test::B(0));
+ // This previously caused a segfault.
+ //
+ // See https://github.com/rust-lang/rust/issues/70509#issuecomment-620654186
+ // for a detailed explanation.
+}
diff --git a/src/test/ui/enum-discriminant/issue-70509-partial_eq.stderr b/src/test/ui/enum-discriminant/issue-70509-partial_eq.stderr
new file mode 100644
index 000000000..5bf6ea56e
--- /dev/null
+++ b/src/test/ui/enum-discriminant/issue-70509-partial_eq.stderr
@@ -0,0 +1,11 @@
+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)]
+ | ^^^^^^^
+ |
+ = note: `#[warn(incomplete_features)]` on by default
+ = note: see issue #56071 <https://github.com/rust-lang/rust/issues/56071> for more information
+
+warning: 1 warning emitted
+
diff --git a/src/test/ui/enum-discriminant/issue-90038.rs b/src/test/ui/enum-discriminant/issue-90038.rs
new file mode 100644
index 000000000..5e98eccd9
--- /dev/null
+++ b/src/test/ui/enum-discriminant/issue-90038.rs
@@ -0,0 +1,21 @@
+// run-pass
+
+#[repr(u32)]
+pub enum Foo {
+ // Greater than or equal to 2
+ A = 2,
+}
+
+pub enum Bar {
+ A(Foo),
+ // More than two const variants
+ B,
+ C,
+}
+
+fn main() {
+ match Bar::A(Foo::A) {
+ Bar::A(_) => (),
+ _ => unreachable!(),
+ }
+}
diff --git a/src/test/ui/enum-discriminant/niche-prefer-zero.rs b/src/test/ui/enum-discriminant/niche-prefer-zero.rs
new file mode 100644
index 000000000..f20607a89
--- /dev/null
+++ b/src/test/ui/enum-discriminant/niche-prefer-zero.rs
@@ -0,0 +1,14 @@
+// Check that niche selection prefers zero.
+// See https://github.com/rust-lang/rust/pull/87794
+// run-pass
+#[repr(u8)]
+pub enum Size {
+ One = 1,
+ Two = 2,
+ Three = 3,
+}
+
+fn main() {
+ // check that `None` is zero
+ assert_eq!(0, unsafe { std::mem::transmute::<Option<Size>, u8>(None) });
+}
diff --git a/src/test/ui/enum-discriminant/niche.rs b/src/test/ui/enum-discriminant/niche.rs
new file mode 100644
index 000000000..8d3061050
--- /dev/null
+++ b/src/test/ui/enum-discriminant/niche.rs
@@ -0,0 +1,109 @@
+// run-pass
+
+//! Make sure that we read and write enum discriminants correctly for corner cases caused
+//! by layout optimizations.
+
+const OVERFLOW: usize = {
+ // Tests for https://github.com/rust-lang/rust/issues/62138.
+ #[repr(u8)]
+ #[allow(dead_code)]
+ enum WithWraparoundInvalidValues {
+ X = 1,
+ Y = 254,
+ }
+
+ #[allow(dead_code)]
+ enum Foo {
+ A,
+ B,
+ C(WithWraparoundInvalidValues),
+ }
+
+ let x = Foo::B;
+ match x {
+ Foo::B => 0,
+ _ => panic!(),
+ }
+};
+
+const MORE_OVERFLOW: usize = {
+ pub enum Infallible {}
+
+ // The check that the `bool` field of `V1` is encoding a "niche variant"
+ // (i.e. not `V1`, so `V3` or `V4`) used to be mathematically incorrect,
+ // causing valid `V1` values to be interpreted as other variants.
+ #[allow(dead_code)]
+ pub enum E1 {
+ V1 { f: bool },
+ V2 { f: Infallible },
+ V3,
+ V4,
+ }
+
+ // Computing the discriminant used to be done using the niche type (here `u8`,
+ // from the `bool` field of `V1`), overflowing for variants with large enough
+ // indices (`V3` and `V4`), causing them to be interpreted as other variants.
+ #[allow(dead_code)]
+ pub enum E2<X> {
+ V1 { f: bool },
+
+ /*_00*/ _01(X), _02(X), _03(X), _04(X), _05(X), _06(X), _07(X),
+ _08(X), _09(X), _0A(X), _0B(X), _0C(X), _0D(X), _0E(X), _0F(X),
+ _10(X), _11(X), _12(X), _13(X), _14(X), _15(X), _16(X), _17(X),
+ _18(X), _19(X), _1A(X), _1B(X), _1C(X), _1D(X), _1E(X), _1F(X),
+ _20(X), _21(X), _22(X), _23(X), _24(X), _25(X), _26(X), _27(X),
+ _28(X), _29(X), _2A(X), _2B(X), _2C(X), _2D(X), _2E(X), _2F(X),
+ _30(X), _31(X), _32(X), _33(X), _34(X), _35(X), _36(X), _37(X),
+ _38(X), _39(X), _3A(X), _3B(X), _3C(X), _3D(X), _3E(X), _3F(X),
+ _40(X), _41(X), _42(X), _43(X), _44(X), _45(X), _46(X), _47(X),
+ _48(X), _49(X), _4A(X), _4B(X), _4C(X), _4D(X), _4E(X), _4F(X),
+ _50(X), _51(X), _52(X), _53(X), _54(X), _55(X), _56(X), _57(X),
+ _58(X), _59(X), _5A(X), _5B(X), _5C(X), _5D(X), _5E(X), _5F(X),
+ _60(X), _61(X), _62(X), _63(X), _64(X), _65(X), _66(X), _67(X),
+ _68(X), _69(X), _6A(X), _6B(X), _6C(X), _6D(X), _6E(X), _6F(X),
+ _70(X), _71(X), _72(X), _73(X), _74(X), _75(X), _76(X), _77(X),
+ _78(X), _79(X), _7A(X), _7B(X), _7C(X), _7D(X), _7E(X), _7F(X),
+ _80(X), _81(X), _82(X), _83(X), _84(X), _85(X), _86(X), _87(X),
+ _88(X), _89(X), _8A(X), _8B(X), _8C(X), _8D(X), _8E(X), _8F(X),
+ _90(X), _91(X), _92(X), _93(X), _94(X), _95(X), _96(X), _97(X),
+ _98(X), _99(X), _9A(X), _9B(X), _9C(X), _9D(X), _9E(X), _9F(X),
+ _A0(X), _A1(X), _A2(X), _A3(X), _A4(X), _A5(X), _A6(X), _A7(X),
+ _A8(X), _A9(X), _AA(X), _AB(X), _AC(X), _AD(X), _AE(X), _AF(X),
+ _B0(X), _B1(X), _B2(X), _B3(X), _B4(X), _B5(X), _B6(X), _B7(X),
+ _B8(X), _B9(X), _BA(X), _BB(X), _BC(X), _BD(X), _BE(X), _BF(X),
+ _C0(X), _C1(X), _C2(X), _C3(X), _C4(X), _C5(X), _C6(X), _C7(X),
+ _C8(X), _C9(X), _CA(X), _CB(X), _CC(X), _CD(X), _CE(X), _CF(X),
+ _D0(X), _D1(X), _D2(X), _D3(X), _D4(X), _D5(X), _D6(X), _D7(X),
+ _D8(X), _D9(X), _DA(X), _DB(X), _DC(X), _DD(X), _DE(X), _DF(X),
+ _E0(X), _E1(X), _E2(X), _E3(X), _E4(X), _E5(X), _E6(X), _E7(X),
+ _E8(X), _E9(X), _EA(X), _EB(X), _EC(X), _ED(X), _EE(X), _EF(X),
+ _F0(X), _F1(X), _F2(X), _F3(X), _F4(X), _F5(X), _F6(X), _F7(X),
+ _F8(X), _F9(X), _FA(X), _FB(X), _FC(X), _FD(X), _FE(X), _FF(X),
+
+ V3,
+ V4,
+ }
+
+ if let E1::V2 { .. } = (E1::V1 { f: true }) {
+ unreachable!()
+ }
+ if let E1::V1 { .. } = (E1::V1 { f: true }) {
+ } else {
+ unreachable!()
+ }
+
+ if let E2::V1 { .. } = E2::V3::<Infallible> {
+ unreachable!()
+ }
+ if let E2::V3 { .. } = E2::V3::<Infallible> {
+ } else {
+ unreachable!()
+ }
+
+ 0
+};
+
+fn main() {
+ assert_eq!(OVERFLOW, 0);
+ assert_eq!(MORE_OVERFLOW, 0);
+}
diff --git a/src/test/ui/enum-discriminant/repr128.rs b/src/test/ui/enum-discriminant/repr128.rs
new file mode 100644
index 000000000..00021a07b
--- /dev/null
+++ b/src/test/ui/enum-discriminant/repr128.rs
@@ -0,0 +1,45 @@
+// run-pass
+#![feature(repr128, core_intrinsics, discriminant_kind)]
+//~^ WARN the feature `repr128` is incomplete
+
+use std::intrinsics::discriminant_value;
+use std::marker::DiscriminantKind;
+
+#[repr(i128)]
+enum Signed {
+ Zero = 0,
+ Staircase = 0x01_02_03_04_05_06_07_08_09_0a_0b_0c_0d_0e_0f,
+ U64Limit = u64::MAX as i128 + 1,
+ SmallNegative = -1,
+ BigNegative = i128::MIN,
+ Next,
+}
+
+#[repr(u128)]
+enum Unsigned {
+ Zero = 0,
+ Staircase = 0x01_02_03_04_05_06_07_08_09_0a_0b_0c_0d_0e_0f,
+ U64Limit = u64::MAX as u128 + 1,
+ Next,
+}
+
+fn discr<T, U>(v: T, value: U)
+where
+ <T as DiscriminantKind>::Discriminant: PartialEq<U>,
+{
+ assert!(discriminant_value(&v) == value);
+}
+
+fn main() {
+ discr(Signed::Zero, 0);
+ discr(Signed::Staircase, 0x01_02_03_04_05_06_07_08_09_0a_0b_0c_0d_0e_0f);
+ discr(Signed::U64Limit, u64::MAX as i128 + 1);
+ discr(Signed::SmallNegative, -1);
+ discr(Signed::BigNegative, i128::MIN);
+ discr(Signed::Next, i128::MIN + 1);
+
+ discr(Unsigned::Zero, 0);
+ discr(Unsigned::Staircase, 0x01_02_03_04_05_06_07_08_09_0a_0b_0c_0d_0e_0f);
+ discr(Unsigned::U64Limit, u64::MAX as u128 + 1);
+ discr(Unsigned::Next, u64::MAX as u128 + 2);
+}
diff --git a/src/test/ui/enum-discriminant/repr128.stderr b/src/test/ui/enum-discriminant/repr128.stderr
new file mode 100644
index 000000000..88adfb174
--- /dev/null
+++ b/src/test/ui/enum-discriminant/repr128.stderr
@@ -0,0 +1,11 @@
+warning: the feature `repr128` is incomplete and may not be safe to use and/or cause compiler crashes
+ --> $DIR/repr128.rs:2:12
+ |
+LL | #![feature(repr128, core_intrinsics, discriminant_kind)]
+ | ^^^^^^^
+ |
+ = note: `#[warn(incomplete_features)]` on by default
+ = note: see issue #56071 <https://github.com/rust-lang/rust/issues/56071> for more information
+
+warning: 1 warning emitted
+
diff --git a/src/test/ui/enum/enum-and-module-in-same-scope.rs b/src/test/ui/enum/enum-and-module-in-same-scope.rs
new file mode 100644
index 000000000..cc6e199bd
--- /dev/null
+++ b/src/test/ui/enum/enum-and-module-in-same-scope.rs
@@ -0,0 +1,10 @@
+enum Foo {
+ X
+}
+
+mod Foo { //~ ERROR the name `Foo` is defined multiple times
+ pub static X: isize = 42;
+ fn f() { f() } // Check that this does not result in a resolution error
+}
+
+fn main() {}
diff --git a/src/test/ui/enum/enum-and-module-in-same-scope.stderr b/src/test/ui/enum/enum-and-module-in-same-scope.stderr
new file mode 100644
index 000000000..538898c2f
--- /dev/null
+++ b/src/test/ui/enum/enum-and-module-in-same-scope.stderr
@@ -0,0 +1,14 @@
+error[E0428]: the name `Foo` is defined multiple times
+ --> $DIR/enum-and-module-in-same-scope.rs:5:1
+ |
+LL | enum Foo {
+ | -------- previous definition of the type `Foo` here
+...
+LL | mod Foo {
+ | ^^^^^^^ `Foo` redefined here
+ |
+ = note: `Foo` must be defined only once in the type namespace of this module
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0428`.
diff --git a/src/test/ui/enum/enum-discrim-autosizing.rs b/src/test/ui/enum/enum-discrim-autosizing.rs
new file mode 100644
index 000000000..27fab1bb5
--- /dev/null
+++ b/src/test/ui/enum/enum-discrim-autosizing.rs
@@ -0,0 +1,14 @@
+// With no repr attribute the discriminant will default to isize.
+// On 32-bit architectures this is equivalent to i32 so the variants
+// collide. On other architectures we need compilation to fail anyway,
+// so force the repr.
+#[cfg_attr(not(target_pointer_width = "32"), repr(i32))]
+enum Eu64 {
+ //~^ ERROR discriminant value `0` assigned more than once
+ Au64 = 0,
+ //~^NOTE first assignment of `0`
+ Bu64 = 0x8000_0000_0000_0000
+ //~^NOTE second assignment of `0` (overflowed from `9223372036854775808`)
+}
+
+fn main() {}
diff --git a/src/test/ui/enum/enum-discrim-autosizing.stderr b/src/test/ui/enum/enum-discrim-autosizing.stderr
new file mode 100644
index 000000000..eacea86d6
--- /dev/null
+++ b/src/test/ui/enum/enum-discrim-autosizing.stderr
@@ -0,0 +1,15 @@
+error[E0081]: discriminant value `0` assigned more than once
+ --> $DIR/enum-discrim-autosizing.rs:6:1
+ |
+LL | enum Eu64 {
+ | ^^^^^^^^^
+LL |
+LL | Au64 = 0,
+ | - first assignment of `0`
+LL |
+LL | Bu64 = 0x8000_0000_0000_0000
+ | --------------------- second assignment of `0` (overflowed from `9223372036854775808`)
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0081`.
diff --git a/src/test/ui/enum/enum-discrim-too-small.rs b/src/test/ui/enum/enum-discrim-too-small.rs
new file mode 100644
index 000000000..e49841402
--- /dev/null
+++ b/src/test/ui/enum/enum-discrim-too-small.rs
@@ -0,0 +1,38 @@
+#[repr(u8)]
+enum Eu8 {
+ Au8 = 23,
+ Bu8 = 223,
+ Cu8 = -23,
+ //~^ ERROR cannot apply unary operator `-` to type `u8`
+}
+
+#[repr(u16)]
+enum Eu16 {
+ Au16 = 23,
+ Bu16 = 55555,
+ Cu16 = -22333,
+ //~^ ERROR cannot apply unary operator `-` to type `u16`
+}
+
+#[repr(u32)]
+enum Eu32 {
+ Au32 = 23,
+ Bu32 = 3_000_000_000,
+ Cu32 = -2_000_000_000,
+ //~^ ERROR cannot apply unary operator `-` to type `u32`
+}
+
+#[repr(u64)]
+enum Eu64 {
+ Au32 = 23,
+ Bu32 = 3_000_000_000,
+ Cu32 = -2_000_000_000,
+ //~^ ERROR cannot apply unary operator `-` to type `u64`
+}
+
+// u64 currently allows negative numbers, and i64 allows numbers greater than `1<<63`. This is a
+// little counterintuitive, but since the discriminant can store all the bits, and extracting it
+// with a cast requires specifying the signedness, there is no loss of information in those cases.
+// This also applies to isize and usize on 64-bit targets.
+
+pub fn main() { }
diff --git a/src/test/ui/enum/enum-discrim-too-small.stderr b/src/test/ui/enum/enum-discrim-too-small.stderr
new file mode 100644
index 000000000..40205d95b
--- /dev/null
+++ b/src/test/ui/enum/enum-discrim-too-small.stderr
@@ -0,0 +1,35 @@
+error[E0600]: cannot apply unary operator `-` to type `u8`
+ --> $DIR/enum-discrim-too-small.rs:5:11
+ |
+LL | Cu8 = -23,
+ | ^^^ cannot apply unary operator `-`
+ |
+ = note: unsigned values cannot be negated
+
+error[E0600]: cannot apply unary operator `-` to type `u16`
+ --> $DIR/enum-discrim-too-small.rs:13:12
+ |
+LL | Cu16 = -22333,
+ | ^^^^^^ cannot apply unary operator `-`
+ |
+ = note: unsigned values cannot be negated
+
+error[E0600]: cannot apply unary operator `-` to type `u32`
+ --> $DIR/enum-discrim-too-small.rs:21:12
+ |
+LL | Cu32 = -2_000_000_000,
+ | ^^^^^^^^^^^^^^ cannot apply unary operator `-`
+ |
+ = note: unsigned values cannot be negated
+
+error[E0600]: cannot apply unary operator `-` to type `u64`
+ --> $DIR/enum-discrim-too-small.rs:29:12
+ |
+LL | Cu32 = -2_000_000_000,
+ | ^^^^^^^^^^^^^^ cannot apply unary operator `-`
+ |
+ = note: unsigned values cannot be negated
+
+error: aborting due to 4 previous errors
+
+For more information about this error, try `rustc --explain E0600`.
diff --git a/src/test/ui/enum/enum-discrim-too-small2.rs b/src/test/ui/enum/enum-discrim-too-small2.rs
new file mode 100644
index 000000000..85cd73d6f
--- /dev/null
+++ b/src/test/ui/enum/enum-discrim-too-small2.rs
@@ -0,0 +1,37 @@
+#![deny(overflowing_literals)]
+#![allow(dead_code)]
+
+#[repr(i8)]
+enum Ei8 {
+ Ai8 = 23,
+ Bi8 = -23,
+ Ci8 = 223, //~ ERROR literal out of range for `i8`
+}
+
+#[repr(i16)]
+enum Ei16 {
+ Ai16 = 23,
+ Bi16 = -22333,
+ Ci16 = 55555, //~ ERROR literal out of range for `i16`
+}
+
+#[repr(i32)]
+enum Ei32 {
+ Ai32 = 23,
+ Bi32 = -2_000_000_000,
+ Ci32 = 3_000_000_000, //~ ERROR literal out of range for `i32`
+}
+
+#[repr(i64)]
+enum Ei64 {
+ Ai64 = 23,
+ Bi64 = -9223372036854775808,
+ Ci64 = 9223372036854775809, //~ ERROR literal out of range for `i64`
+}
+
+// u64 currently allows negative numbers, and i64 allows numbers greater than `1<<63`. This is a
+// little counterintuitive, but since the discriminant can store all the bits, and extracting it
+// with a cast requires specifying the signedness, there is no loss of information in those cases.
+// This also applies to isize and usize on 64-bit targets.
+
+pub fn main() { }
diff --git a/src/test/ui/enum/enum-discrim-too-small2.stderr b/src/test/ui/enum/enum-discrim-too-small2.stderr
new file mode 100644
index 000000000..438306795
--- /dev/null
+++ b/src/test/ui/enum/enum-discrim-too-small2.stderr
@@ -0,0 +1,43 @@
+error: literal out of range for `i8`
+ --> $DIR/enum-discrim-too-small2.rs:8:11
+ |
+LL | Ci8 = 223,
+ | ^^^
+ |
+note: the lint level is defined here
+ --> $DIR/enum-discrim-too-small2.rs:1:9
+ |
+LL | #![deny(overflowing_literals)]
+ | ^^^^^^^^^^^^^^^^^^^^
+ = note: the literal `223` does not fit into the type `i8` whose range is `-128..=127`
+ = help: consider using the type `u8` instead
+
+error: literal out of range for `i16`
+ --> $DIR/enum-discrim-too-small2.rs:15:12
+ |
+LL | Ci16 = 55555,
+ | ^^^^^
+ |
+ = note: the literal `55555` does not fit into the type `i16` whose range is `-32768..=32767`
+ = help: consider using the type `u16` instead
+
+error: literal out of range for `i32`
+ --> $DIR/enum-discrim-too-small2.rs:22:12
+ |
+LL | Ci32 = 3_000_000_000,
+ | ^^^^^^^^^^^^^
+ |
+ = note: the literal `3_000_000_000` does not fit into the type `i32` whose range is `-2147483648..=2147483647`
+ = help: consider using the type `u32` instead
+
+error: literal out of range for `i64`
+ --> $DIR/enum-discrim-too-small2.rs:29:12
+ |
+LL | Ci64 = 9223372036854775809,
+ | ^^^^^^^^^^^^^^^^^^^
+ |
+ = note: the literal `9223372036854775809` does not fit into the type `i64` whose range is `-9223372036854775808..=9223372036854775807`
+ = help: consider using the type `u64` instead
+
+error: aborting due to 4 previous errors
+
diff --git a/src/test/ui/enum/enum-in-scope.rs b/src/test/ui/enum/enum-in-scope.rs
new file mode 100644
index 000000000..df14bc62e
--- /dev/null
+++ b/src/test/ui/enum/enum-in-scope.rs
@@ -0,0 +1,7 @@
+#![allow(non_camel_case_types)]
+
+struct hello(isize);
+
+fn main() {
+ let hello = 0; //~ERROR let bindings cannot shadow tuple structs
+}
diff --git a/src/test/ui/enum/enum-in-scope.stderr b/src/test/ui/enum/enum-in-scope.stderr
new file mode 100644
index 000000000..49a01abcb
--- /dev/null
+++ b/src/test/ui/enum/enum-in-scope.stderr
@@ -0,0 +1,12 @@
+error[E0530]: let bindings cannot shadow tuple structs
+ --> $DIR/enum-in-scope.rs:6:9
+ |
+LL | struct hello(isize);
+ | -------------------- the tuple struct `hello` is defined here
+...
+LL | let hello = 0;
+ | ^^^^^ cannot be named the same as a tuple struct
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0530`.
diff --git a/src/test/ui/enum/enum-size-variance.rs b/src/test/ui/enum/enum-size-variance.rs
new file mode 100644
index 000000000..082bd0dcf
--- /dev/null
+++ b/src/test/ui/enum/enum-size-variance.rs
@@ -0,0 +1,35 @@
+// run-pass
+
+#![warn(variant_size_differences)]
+#![allow(dead_code)]
+
+// Note that the following test works because all fields of the enum variants are of the same size.
+// If this test is modified and the reordering logic in librustc/ty/layout.rs kicks in, it fails.
+
+enum Enum1 { }
+
+enum Enum2 { A, B, C }
+
+enum Enum3 { D(i64), E, F }
+
+enum Enum4 { H(i64), I(i64), J }
+
+enum Enum5 {
+ L(i64, i64, i64, i64), //~ WARNING three times larger
+ M(i64),
+ N
+}
+
+enum Enum6<T, U> {
+ O(T),
+ P(U),
+ Q(i64)
+}
+
+#[allow(variant_size_differences)]
+enum Enum7 {
+ R(i64, i64, i64, i64),
+ S(i64),
+ T
+}
+pub fn main() { }
diff --git a/src/test/ui/enum/enum-size-variance.stderr b/src/test/ui/enum/enum-size-variance.stderr
new file mode 100644
index 000000000..6012033dc
--- /dev/null
+++ b/src/test/ui/enum/enum-size-variance.stderr
@@ -0,0 +1,14 @@
+warning: enum variant is more than three times larger (32 bytes) than the next largest
+ --> $DIR/enum-size-variance.rs:18:5
+ |
+LL | L(i64, i64, i64, i64),
+ | ^^^^^^^^^^^^^^^^^^^^^
+ |
+note: the lint level is defined here
+ --> $DIR/enum-size-variance.rs:3:9
+ |
+LL | #![warn(variant_size_differences)]
+ | ^^^^^^^^^^^^^^^^^^^^^^^^
+
+warning: 1 warning emitted
+
diff --git a/src/test/ui/enum/enum-to-float-cast-2.rs b/src/test/ui/enum/enum-to-float-cast-2.rs
new file mode 100644
index 000000000..c861b5ed9
--- /dev/null
+++ b/src/test/ui/enum/enum-to-float-cast-2.rs
@@ -0,0 +1,18 @@
+// Tests that enum-to-float casts are disallowed.
+
+enum E {
+ L0 = -1,
+ H0 = 1
+}
+
+enum F {
+ L1 = 1,
+ H1 = 0xFFFFFFFFFFFFFFFF
+}
+
+pub fn main() {
+ let a = E::L0 as f32; //~ ERROR casting
+ let c = F::H1 as f32; //~ ERROR casting
+ assert_eq!(a, -1.0f32);
+ assert_eq!(c, -1.0f32);
+}
diff --git a/src/test/ui/enum/enum-to-float-cast-2.stderr b/src/test/ui/enum/enum-to-float-cast-2.stderr
new file mode 100644
index 000000000..2bc414098
--- /dev/null
+++ b/src/test/ui/enum/enum-to-float-cast-2.stderr
@@ -0,0 +1,19 @@
+error[E0606]: casting `E` as `f32` is invalid
+ --> $DIR/enum-to-float-cast-2.rs:14:13
+ |
+LL | let a = E::L0 as f32;
+ | ^^^^^^^^^^^^
+ |
+ = help: cast through an integer first
+
+error[E0606]: casting `F` as `f32` is invalid
+ --> $DIR/enum-to-float-cast-2.rs:15:13
+ |
+LL | let c = F::H1 as f32;
+ | ^^^^^^^^^^^^
+ |
+ = help: cast through an integer first
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0606`.
diff --git a/src/test/ui/enum/enum-to-float-cast.rs b/src/test/ui/enum/enum-to-float-cast.rs
new file mode 100644
index 000000000..05acdfd34
--- /dev/null
+++ b/src/test/ui/enum/enum-to-float-cast.rs
@@ -0,0 +1,21 @@
+// Tests that enum-to-float casts are disallowed.
+
+enum E {
+ L0 = -1,
+ H0 = 1
+}
+
+enum F {
+ L1 = 1,
+ H1 = 0xFFFFFFFFFFFFFFFF
+}
+
+static C0: f32 = E::L0 as f32; //~ ERROR casting
+static C1: f32 = F::H1 as f32; //~ ERROR casting
+
+pub fn main() {
+ let b = C0;
+ let d = C1;
+ assert_eq!(b, -1.0f32);
+ assert_eq!(d, -1.0f32);
+}
diff --git a/src/test/ui/enum/enum-to-float-cast.stderr b/src/test/ui/enum/enum-to-float-cast.stderr
new file mode 100644
index 000000000..191606d8d
--- /dev/null
+++ b/src/test/ui/enum/enum-to-float-cast.stderr
@@ -0,0 +1,19 @@
+error[E0606]: casting `E` as `f32` is invalid
+ --> $DIR/enum-to-float-cast.rs:13:18
+ |
+LL | static C0: f32 = E::L0 as f32;
+ | ^^^^^^^^^^^^
+ |
+ = help: cast through an integer first
+
+error[E0606]: casting `F` as `f32` is invalid
+ --> $DIR/enum-to-float-cast.rs:14:18
+ |
+LL | static C1: f32 = F::H1 as f32;
+ | ^^^^^^^^^^^^
+ |
+ = help: cast through an integer first
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0606`.
diff --git a/src/test/ui/enum/enum-variant-type-2.rs b/src/test/ui/enum/enum-variant-type-2.rs
new file mode 100644
index 000000000..27286a0a3
--- /dev/null
+++ b/src/test/ui/enum/enum-variant-type-2.rs
@@ -0,0 +1,9 @@
+// Test that enum variants are not actually types.
+
+enum Foo {
+ Bar
+}
+
+fn foo(x: Foo::Bar) {} //~ ERROR expected type, found variant `Foo::Bar`
+
+fn main() {}
diff --git a/src/test/ui/enum/enum-variant-type-2.stderr b/src/test/ui/enum/enum-variant-type-2.stderr
new file mode 100644
index 000000000..7e8453c61
--- /dev/null
+++ b/src/test/ui/enum/enum-variant-type-2.stderr
@@ -0,0 +1,12 @@
+error[E0573]: expected type, found variant `Foo::Bar`
+ --> $DIR/enum-variant-type-2.rs:7:11
+ |
+LL | fn foo(x: Foo::Bar) {}
+ | ^^^^^^^^
+ | |
+ | not a type
+ | help: try using the variant's enum: `Foo`
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0573`.
diff --git a/src/test/ui/enum/issue-42747.rs b/src/test/ui/enum/issue-42747.rs
new file mode 100644
index 000000000..fec658782
--- /dev/null
+++ b/src/test/ui/enum/issue-42747.rs
@@ -0,0 +1,46 @@
+// run-pass
+macro_rules! fooN {
+ ($cur:ident $prev:ty) => {
+ #[allow(dead_code)]
+ enum $cur {
+ Empty,
+ First($prev),
+ Second($prev),
+ Third($prev),
+ Fourth($prev),
+ }
+ }
+}
+
+fooN!(Foo0 ());
+fooN!(Foo1 Foo0);
+fooN!(Foo2 Foo1);
+fooN!(Foo3 Foo2);
+fooN!(Foo4 Foo3);
+fooN!(Foo5 Foo4);
+fooN!(Foo6 Foo5);
+fooN!(Foo7 Foo6);
+fooN!(Foo8 Foo7);
+fooN!(Foo9 Foo8);
+fooN!(Foo10 Foo9);
+fooN!(Foo11 Foo10);
+fooN!(Foo12 Foo11);
+fooN!(Foo13 Foo12);
+fooN!(Foo14 Foo13);
+fooN!(Foo15 Foo14);
+fooN!(Foo16 Foo15);
+fooN!(Foo17 Foo16);
+fooN!(Foo18 Foo17);
+fooN!(Foo19 Foo18);
+fooN!(Foo20 Foo19);
+fooN!(Foo21 Foo20);
+fooN!(Foo22 Foo21);
+fooN!(Foo23 Foo22);
+fooN!(Foo24 Foo23);
+fooN!(Foo25 Foo24);
+fooN!(Foo26 Foo25);
+fooN!(Foo27 Foo26);
+
+fn main() {
+ let _foo = Foo27::Empty;
+}
diff --git a/src/test/ui/enum/issue-67945-1.rs b/src/test/ui/enum/issue-67945-1.rs
new file mode 100644
index 000000000..f4697344c
--- /dev/null
+++ b/src/test/ui/enum/issue-67945-1.rs
@@ -0,0 +1,8 @@
+enum Bug<S> { //~ ERROR parameter `S` is never used
+ Var = {
+ let x: S = 0; //~ ERROR generic parameters may not be used
+ 0
+ },
+}
+
+fn main() {}
diff --git a/src/test/ui/enum/issue-67945-1.stderr b/src/test/ui/enum/issue-67945-1.stderr
new file mode 100644
index 000000000..8f1b5b38e
--- /dev/null
+++ b/src/test/ui/enum/issue-67945-1.stderr
@@ -0,0 +1,21 @@
+error: generic parameters may not be used in const operations
+ --> $DIR/issue-67945-1.rs:3:16
+ |
+LL | let x: S = 0;
+ | ^ cannot perform const operation using `S`
+ |
+ = note: type parameters may not be used in const expressions
+ = help: use `#![feature(generic_const_exprs)]` to allow generic const expressions
+
+error[E0392]: parameter `S` is never used
+ --> $DIR/issue-67945-1.rs:1:10
+ |
+LL | enum Bug<S> {
+ | ^ unused parameter
+ |
+ = help: consider removing `S`, referring to it in a field, or using a marker such as `PhantomData`
+ = help: if you intended `S` to be a const parameter, use `const S: usize` instead
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0392`.
diff --git a/src/test/ui/enum/issue-67945-2.rs b/src/test/ui/enum/issue-67945-2.rs
new file mode 100644
index 000000000..e5044468d
--- /dev/null
+++ b/src/test/ui/enum/issue-67945-2.rs
@@ -0,0 +1,8 @@
+#![feature(type_ascription)]
+
+enum Bug<S> { //~ ERROR parameter `S` is never used
+ Var = 0: S,
+ //~^ ERROR generic parameters may not be used
+}
+
+fn main() {}
diff --git a/src/test/ui/enum/issue-67945-2.stderr b/src/test/ui/enum/issue-67945-2.stderr
new file mode 100644
index 000000000..4f5e236a3
--- /dev/null
+++ b/src/test/ui/enum/issue-67945-2.stderr
@@ -0,0 +1,21 @@
+error: generic parameters may not be used in const operations
+ --> $DIR/issue-67945-2.rs:4:14
+ |
+LL | Var = 0: S,
+ | ^ cannot perform const operation using `S`
+ |
+ = note: type parameters may not be used in const expressions
+ = help: use `#![feature(generic_const_exprs)]` to allow generic const expressions
+
+error[E0392]: parameter `S` is never used
+ --> $DIR/issue-67945-2.rs:3:10
+ |
+LL | enum Bug<S> {
+ | ^ unused parameter
+ |
+ = help: consider removing `S`, referring to it in a field, or using a marker such as `PhantomData`
+ = help: if you intended `S` to be a const parameter, use `const S: usize` instead
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0392`.
diff --git a/src/test/ui/enum/nested-enum.rs b/src/test/ui/enum/nested-enum.rs
new file mode 100644
index 000000000..80957b8a1
--- /dev/null
+++ b/src/test/ui/enum/nested-enum.rs
@@ -0,0 +1,8 @@
+enum Foo {
+ enum Bar { Baz }, //~ ERROR `enum` definition cannot be nested inside `enum`
+ struct Quux { field: u8 }, //~ ERROR `struct` definition cannot be nested inside `enum`
+ union Wibble { field: u8 }, //~ ERROR `union` definition cannot be nested inside `enum`
+ Bat,
+}
+
+fn main() { }
diff --git a/src/test/ui/enum/nested-enum.stderr b/src/test/ui/enum/nested-enum.stderr
new file mode 100644
index 000000000..7d6f57e88
--- /dev/null
+++ b/src/test/ui/enum/nested-enum.stderr
@@ -0,0 +1,26 @@
+error: `enum` definition cannot be nested inside `enum`
+ --> $DIR/nested-enum.rs:2:5
+ |
+LL | enum Bar { Baz },
+ | ^^^^------------
+ | |
+ | help: consider creating a new `enum` definition instead of nesting
+
+error: `struct` definition cannot be nested inside `enum`
+ --> $DIR/nested-enum.rs:3:5
+ |
+LL | struct Quux { field: u8 },
+ | ^^^^^^-------------------
+ | |
+ | help: consider creating a new `struct` definition instead of nesting
+
+error: `union` definition cannot be nested inside `enum`
+ --> $DIR/nested-enum.rs:4:5
+ |
+LL | union Wibble { field: u8 },
+ | ^^^^^---------------------
+ | |
+ | help: consider creating a new `union` definition instead of nesting
+
+error: aborting due to 3 previous errors
+
diff --git a/src/test/ui/enum/suggest-default-attribute.rs b/src/test/ui/enum/suggest-default-attribute.rs
new file mode 100644
index 000000000..1d7567e60
--- /dev/null
+++ b/src/test/ui/enum/suggest-default-attribute.rs
@@ -0,0 +1,8 @@
+pub enum Test { //~ HELP consider adding a derive
+ #[default]
+ //~^ ERROR cannot find attribute `default` in this scope
+ First,
+ Second,
+}
+
+fn main() {}
diff --git a/src/test/ui/enum/suggest-default-attribute.stderr b/src/test/ui/enum/suggest-default-attribute.stderr
new file mode 100644
index 000000000..fb830d3f7
--- /dev/null
+++ b/src/test/ui/enum/suggest-default-attribute.stderr
@@ -0,0 +1,14 @@
+error: cannot find attribute `default` in this scope
+ --> $DIR/suggest-default-attribute.rs:2:7
+ |
+LL | #[default]
+ | ^^^^^^^
+ |
+help: consider adding a derive
+ |
+LL + #[derive(Default)]
+LL ~ pub enum Test {
+ |
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/enum/union-in-enum.rs b/src/test/ui/enum/union-in-enum.rs
new file mode 100644
index 000000000..048913e25
--- /dev/null
+++ b/src/test/ui/enum/union-in-enum.rs
@@ -0,0 +1,13 @@
+// This test checks that the union keyword
+// is accepted as the name of an enum variant
+// when not followed by an identifier
+// This special case exists because `union` is a contextual keyword.
+
+#![allow(warnings)]
+
+// check-pass
+
+enum A { union }
+enum B { union {} }
+enum C { union() }
+fn main(){}