summaryrefslogtreecommitdiffstats
path: root/tests/ui/rfc-2008-non-exhaustive
diff options
context:
space:
mode:
authorDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-17 12:19:13 +0000
committerDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-17 12:19:13 +0000
commit218caa410aa38c29984be31a5229b9fa717560ee (patch)
treec54bd55eeb6e4c508940a30e94c0032fbd45d677 /tests/ui/rfc-2008-non-exhaustive
parentReleasing progress-linux version 1.67.1+dfsg1-1~progress7.99u1. (diff)
downloadrustc-218caa410aa38c29984be31a5229b9fa717560ee.tar.xz
rustc-218caa410aa38c29984be31a5229b9fa717560ee.zip
Merging upstream version 1.68.2+dfsg1.
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'tests/ui/rfc-2008-non-exhaustive')
-rw-r--r--tests/ui/rfc-2008-non-exhaustive/auxiliary/enums.rs44
-rw-r--r--tests/ui/rfc-2008-non-exhaustive/auxiliary/monovariants.rs8
-rw-r--r--tests/ui/rfc-2008-non-exhaustive/auxiliary/structs.rs41
-rw-r--r--tests/ui/rfc-2008-non-exhaustive/auxiliary/unstable.rs60
-rw-r--r--tests/ui/rfc-2008-non-exhaustive/auxiliary/variants.rs7
-rw-r--r--tests/ui/rfc-2008-non-exhaustive/borrowck-exhaustive.rs42
-rw-r--r--tests/ui/rfc-2008-non-exhaustive/borrowck-non-exhaustive.rs18
-rw-r--r--tests/ui/rfc-2008-non-exhaustive/borrowck-non-exhaustive.stderr14
-rw-r--r--tests/ui/rfc-2008-non-exhaustive/enum-as-cast.rs11
-rw-r--r--tests/ui/rfc-2008-non-exhaustive/enum-as-cast.stderr11
-rw-r--r--tests/ui/rfc-2008-non-exhaustive/enum.rs69
-rw-r--r--tests/ui/rfc-2008-non-exhaustive/enum.stderr59
-rw-r--r--tests/ui/rfc-2008-non-exhaustive/enum_same_crate.rs18
-rw-r--r--tests/ui/rfc-2008-non-exhaustive/enum_same_crate_empty_match.rs37
-rw-r--r--tests/ui/rfc-2008-non-exhaustive/enum_same_crate_empty_match.stderr69
-rw-r--r--tests/ui/rfc-2008-non-exhaustive/improper_ctypes/auxiliary/types.rs29
-rw-r--r--tests/ui/rfc-2008-non-exhaustive/improper_ctypes/extern_crate_improper.rs24
-rw-r--r--tests/ui/rfc-2008-non-exhaustive/improper_ctypes/extern_crate_improper.stderr47
-rw-r--r--tests/ui/rfc-2008-non-exhaustive/improper_ctypes/same_crate_proper.rs48
-rw-r--r--tests/ui/rfc-2008-non-exhaustive/invalid-attribute.rs16
-rw-r--r--tests/ui/rfc-2008-non-exhaustive/invalid-attribute.stderr30
-rw-r--r--tests/ui/rfc-2008-non-exhaustive/omitted-patterns.rs187
-rw-r--r--tests/ui/rfc-2008-non-exhaustive/omitted-patterns.stderr188
-rw-r--r--tests/ui/rfc-2008-non-exhaustive/stable-omitted-patterns.rs45
-rw-r--r--tests/ui/rfc-2008-non-exhaustive/stable-omitted-patterns.stderr30
-rw-r--r--tests/ui/rfc-2008-non-exhaustive/struct.rs49
-rw-r--r--tests/ui/rfc-2008-non-exhaustive/struct.stderr96
-rw-r--r--tests/ui/rfc-2008-non-exhaustive/structs_same_crate.rs32
-rw-r--r--tests/ui/rfc-2008-non-exhaustive/uninhabited/auxiliary/uninhabited.rs32
-rw-r--r--tests/ui/rfc-2008-non-exhaustive/uninhabited/coercions.rs38
-rw-r--r--tests/ui/rfc-2008-non-exhaustive/uninhabited/coercions.stderr35
-rw-r--r--tests/ui/rfc-2008-non-exhaustive/uninhabited/coercions_same_crate.rs45
-rw-r--r--tests/ui/rfc-2008-non-exhaustive/uninhabited/coercions_same_crate.stderr35
-rw-r--r--tests/ui/rfc-2008-non-exhaustive/uninhabited/indirect_match.rs36
-rw-r--r--tests/ui/rfc-2008-non-exhaustive/uninhabited/indirect_match.stderr79
-rw-r--r--tests/ui/rfc-2008-non-exhaustive/uninhabited/indirect_match_same_crate.rs51
-rw-r--r--tests/ui/rfc-2008-non-exhaustive/uninhabited/indirect_match_same_crate.stderr79
-rw-r--r--tests/ui/rfc-2008-non-exhaustive/uninhabited/indirect_match_with_exhaustive_patterns.rs40
-rw-r--r--tests/ui/rfc-2008-non-exhaustive/uninhabited/indirect_match_with_exhaustive_patterns.stderr79
-rw-r--r--tests/ui/rfc-2008-non-exhaustive/uninhabited/indirect_match_with_exhaustive_patterns_same_crate.rs57
-rw-r--r--tests/ui/rfc-2008-non-exhaustive/uninhabited/issue-65157-repeated-match-arm.rs21
-rw-r--r--tests/ui/rfc-2008-non-exhaustive/uninhabited/issue-65157-repeated-match-arm.stderr14
-rw-r--r--tests/ui/rfc-2008-non-exhaustive/uninhabited/match.rs34
-rw-r--r--tests/ui/rfc-2008-non-exhaustive/uninhabited/match.stderr83
-rw-r--r--tests/ui/rfc-2008-non-exhaustive/uninhabited/match_same_crate.rs41
-rw-r--r--tests/ui/rfc-2008-non-exhaustive/uninhabited/match_same_crate.stderr64
-rw-r--r--tests/ui/rfc-2008-non-exhaustive/uninhabited/match_with_exhaustive_patterns.rs37
-rw-r--r--tests/ui/rfc-2008-non-exhaustive/uninhabited/match_with_exhaustive_patterns.stderr83
-rw-r--r--tests/ui/rfc-2008-non-exhaustive/uninhabited/match_with_exhaustive_patterns_same_crate.rs47
-rw-r--r--tests/ui/rfc-2008-non-exhaustive/uninhabited/patterns.rs59
-rw-r--r--tests/ui/rfc-2008-non-exhaustive/uninhabited/patterns_same_crate.rs70
-rw-r--r--tests/ui/rfc-2008-non-exhaustive/uninhabited/patterns_same_crate.stderr38
-rw-r--r--tests/ui/rfc-2008-non-exhaustive/variant.rs33
-rw-r--r--tests/ui/rfc-2008-non-exhaustive/variant.stderr92
-rw-r--r--tests/ui/rfc-2008-non-exhaustive/variants_fictive_visibility.rs12
-rw-r--r--tests/ui/rfc-2008-non-exhaustive/variants_same_crate.rs18
56 files changed, 2681 insertions, 0 deletions
diff --git a/tests/ui/rfc-2008-non-exhaustive/auxiliary/enums.rs b/tests/ui/rfc-2008-non-exhaustive/auxiliary/enums.rs
new file mode 100644
index 000000000..cb2b585ab
--- /dev/null
+++ b/tests/ui/rfc-2008-non-exhaustive/auxiliary/enums.rs
@@ -0,0 +1,44 @@
+#![crate_type = "rlib"]
+
+#[non_exhaustive]
+pub enum NonExhaustiveEnum {
+ Unit,
+ Tuple(u32),
+ Struct { field: u32 },
+}
+
+#[non_exhaustive]
+pub enum NestedNonExhaustive {
+ A(NonExhaustiveEnum),
+ B,
+ C,
+}
+
+#[non_exhaustive]
+pub enum EmptyNonExhaustiveEnum {}
+
+pub enum VariantNonExhaustive {
+ #[non_exhaustive]
+ Bar {
+ x: u32,
+ y: u64,
+ },
+ Baz(u32, u16),
+}
+
+#[non_exhaustive]
+pub enum NonExhaustiveSingleVariant {
+ A(bool),
+}
+
+#[repr(u8)]
+pub enum FieldLessWithNonExhaustiveVariant {
+ A,
+ B,
+ #[non_exhaustive]
+ C,
+}
+
+impl Default for FieldLessWithNonExhaustiveVariant {
+ fn default() -> Self { Self::A }
+}
diff --git a/tests/ui/rfc-2008-non-exhaustive/auxiliary/monovariants.rs b/tests/ui/rfc-2008-non-exhaustive/auxiliary/monovariants.rs
new file mode 100644
index 000000000..5f86db86d
--- /dev/null
+++ b/tests/ui/rfc-2008-non-exhaustive/auxiliary/monovariants.rs
@@ -0,0 +1,8 @@
+#[non_exhaustive]
+pub enum NonExhaustiveMonovariant {
+ Variant(u32),
+}
+
+pub enum ExhaustiveMonovariant {
+ Variant(u32),
+}
diff --git a/tests/ui/rfc-2008-non-exhaustive/auxiliary/structs.rs b/tests/ui/rfc-2008-non-exhaustive/auxiliary/structs.rs
new file mode 100644
index 000000000..78db6b170
--- /dev/null
+++ b/tests/ui/rfc-2008-non-exhaustive/auxiliary/structs.rs
@@ -0,0 +1,41 @@
+#[derive(Default)]
+#[non_exhaustive]
+pub struct NormalStruct {
+ pub first_field: u16,
+ pub second_field: u16,
+}
+
+#[non_exhaustive]
+pub struct UnitStruct;
+
+#[non_exhaustive]
+pub struct TupleStruct(pub u16, pub u16);
+
+#[derive(Debug)]
+#[non_exhaustive]
+pub struct FunctionalRecord {
+ pub first_field: u16,
+ pub second_field: u16,
+ pub third_field: bool,
+}
+
+impl Default for FunctionalRecord {
+ fn default() -> FunctionalRecord {
+ FunctionalRecord { first_field: 640, second_field: 480, third_field: false }
+ }
+}
+
+#[derive(Default)]
+#[non_exhaustive]
+pub struct NestedStruct {
+ pub foo: u16,
+ pub bar: NormalStruct,
+}
+
+#[derive(Default)]
+#[non_exhaustive]
+pub struct MixedVisFields {
+ pub a: u16,
+ pub b: bool,
+ pub(crate) foo: bool,
+}
diff --git a/tests/ui/rfc-2008-non-exhaustive/auxiliary/unstable.rs b/tests/ui/rfc-2008-non-exhaustive/auxiliary/unstable.rs
new file mode 100644
index 000000000..11df44461
--- /dev/null
+++ b/tests/ui/rfc-2008-non-exhaustive/auxiliary/unstable.rs
@@ -0,0 +1,60 @@
+#![feature(staged_api)]
+#![stable(feature = "stable_test_feature", since = "1.0.0")]
+
+#[stable(feature = "stable_test_feature", since = "1.0.0")]
+#[non_exhaustive]
+pub enum UnstableEnum {
+ #[stable(feature = "stable_test_feature", since = "1.0.0")]
+ Stable,
+ #[stable(feature = "stable_test_feature", since = "1.0.0")]
+ Stable2,
+ #[unstable(feature = "unstable_test_feature", issue = "none")]
+ Unstable,
+}
+
+#[stable(feature = "stable_test_feature", since = "1.0.0")]
+#[non_exhaustive]
+pub enum OnlyUnstableEnum {
+ #[unstable(feature = "unstable_test_feature", issue = "none")]
+ Unstable,
+ #[unstable(feature = "unstable_test_feature", issue = "none")]
+ Unstable2,
+}
+
+impl OnlyUnstableEnum {
+ #[stable(feature = "stable_test_feature", since = "1.0.0")]
+ pub fn new() -> Self {
+ Self::Unstable
+ }
+}
+
+#[derive(Default)]
+#[stable(feature = "stable_test_feature", since = "1.0.0")]
+#[non_exhaustive]
+pub struct UnstableStruct {
+ #[stable(feature = "stable_test_feature", since = "1.0.0")]
+ pub stable: bool,
+ #[stable(feature = "stable_test_feature", since = "1.0.0")]
+ pub stable2: usize,
+ #[unstable(feature = "unstable_test_feature", issue = "none")]
+ pub unstable: u8,
+}
+
+#[stable(feature = "stable_test_feature", since = "1.0.0")]
+#[non_exhaustive]
+pub struct OnlyUnstableStruct {
+ #[unstable(feature = "unstable_test_feature", issue = "none")]
+ pub unstable: u8,
+ #[unstable(feature = "unstable_test_feature", issue = "none")]
+ pub unstable2: bool,
+}
+
+impl OnlyUnstableStruct {
+ #[stable(feature = "stable_test_feature", since = "1.0.0")]
+ pub fn new() -> Self {
+ Self {
+ unstable: 0,
+ unstable2: false,
+ }
+ }
+}
diff --git a/tests/ui/rfc-2008-non-exhaustive/auxiliary/variants.rs b/tests/ui/rfc-2008-non-exhaustive/auxiliary/variants.rs
new file mode 100644
index 000000000..02672d545
--- /dev/null
+++ b/tests/ui/rfc-2008-non-exhaustive/auxiliary/variants.rs
@@ -0,0 +1,7 @@
+#![crate_type = "rlib"]
+
+pub enum NonExhaustiveVariants {
+ #[non_exhaustive] Unit,
+ #[non_exhaustive] Tuple(u32),
+ #[non_exhaustive] Struct { field: u32 }
+}
diff --git a/tests/ui/rfc-2008-non-exhaustive/borrowck-exhaustive.rs b/tests/ui/rfc-2008-non-exhaustive/borrowck-exhaustive.rs
new file mode 100644
index 000000000..be775b37f
--- /dev/null
+++ b/tests/ui/rfc-2008-non-exhaustive/borrowck-exhaustive.rs
@@ -0,0 +1,42 @@
+// Test that the borrow checker doesn't consider checking an exhaustive pattern
+// as an access.
+
+// check-pass
+
+// aux-build:monovariants.rs
+extern crate monovariants;
+
+use monovariants::ExhaustiveMonovariant;
+
+enum Local {
+ Variant(u32),
+}
+
+#[non_exhaustive]
+enum LocalNonExhaustive {
+ Variant(u32),
+}
+
+fn main() {
+ let mut x = ExhaustiveMonovariant::Variant(1);
+ let y = &mut x;
+ match x {
+ ExhaustiveMonovariant::Variant(_) => {},
+ _ => {},
+ }
+ drop(y);
+ let mut x = Local::Variant(1);
+ let y = &mut x;
+ match x {
+ Local::Variant(_) => {},
+ _ => {},
+ }
+ drop(y);
+ let mut x = LocalNonExhaustive::Variant(1);
+ let y = &mut x;
+ match x {
+ LocalNonExhaustive::Variant(_) => {},
+ _ => {},
+ }
+ drop(y);
+}
diff --git a/tests/ui/rfc-2008-non-exhaustive/borrowck-non-exhaustive.rs b/tests/ui/rfc-2008-non-exhaustive/borrowck-non-exhaustive.rs
new file mode 100644
index 000000000..2ad92b794
--- /dev/null
+++ b/tests/ui/rfc-2008-non-exhaustive/borrowck-non-exhaustive.rs
@@ -0,0 +1,18 @@
+// Test that the borrow checker considers `#[non_exhaustive]` when checking
+// whether a match contains a discriminant read.
+
+// aux-build:monovariants.rs
+extern crate monovariants;
+
+use monovariants::NonExhaustiveMonovariant;
+
+fn main() {
+ let mut x = NonExhaustiveMonovariant::Variant(1);
+ let y = &mut x;
+ match x {
+ //~^ ERROR cannot use `x` because it was mutably borrowed
+ NonExhaustiveMonovariant::Variant(_) => {},
+ _ => {},
+ }
+ drop(y);
+}
diff --git a/tests/ui/rfc-2008-non-exhaustive/borrowck-non-exhaustive.stderr b/tests/ui/rfc-2008-non-exhaustive/borrowck-non-exhaustive.stderr
new file mode 100644
index 000000000..de730ce10
--- /dev/null
+++ b/tests/ui/rfc-2008-non-exhaustive/borrowck-non-exhaustive.stderr
@@ -0,0 +1,14 @@
+error[E0503]: cannot use `x` because it was mutably borrowed
+ --> $DIR/borrowck-non-exhaustive.rs:12:11
+ |
+LL | let y = &mut x;
+ | ------ borrow of `x` occurs here
+LL | match x {
+ | ^ use of borrowed `x`
+...
+LL | drop(y);
+ | - borrow later used here
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0503`.
diff --git a/tests/ui/rfc-2008-non-exhaustive/enum-as-cast.rs b/tests/ui/rfc-2008-non-exhaustive/enum-as-cast.rs
new file mode 100644
index 000000000..5dce8180f
--- /dev/null
+++ b/tests/ui/rfc-2008-non-exhaustive/enum-as-cast.rs
@@ -0,0 +1,11 @@
+// aux-build:enums.rs
+
+extern crate enums;
+
+use enums::FieldLessWithNonExhaustiveVariant;
+
+fn main() {
+ let e = FieldLessWithNonExhaustiveVariant::default();
+ let d = e as u8; //~ ERROR casting `FieldLessWithNonExhaustiveVariant` as `u8` is invalid [E0606]
+ assert_eq!(d, 0);
+}
diff --git a/tests/ui/rfc-2008-non-exhaustive/enum-as-cast.stderr b/tests/ui/rfc-2008-non-exhaustive/enum-as-cast.stderr
new file mode 100644
index 000000000..a61dcf839
--- /dev/null
+++ b/tests/ui/rfc-2008-non-exhaustive/enum-as-cast.stderr
@@ -0,0 +1,11 @@
+error[E0606]: casting `FieldLessWithNonExhaustiveVariant` as `u8` is invalid
+ --> $DIR/enum-as-cast.rs:9:13
+ |
+LL | let d = e as u8;
+ | ^^^^^^^
+ |
+ = note: cannot cast an enum with a non-exhaustive variant when it's defined in another crate
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0606`.
diff --git a/tests/ui/rfc-2008-non-exhaustive/enum.rs b/tests/ui/rfc-2008-non-exhaustive/enum.rs
new file mode 100644
index 000000000..9d2855f5c
--- /dev/null
+++ b/tests/ui/rfc-2008-non-exhaustive/enum.rs
@@ -0,0 +1,69 @@
+// aux-build:enums.rs
+extern crate enums;
+
+use enums::{EmptyNonExhaustiveEnum, NonExhaustiveEnum};
+
+fn empty(x: EmptyNonExhaustiveEnum) {
+ match x {} //~ ERROR type `EmptyNonExhaustiveEnum` is non-empty
+ match x {
+ _ => {}, // ok
+ }
+}
+
+fn main() {
+ let enum_unit = NonExhaustiveEnum::Unit;
+
+ match enum_unit {
+ //~^ ERROR non-exhaustive patterns: `_` not covered [E0004]
+ NonExhaustiveEnum::Unit => "first",
+ NonExhaustiveEnum::Tuple(_) => "second",
+ NonExhaustiveEnum::Struct { .. } => "third"
+ };
+
+ match enum_unit {};
+ //~^ ERROR non-exhaustive patterns: `_` not covered [E0004]
+
+ // Everything below this is expected to compile successfully.
+
+ let enum_unit = NonExhaustiveEnum::Unit;
+
+ match enum_unit {
+ NonExhaustiveEnum::Unit => 1,
+ NonExhaustiveEnum::Tuple(_) => 2,
+ // This particular arm tests that an enum marked as non-exhaustive
+ // will not error if its variants are matched exhaustively.
+ NonExhaustiveEnum::Struct { field } => field,
+ _ => 0 // no error with wildcard
+ };
+
+ match enum_unit {
+ _ => "no error with only wildcard"
+ };
+
+ // #53549: Check that variant constructors can still be called normally.
+ match NonExhaustiveEnum::Unit {
+ NonExhaustiveEnum::Unit => {},
+ _ => {}
+ };
+
+ match NonExhaustiveEnum::Tuple(2) {
+ NonExhaustiveEnum::Tuple(2) => {},
+ _ => {}
+ };
+
+ match (NonExhaustiveEnum::Unit {}) {
+ NonExhaustiveEnum::Unit {} => {},
+ _ => {}
+ };
+
+ match (NonExhaustiveEnum::Tuple { 0: 2 }) {
+ NonExhaustiveEnum::Tuple { 0: 2 } => {},
+ _ => {}
+ };
+
+ match (NonExhaustiveEnum::Struct { field: 2 }) {
+ NonExhaustiveEnum::Struct { field: 2 } => {},
+ _ => {}
+ };
+
+}
diff --git a/tests/ui/rfc-2008-non-exhaustive/enum.stderr b/tests/ui/rfc-2008-non-exhaustive/enum.stderr
new file mode 100644
index 000000000..872cb9b8b
--- /dev/null
+++ b/tests/ui/rfc-2008-non-exhaustive/enum.stderr
@@ -0,0 +1,59 @@
+error[E0004]: non-exhaustive patterns: type `EmptyNonExhaustiveEnum` is non-empty
+ --> $DIR/enum.rs:7:11
+ |
+LL | match x {}
+ | ^
+ |
+note: `EmptyNonExhaustiveEnum` defined here
+ --> $DIR/auxiliary/enums.rs:18:1
+ |
+LL | pub enum EmptyNonExhaustiveEnum {}
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+ = note: the matched value is of type `EmptyNonExhaustiveEnum`, which is marked as non-exhaustive
+help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern as shown
+ |
+LL ~ match x {
+LL + _ => todo!(),
+LL ~ }
+ |
+
+error[E0004]: non-exhaustive patterns: `_` not covered
+ --> $DIR/enum.rs:16:11
+ |
+LL | match enum_unit {
+ | ^^^^^^^^^ pattern `_` not covered
+ |
+note: `NonExhaustiveEnum` defined here
+ --> $DIR/auxiliary/enums.rs:4:1
+ |
+LL | pub enum NonExhaustiveEnum {
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^
+ = note: the matched value is of type `NonExhaustiveEnum`, which is marked as non-exhaustive
+help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern or an explicit pattern as shown
+ |
+LL ~ NonExhaustiveEnum::Struct { .. } => "third",
+LL + _ => todo!()
+ |
+
+error[E0004]: non-exhaustive patterns: `_` not covered
+ --> $DIR/enum.rs:23:11
+ |
+LL | match enum_unit {};
+ | ^^^^^^^^^ pattern `_` not covered
+ |
+note: `NonExhaustiveEnum` defined here
+ --> $DIR/auxiliary/enums.rs:4:1
+ |
+LL | pub enum NonExhaustiveEnum {
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^
+ = note: the matched value is of type `NonExhaustiveEnum`, which is marked as non-exhaustive
+help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern or an explicit pattern as shown
+ |
+LL ~ match enum_unit {
+LL + _ => todo!(),
+LL ~ };
+ |
+
+error: aborting due to 3 previous errors
+
+For more information about this error, try `rustc --explain E0004`.
diff --git a/tests/ui/rfc-2008-non-exhaustive/enum_same_crate.rs b/tests/ui/rfc-2008-non-exhaustive/enum_same_crate.rs
new file mode 100644
index 000000000..54e42917f
--- /dev/null
+++ b/tests/ui/rfc-2008-non-exhaustive/enum_same_crate.rs
@@ -0,0 +1,18 @@
+// run-pass
+
+#[non_exhaustive]
+pub enum NonExhaustiveEnum {
+ Unit,
+ Tuple(u32),
+ Struct { field: u32 }
+}
+
+fn main() {
+ let enum_unit = NonExhaustiveEnum::Unit;
+
+ match enum_unit {
+ NonExhaustiveEnum::Unit => "first",
+ NonExhaustiveEnum::Tuple(_) => "second",
+ NonExhaustiveEnum::Struct { .. } => "third",
+ };
+}
diff --git a/tests/ui/rfc-2008-non-exhaustive/enum_same_crate_empty_match.rs b/tests/ui/rfc-2008-non-exhaustive/enum_same_crate_empty_match.rs
new file mode 100644
index 000000000..69a283c31
--- /dev/null
+++ b/tests/ui/rfc-2008-non-exhaustive/enum_same_crate_empty_match.rs
@@ -0,0 +1,37 @@
+#![deny(unreachable_patterns)]
+
+#[non_exhaustive]
+pub enum NonExhaustiveEnum {
+ Unit,
+ //~^ not covered
+ Tuple(u32),
+ //~^ not covered
+ Struct { field: u32 }
+ //~^ not covered
+}
+
+pub enum NormalEnum {
+ Unit,
+ //~^ not covered
+ Tuple(u32),
+ //~^ not covered
+ Struct { field: u32 }
+ //~^ not covered
+}
+
+#[non_exhaustive]
+pub enum EmptyNonExhaustiveEnum {}
+
+fn empty_non_exhaustive(x: EmptyNonExhaustiveEnum) {
+ match x {}
+ match x {
+ _ => {} //~ ERROR unreachable pattern
+ }
+}
+
+fn main() {
+ match NonExhaustiveEnum::Unit {}
+ //~^ ERROR `NonExhaustiveEnum::Unit`, `NonExhaustiveEnum::Tuple(_)` and `NonExhaustiveEnum::Struct { .. }` not covered [E0004]
+ match NormalEnum::Unit {}
+ //~^ ERROR `NormalEnum::Unit`, `NormalEnum::Tuple(_)` and `NormalEnum::Struct { .. }` not covered [E0004]
+}
diff --git a/tests/ui/rfc-2008-non-exhaustive/enum_same_crate_empty_match.stderr b/tests/ui/rfc-2008-non-exhaustive/enum_same_crate_empty_match.stderr
new file mode 100644
index 000000000..de1bf8be8
--- /dev/null
+++ b/tests/ui/rfc-2008-non-exhaustive/enum_same_crate_empty_match.stderr
@@ -0,0 +1,69 @@
+error: unreachable pattern
+ --> $DIR/enum_same_crate_empty_match.rs:28:9
+ |
+LL | _ => {}
+ | ^
+ |
+note: the lint level is defined here
+ --> $DIR/enum_same_crate_empty_match.rs:1:9
+ |
+LL | #![deny(unreachable_patterns)]
+ | ^^^^^^^^^^^^^^^^^^^^
+
+error[E0004]: non-exhaustive patterns: `NonExhaustiveEnum::Unit`, `NonExhaustiveEnum::Tuple(_)` and `NonExhaustiveEnum::Struct { .. }` not covered
+ --> $DIR/enum_same_crate_empty_match.rs:33:11
+ |
+LL | match NonExhaustiveEnum::Unit {}
+ | ^^^^^^^^^^^^^^^^^^^^^^^ patterns `NonExhaustiveEnum::Unit`, `NonExhaustiveEnum::Tuple(_)` and `NonExhaustiveEnum::Struct { .. }` not covered
+ |
+note: `NonExhaustiveEnum` defined here
+ --> $DIR/enum_same_crate_empty_match.rs:5:5
+ |
+LL | pub enum NonExhaustiveEnum {
+ | -----------------
+LL | Unit,
+ | ^^^^ not covered
+LL |
+LL | Tuple(u32),
+ | ^^^^^ not covered
+LL |
+LL | Struct { field: u32 }
+ | ^^^^^^ not covered
+ = note: the matched value is of type `NonExhaustiveEnum`
+help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern, a match arm with multiple or-patterns as shown, or multiple match arms
+ |
+LL ~ match NonExhaustiveEnum::Unit {
+LL + NonExhaustiveEnum::Unit | NonExhaustiveEnum::Tuple(_) | NonExhaustiveEnum::Struct { .. } => todo!(),
+LL + }
+ |
+
+error[E0004]: non-exhaustive patterns: `NormalEnum::Unit`, `NormalEnum::Tuple(_)` and `NormalEnum::Struct { .. }` not covered
+ --> $DIR/enum_same_crate_empty_match.rs:35:11
+ |
+LL | match NormalEnum::Unit {}
+ | ^^^^^^^^^^^^^^^^ patterns `NormalEnum::Unit`, `NormalEnum::Tuple(_)` and `NormalEnum::Struct { .. }` not covered
+ |
+note: `NormalEnum` defined here
+ --> $DIR/enum_same_crate_empty_match.rs:14:5
+ |
+LL | pub enum NormalEnum {
+ | ----------
+LL | Unit,
+ | ^^^^ not covered
+LL |
+LL | Tuple(u32),
+ | ^^^^^ not covered
+LL |
+LL | Struct { field: u32 }
+ | ^^^^^^ not covered
+ = note: the matched value is of type `NormalEnum`
+help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern, a match arm with multiple or-patterns as shown, or multiple match arms
+ |
+LL ~ match NormalEnum::Unit {
+LL + NormalEnum::Unit | NormalEnum::Tuple(_) | NormalEnum::Struct { .. } => todo!(),
+LL + }
+ |
+
+error: aborting due to 3 previous errors
+
+For more information about this error, try `rustc --explain E0004`.
diff --git a/tests/ui/rfc-2008-non-exhaustive/improper_ctypes/auxiliary/types.rs b/tests/ui/rfc-2008-non-exhaustive/improper_ctypes/auxiliary/types.rs
new file mode 100644
index 000000000..d6251fcb7
--- /dev/null
+++ b/tests/ui/rfc-2008-non-exhaustive/improper_ctypes/auxiliary/types.rs
@@ -0,0 +1,29 @@
+#[non_exhaustive]
+#[repr(C)]
+pub enum NonExhaustiveEnum {
+ Unit,
+ Tuple(u32),
+ Struct { field: u32 }
+}
+
+#[non_exhaustive]
+#[repr(C)]
+pub struct NormalStruct {
+ pub first_field: u16,
+ pub second_field: u16,
+}
+
+#[non_exhaustive]
+#[repr(C)]
+pub struct UnitStruct;
+
+#[non_exhaustive]
+#[repr(C)]
+pub struct TupleStruct (pub u16, pub u16);
+
+#[repr(C)]
+pub enum NonExhaustiveVariants {
+ #[non_exhaustive] Unit,
+ #[non_exhaustive] Tuple(u32),
+ #[non_exhaustive] Struct { field: u32 }
+}
diff --git a/tests/ui/rfc-2008-non-exhaustive/improper_ctypes/extern_crate_improper.rs b/tests/ui/rfc-2008-non-exhaustive/improper_ctypes/extern_crate_improper.rs
new file mode 100644
index 000000000..15c0c695f
--- /dev/null
+++ b/tests/ui/rfc-2008-non-exhaustive/improper_ctypes/extern_crate_improper.rs
@@ -0,0 +1,24 @@
+// aux-build:types.rs
+#![deny(improper_ctypes)]
+
+extern crate types;
+
+// This test checks that non-exhaustive types with `#[repr(C)]` from an extern crate are considered
+// improper.
+
+use types::{NonExhaustiveEnum, NonExhaustiveVariants, NormalStruct, TupleStruct, UnitStruct};
+
+extern "C" {
+ pub fn non_exhaustive_enum(_: NonExhaustiveEnum);
+ //~^ ERROR `extern` block uses type `NonExhaustiveEnum`, which is not FFI-safe
+ pub fn non_exhaustive_normal_struct(_: NormalStruct);
+ //~^ ERROR `extern` block uses type `NormalStruct`, which is not FFI-safe
+ pub fn non_exhaustive_unit_struct(_: UnitStruct);
+ //~^ ERROR `extern` block uses type `UnitStruct`, which is not FFI-safe
+ pub fn non_exhaustive_tuple_struct(_: TupleStruct);
+ //~^ ERROR `extern` block uses type `TupleStruct`, which is not FFI-safe
+ pub fn non_exhaustive_variant(_: NonExhaustiveVariants);
+ //~^ ERROR `extern` block uses type `NonExhaustiveVariants`, which is not FFI-safe
+}
+
+fn main() {}
diff --git a/tests/ui/rfc-2008-non-exhaustive/improper_ctypes/extern_crate_improper.stderr b/tests/ui/rfc-2008-non-exhaustive/improper_ctypes/extern_crate_improper.stderr
new file mode 100644
index 000000000..43c8e1015
--- /dev/null
+++ b/tests/ui/rfc-2008-non-exhaustive/improper_ctypes/extern_crate_improper.stderr
@@ -0,0 +1,47 @@
+error: `extern` block uses type `NonExhaustiveEnum`, which is not FFI-safe
+ --> $DIR/extern_crate_improper.rs:12:35
+ |
+LL | pub fn non_exhaustive_enum(_: NonExhaustiveEnum);
+ | ^^^^^^^^^^^^^^^^^ not FFI-safe
+ |
+ = note: this enum is non-exhaustive
+note: the lint level is defined here
+ --> $DIR/extern_crate_improper.rs:2:9
+ |
+LL | #![deny(improper_ctypes)]
+ | ^^^^^^^^^^^^^^^
+
+error: `extern` block uses type `NormalStruct`, which is not FFI-safe
+ --> $DIR/extern_crate_improper.rs:14:44
+ |
+LL | pub fn non_exhaustive_normal_struct(_: NormalStruct);
+ | ^^^^^^^^^^^^ not FFI-safe
+ |
+ = note: this struct is non-exhaustive
+
+error: `extern` block uses type `UnitStruct`, which is not FFI-safe
+ --> $DIR/extern_crate_improper.rs:16:42
+ |
+LL | pub fn non_exhaustive_unit_struct(_: UnitStruct);
+ | ^^^^^^^^^^ not FFI-safe
+ |
+ = note: this struct is non-exhaustive
+
+error: `extern` block uses type `TupleStruct`, which is not FFI-safe
+ --> $DIR/extern_crate_improper.rs:18:43
+ |
+LL | pub fn non_exhaustive_tuple_struct(_: TupleStruct);
+ | ^^^^^^^^^^^ not FFI-safe
+ |
+ = note: this struct is non-exhaustive
+
+error: `extern` block uses type `NonExhaustiveVariants`, which is not FFI-safe
+ --> $DIR/extern_crate_improper.rs:20:38
+ |
+LL | pub fn non_exhaustive_variant(_: NonExhaustiveVariants);
+ | ^^^^^^^^^^^^^^^^^^^^^ not FFI-safe
+ |
+ = note: this enum has non-exhaustive variants
+
+error: aborting due to 5 previous errors
+
diff --git a/tests/ui/rfc-2008-non-exhaustive/improper_ctypes/same_crate_proper.rs b/tests/ui/rfc-2008-non-exhaustive/improper_ctypes/same_crate_proper.rs
new file mode 100644
index 000000000..fe4ae345d
--- /dev/null
+++ b/tests/ui/rfc-2008-non-exhaustive/improper_ctypes/same_crate_proper.rs
@@ -0,0 +1,48 @@
+// check-pass
+#![deny(improper_ctypes)]
+
+// This test checks that non-exhaustive types with `#[repr(C)]` are considered proper within
+// the defining crate.
+
+#[non_exhaustive]
+#[repr(C)]
+pub enum NonExhaustiveEnum {
+ Unit,
+ Tuple(u32),
+ Struct { field: u32 },
+}
+
+#[non_exhaustive]
+#[repr(C)]
+pub struct NormalStruct {
+ pub first_field: u16,
+ pub second_field: u16,
+}
+
+#[non_exhaustive]
+#[repr(C)]
+pub struct UnitStruct;
+
+#[non_exhaustive]
+#[repr(C)]
+pub struct TupleStruct(pub u16, pub u16);
+
+#[repr(C)]
+pub enum NonExhaustiveVariants {
+ #[non_exhaustive]
+ Unit,
+ #[non_exhaustive]
+ Tuple(u32),
+ #[non_exhaustive]
+ Struct { field: u32 },
+}
+
+extern "C" {
+ // Unit structs aren't tested here because they will trigger `improper_ctypes` anyway.
+ pub fn non_exhaustive_enum(_: NonExhaustiveEnum);
+ pub fn non_exhaustive_normal_struct(_: NormalStruct);
+ pub fn non_exhaustive_tuple_struct(_: TupleStruct);
+ pub fn non_exhaustive_variant(_: NonExhaustiveVariants);
+}
+
+fn main() {}
diff --git a/tests/ui/rfc-2008-non-exhaustive/invalid-attribute.rs b/tests/ui/rfc-2008-non-exhaustive/invalid-attribute.rs
new file mode 100644
index 000000000..143f9a300
--- /dev/null
+++ b/tests/ui/rfc-2008-non-exhaustive/invalid-attribute.rs
@@ -0,0 +1,16 @@
+#[non_exhaustive(anything)]
+//~^ ERROR malformed `non_exhaustive` attribute
+struct Foo;
+
+#[non_exhaustive]
+//~^ ERROR attribute should be applied to a struct or enum [E0701]
+trait Bar { }
+
+#[non_exhaustive]
+//~^ ERROR attribute should be applied to a struct or enum [E0701]
+union Baz {
+ f1: u16,
+ f2: u16
+}
+
+fn main() { }
diff --git a/tests/ui/rfc-2008-non-exhaustive/invalid-attribute.stderr b/tests/ui/rfc-2008-non-exhaustive/invalid-attribute.stderr
new file mode 100644
index 000000000..136cd763b
--- /dev/null
+++ b/tests/ui/rfc-2008-non-exhaustive/invalid-attribute.stderr
@@ -0,0 +1,30 @@
+error: malformed `non_exhaustive` attribute input
+ --> $DIR/invalid-attribute.rs:1:1
+ |
+LL | #[non_exhaustive(anything)]
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: must be of the form: `#[non_exhaustive]`
+
+error[E0701]: attribute should be applied to a struct or enum
+ --> $DIR/invalid-attribute.rs:5:1
+ |
+LL | #[non_exhaustive]
+ | ^^^^^^^^^^^^^^^^^
+LL |
+LL | trait Bar { }
+ | ------------- not a struct or enum
+
+error[E0701]: attribute should be applied to a struct or enum
+ --> $DIR/invalid-attribute.rs:9:1
+ |
+LL | #[non_exhaustive]
+ | ^^^^^^^^^^^^^^^^^
+LL |
+LL | / union Baz {
+LL | | f1: u16,
+LL | | f2: u16
+LL | | }
+ | |_- not a struct or enum
+
+error: aborting due to 3 previous errors
+
+For more information about this error, try `rustc --explain E0701`.
diff --git a/tests/ui/rfc-2008-non-exhaustive/omitted-patterns.rs b/tests/ui/rfc-2008-non-exhaustive/omitted-patterns.rs
new file mode 100644
index 000000000..d8f07bb8f
--- /dev/null
+++ b/tests/ui/rfc-2008-non-exhaustive/omitted-patterns.rs
@@ -0,0 +1,187 @@
+// Test that the `non_exhaustive_omitted_patterns` lint is triggered correctly.
+
+#![feature(non_exhaustive_omitted_patterns_lint, unstable_test_feature)]
+
+// aux-build:enums.rs
+extern crate enums;
+// aux-build:unstable.rs
+extern crate unstable;
+// aux-build:structs.rs
+extern crate structs;
+
+use enums::{
+ EmptyNonExhaustiveEnum, NestedNonExhaustive, NonExhaustiveEnum, NonExhaustiveSingleVariant,
+ VariantNonExhaustive,
+};
+use unstable::{UnstableEnum, OnlyUnstableEnum, UnstableStruct, OnlyUnstableStruct};
+use structs::{FunctionalRecord, MixedVisFields, NestedStruct, NormalStruct};
+
+#[non_exhaustive]
+#[derive(Default)]
+pub struct Foo {
+ a: u8,
+ b: usize,
+ c: String,
+}
+
+#[non_exhaustive]
+pub enum Bar {
+ A,
+ B,
+ C,
+}
+
+fn main() {
+ let enumeration = Bar::A;
+
+ // Ok: this is a crate local non_exhaustive enum
+ match enumeration {
+ Bar::A => {}
+ Bar::B => {}
+ #[deny(non_exhaustive_omitted_patterns)]
+ _ => {}
+ }
+
+ let non_enum = NonExhaustiveEnum::Unit;
+
+ // Ok: without the attribute
+ match non_enum {
+ NonExhaustiveEnum::Unit => {}
+ NonExhaustiveEnum::Tuple(_) => {}
+ _ => {}
+ }
+
+ match non_enum {
+ NonExhaustiveEnum::Unit => {}
+ NonExhaustiveEnum::Tuple(_) => {}
+ #[deny(non_exhaustive_omitted_patterns)]
+ _ => {}
+ }
+ //~^^ some variants are not matched explicitly
+
+ match non_enum {
+ NonExhaustiveEnum::Unit | NonExhaustiveEnum::Struct { .. } => {}
+ #[deny(non_exhaustive_omitted_patterns)]
+ _ => {}
+ }
+ //~^^ some variants are not matched explicitly
+
+ let x = 5;
+ match non_enum {
+ NonExhaustiveEnum::Unit if x > 10 => {}
+ NonExhaustiveEnum::Tuple(_) => {}
+ NonExhaustiveEnum::Struct { .. } => {}
+ #[deny(non_exhaustive_omitted_patterns)]
+ _ => {}
+ }
+ //~^^ some variants are not matched explicitly
+
+ // Ok: all covered and not `unreachable-patterns`
+ #[deny(unreachable_patterns)]
+ match non_enum {
+ NonExhaustiveEnum::Unit => {}
+ NonExhaustiveEnum::Tuple(_) => {}
+ NonExhaustiveEnum::Struct { .. } => {}
+ #[deny(non_exhaustive_omitted_patterns)]
+ _ => {}
+ }
+
+ #[deny(non_exhaustive_omitted_patterns)]
+ match NestedNonExhaustive::B {
+ NestedNonExhaustive::A(NonExhaustiveEnum::Unit) => {}
+ NestedNonExhaustive::A(_) => {}
+ NestedNonExhaustive::B => {}
+ _ => {}
+ }
+ //~^^ some variants are not matched explicitly
+ //~^^^^^ some variants are not matched explicitly
+
+ #[warn(non_exhaustive_omitted_patterns)]
+ match VariantNonExhaustive::Baz(1, 2) {
+ VariantNonExhaustive::Baz(_, _) => {}
+ VariantNonExhaustive::Bar { x, .. } => {}
+ }
+ //~^^ some fields are not explicitly listed
+
+ #[warn(non_exhaustive_omitted_patterns)]
+ let FunctionalRecord { first_field, second_field, .. } = FunctionalRecord::default();
+ //~^ some fields are not explicitly listed
+
+ // Ok: this is local
+ #[warn(non_exhaustive_omitted_patterns)]
+ let Foo { a, b, .. } = Foo::default();
+
+ #[warn(non_exhaustive_omitted_patterns)]
+ let NestedStruct { bar: NormalStruct { first_field, .. }, .. } = NestedStruct::default();
+ //~^ some fields are not explicitly listed
+ //~^^ some fields are not explicitly listed
+
+ // Ok: this tests https://github.com/rust-lang/rust/issues/89382
+ #[warn(non_exhaustive_omitted_patterns)]
+ let MixedVisFields { a, b, .. } = MixedVisFields::default();
+
+ // Ok: because this only has 1 variant
+ #[deny(non_exhaustive_omitted_patterns)]
+ match NonExhaustiveSingleVariant::A(true) {
+ NonExhaustiveSingleVariant::A(true) => {}
+ _ => {}
+ }
+
+ #[deny(non_exhaustive_omitted_patterns)]
+ match NonExhaustiveSingleVariant::A(true) {
+ _ => {}
+ }
+ //~^^ some variants are not matched explicitly
+
+ // Ok: we don't lint on `if let` expressions
+ #[deny(non_exhaustive_omitted_patterns)]
+ if let NonExhaustiveEnum::Tuple(_) = non_enum {}
+
+ match UnstableEnum::Stable {
+ UnstableEnum::Stable => {}
+ UnstableEnum::Stable2 => {}
+ #[deny(non_exhaustive_omitted_patterns)]
+ _ => {}
+ }
+ //~^^ some variants are not matched explicitly
+
+ // Ok: the feature is on and all variants are matched
+ #[deny(non_exhaustive_omitted_patterns)]
+ match UnstableEnum::Stable {
+ UnstableEnum::Stable => {}
+ UnstableEnum::Stable2 => {}
+ UnstableEnum::Unstable => {}
+ _ => {}
+ }
+
+ // Ok: the feature is on and both variants are matched
+ #[deny(non_exhaustive_omitted_patterns)]
+ match OnlyUnstableEnum::Unstable {
+ OnlyUnstableEnum::Unstable => {}
+ OnlyUnstableEnum::Unstable2 => {}
+ _ => {}
+ }
+
+ #[deny(non_exhaustive_omitted_patterns)]
+ match OnlyUnstableEnum::Unstable {
+ OnlyUnstableEnum::Unstable => {}
+ _ => {}
+ }
+ //~^^ some variants are not matched explicitly
+
+ #[warn(non_exhaustive_omitted_patterns)]
+ let OnlyUnstableStruct { unstable, .. } = OnlyUnstableStruct::new();
+ //~^ some fields are not explicitly listed
+
+ // OK: both unstable fields are matched with feature on
+ #[warn(non_exhaustive_omitted_patterns)]
+ let OnlyUnstableStruct { unstable, unstable2, .. } = OnlyUnstableStruct::new();
+
+ #[warn(non_exhaustive_omitted_patterns)]
+ let UnstableStruct { stable, stable2, .. } = UnstableStruct::default();
+ //~^ some fields are not explicitly listed
+
+ // OK: both unstable and stable fields are matched with feature on
+ #[warn(non_exhaustive_omitted_patterns)]
+ let UnstableStruct { stable, stable2, unstable, .. } = UnstableStruct::default();
+}
diff --git a/tests/ui/rfc-2008-non-exhaustive/omitted-patterns.stderr b/tests/ui/rfc-2008-non-exhaustive/omitted-patterns.stderr
new file mode 100644
index 000000000..996bd4a12
--- /dev/null
+++ b/tests/ui/rfc-2008-non-exhaustive/omitted-patterns.stderr
@@ -0,0 +1,188 @@
+warning: some fields are not explicitly listed
+ --> $DIR/omitted-patterns.rs:102:9
+ |
+LL | VariantNonExhaustive::Bar { x, .. } => {}
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ field `y` not listed
+ |
+ = help: ensure that all fields are mentioned explicitly by adding the suggested fields
+ = note: the pattern is of type `VariantNonExhaustive` and the `non_exhaustive_omitted_patterns` attribute was found
+note: the lint level is defined here
+ --> $DIR/omitted-patterns.rs:99:12
+ |
+LL | #[warn(non_exhaustive_omitted_patterns)]
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+warning: some fields are not explicitly listed
+ --> $DIR/omitted-patterns.rs:107:9
+ |
+LL | let FunctionalRecord { first_field, second_field, .. } = FunctionalRecord::default();
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ field `third_field` not listed
+ |
+ = help: ensure that all fields are mentioned explicitly by adding the suggested fields
+ = note: the pattern is of type `FunctionalRecord` and the `non_exhaustive_omitted_patterns` attribute was found
+note: the lint level is defined here
+ --> $DIR/omitted-patterns.rs:106:12
+ |
+LL | #[warn(non_exhaustive_omitted_patterns)]
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+warning: some fields are not explicitly listed
+ --> $DIR/omitted-patterns.rs:115:29
+ |
+LL | let NestedStruct { bar: NormalStruct { first_field, .. }, .. } = NestedStruct::default();
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ field `second_field` not listed
+ |
+ = help: ensure that all fields are mentioned explicitly by adding the suggested fields
+ = note: the pattern is of type `NormalStruct` and the `non_exhaustive_omitted_patterns` attribute was found
+note: the lint level is defined here
+ --> $DIR/omitted-patterns.rs:114:12
+ |
+LL | #[warn(non_exhaustive_omitted_patterns)]
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+warning: some fields are not explicitly listed
+ --> $DIR/omitted-patterns.rs:115:9
+ |
+LL | let NestedStruct { bar: NormalStruct { first_field, .. }, .. } = NestedStruct::default();
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ field `foo` not listed
+ |
+ = help: ensure that all fields are mentioned explicitly by adding the suggested fields
+ = note: the pattern is of type `NestedStruct` and the `non_exhaustive_omitted_patterns` attribute was found
+
+warning: some fields are not explicitly listed
+ --> $DIR/omitted-patterns.rs:173:9
+ |
+LL | let OnlyUnstableStruct { unstable, .. } = OnlyUnstableStruct::new();
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ field `unstable2` not listed
+ |
+ = help: ensure that all fields are mentioned explicitly by adding the suggested fields
+ = note: the pattern is of type `OnlyUnstableStruct` and the `non_exhaustive_omitted_patterns` attribute was found
+note: the lint level is defined here
+ --> $DIR/omitted-patterns.rs:172:12
+ |
+LL | #[warn(non_exhaustive_omitted_patterns)]
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+warning: some fields are not explicitly listed
+ --> $DIR/omitted-patterns.rs:181:9
+ |
+LL | let UnstableStruct { stable, stable2, .. } = UnstableStruct::default();
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ field `unstable` not listed
+ |
+ = help: ensure that all fields are mentioned explicitly by adding the suggested fields
+ = note: the pattern is of type `UnstableStruct` and the `non_exhaustive_omitted_patterns` attribute was found
+note: the lint level is defined here
+ --> $DIR/omitted-patterns.rs:180:12
+ |
+LL | #[warn(non_exhaustive_omitted_patterns)]
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: some variants are not matched explicitly
+ --> $DIR/omitted-patterns.rs:58:9
+ |
+LL | _ => {}
+ | ^ pattern `NonExhaustiveEnum::Struct { .. }` not covered
+ |
+ = help: ensure that all variants are matched explicitly by adding the suggested match arms
+ = note: the matched value is of type `NonExhaustiveEnum` and the `non_exhaustive_omitted_patterns` attribute was found
+note: the lint level is defined here
+ --> $DIR/omitted-patterns.rs:57:16
+ |
+LL | #[deny(non_exhaustive_omitted_patterns)]
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: some variants are not matched explicitly
+ --> $DIR/omitted-patterns.rs:65:9
+ |
+LL | _ => {}
+ | ^ pattern `NonExhaustiveEnum::Tuple(_)` not covered
+ |
+ = help: ensure that all variants are matched explicitly by adding the suggested match arms
+ = note: the matched value is of type `NonExhaustiveEnum` and the `non_exhaustive_omitted_patterns` attribute was found
+note: the lint level is defined here
+ --> $DIR/omitted-patterns.rs:64:16
+ |
+LL | #[deny(non_exhaustive_omitted_patterns)]
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: some variants are not matched explicitly
+ --> $DIR/omitted-patterns.rs:75:9
+ |
+LL | _ => {}
+ | ^ pattern `NonExhaustiveEnum::Unit` not covered
+ |
+ = help: ensure that all variants are matched explicitly by adding the suggested match arms
+ = note: the matched value is of type `NonExhaustiveEnum` and the `non_exhaustive_omitted_patterns` attribute was found
+note: the lint level is defined here
+ --> $DIR/omitted-patterns.rs:74:16
+ |
+LL | #[deny(non_exhaustive_omitted_patterns)]
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: some variants are not matched explicitly
+ --> $DIR/omitted-patterns.rs:92:32
+ |
+LL | NestedNonExhaustive::A(_) => {}
+ | ^ patterns `NonExhaustiveEnum::Tuple(_)` and `NonExhaustiveEnum::Struct { .. }` not covered
+ |
+ = help: ensure that all variants are matched explicitly by adding the suggested match arms
+ = note: the matched value is of type `NonExhaustiveEnum` and the `non_exhaustive_omitted_patterns` attribute was found
+note: the lint level is defined here
+ --> $DIR/omitted-patterns.rs:89:12
+ |
+LL | #[deny(non_exhaustive_omitted_patterns)]
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: some variants are not matched explicitly
+ --> $DIR/omitted-patterns.rs:94:9
+ |
+LL | _ => {}
+ | ^ pattern `NestedNonExhaustive::C` not covered
+ |
+ = help: ensure that all variants are matched explicitly by adding the suggested match arms
+ = note: the matched value is of type `NestedNonExhaustive` and the `non_exhaustive_omitted_patterns` attribute was found
+
+error: some variants are not matched explicitly
+ --> $DIR/omitted-patterns.rs:132:9
+ |
+LL | _ => {}
+ | ^ pattern `NonExhaustiveSingleVariant::A(_)` not covered
+ |
+ = help: ensure that all variants are matched explicitly by adding the suggested match arms
+ = note: the matched value is of type `NonExhaustiveSingleVariant` and the `non_exhaustive_omitted_patterns` attribute was found
+note: the lint level is defined here
+ --> $DIR/omitted-patterns.rs:130:12
+ |
+LL | #[deny(non_exhaustive_omitted_patterns)]
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: some variants are not matched explicitly
+ --> $DIR/omitted-patterns.rs:144:9
+ |
+LL | _ => {}
+ | ^ pattern `UnstableEnum::Unstable` not covered
+ |
+ = help: ensure that all variants are matched explicitly by adding the suggested match arms
+ = note: the matched value is of type `UnstableEnum` and the `non_exhaustive_omitted_patterns` attribute was found
+note: the lint level is defined here
+ --> $DIR/omitted-patterns.rs:143:16
+ |
+LL | #[deny(non_exhaustive_omitted_patterns)]
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: some variants are not matched explicitly
+ --> $DIR/omitted-patterns.rs:168:9
+ |
+LL | _ => {}
+ | ^ pattern `OnlyUnstableEnum::Unstable2` not covered
+ |
+ = help: ensure that all variants are matched explicitly by adding the suggested match arms
+ = note: the matched value is of type `OnlyUnstableEnum` and the `non_exhaustive_omitted_patterns` attribute was found
+note: the lint level is defined here
+ --> $DIR/omitted-patterns.rs:165:12
+ |
+LL | #[deny(non_exhaustive_omitted_patterns)]
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: aborting due to 8 previous errors; 6 warnings emitted
+
diff --git a/tests/ui/rfc-2008-non-exhaustive/stable-omitted-patterns.rs b/tests/ui/rfc-2008-non-exhaustive/stable-omitted-patterns.rs
new file mode 100644
index 000000000..82ee68687
--- /dev/null
+++ b/tests/ui/rfc-2008-non-exhaustive/stable-omitted-patterns.rs
@@ -0,0 +1,45 @@
+// Test that the `non_exhaustive_omitted_patterns` lint is triggered correctly with variants
+// marked stable and unstable.
+
+#![feature(non_exhaustive_omitted_patterns_lint)]
+
+// aux-build:unstable.rs
+extern crate unstable;
+
+use unstable::{UnstableEnum, OnlyUnstableEnum, UnstableStruct, OnlyUnstableStruct};
+
+fn main() {
+ // OK: this matches all the stable variants
+ match UnstableEnum::Stable {
+ UnstableEnum::Stable => {}
+ UnstableEnum::Stable2 => {}
+ #[deny(non_exhaustive_omitted_patterns)]
+ _ => {}
+ }
+
+ match UnstableEnum::Stable {
+ UnstableEnum::Stable => {}
+ #[deny(non_exhaustive_omitted_patterns)]
+ _ => {}
+ }
+ //~^^ some variants are not matched explicitly
+
+ // Ok: although this is a bit odd, we don't have anything to report
+ // since there is no stable variants and the feature is off
+ #[deny(non_exhaustive_omitted_patterns)]
+ match OnlyUnstableEnum::new() {
+ _ => {}
+ }
+
+ // Ok: Same as the above enum (no fields can be matched on)
+ #[warn(non_exhaustive_omitted_patterns)]
+ let OnlyUnstableStruct { .. } = OnlyUnstableStruct::new();
+
+ #[warn(non_exhaustive_omitted_patterns)]
+ let UnstableStruct { stable, .. } = UnstableStruct::default();
+ //~^ some fields are not explicitly listed
+
+ // OK: stable field is matched
+ #[warn(non_exhaustive_omitted_patterns)]
+ let UnstableStruct { stable, stable2, .. } = UnstableStruct::default();
+}
diff --git a/tests/ui/rfc-2008-non-exhaustive/stable-omitted-patterns.stderr b/tests/ui/rfc-2008-non-exhaustive/stable-omitted-patterns.stderr
new file mode 100644
index 000000000..f38368590
--- /dev/null
+++ b/tests/ui/rfc-2008-non-exhaustive/stable-omitted-patterns.stderr
@@ -0,0 +1,30 @@
+warning: some fields are not explicitly listed
+ --> $DIR/stable-omitted-patterns.rs:39:9
+ |
+LL | let UnstableStruct { stable, .. } = UnstableStruct::default();
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ field `stable2` not listed
+ |
+ = help: ensure that all fields are mentioned explicitly by adding the suggested fields
+ = note: the pattern is of type `UnstableStruct` and the `non_exhaustive_omitted_patterns` attribute was found
+note: the lint level is defined here
+ --> $DIR/stable-omitted-patterns.rs:38:12
+ |
+LL | #[warn(non_exhaustive_omitted_patterns)]
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: some variants are not matched explicitly
+ --> $DIR/stable-omitted-patterns.rs:23:9
+ |
+LL | _ => {}
+ | ^ pattern `UnstableEnum::Stable2` not covered
+ |
+ = help: ensure that all variants are matched explicitly by adding the suggested match arms
+ = note: the matched value is of type `UnstableEnum` and the `non_exhaustive_omitted_patterns` attribute was found
+note: the lint level is defined here
+ --> $DIR/stable-omitted-patterns.rs:22:16
+ |
+LL | #[deny(non_exhaustive_omitted_patterns)]
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: aborting due to previous error; 1 warning emitted
+
diff --git a/tests/ui/rfc-2008-non-exhaustive/struct.rs b/tests/ui/rfc-2008-non-exhaustive/struct.rs
new file mode 100644
index 000000000..07e093c15
--- /dev/null
+++ b/tests/ui/rfc-2008-non-exhaustive/struct.rs
@@ -0,0 +1,49 @@
+// aux-build:structs.rs
+extern crate structs;
+
+use structs::{NormalStruct, UnitStruct, TupleStruct, FunctionalRecord};
+
+fn main() {
+ let fr = FunctionalRecord {
+ //~^ ERROR cannot create non-exhaustive struct
+ first_field: 1920,
+ second_field: 1080,
+ ..FunctionalRecord::default()
+ };
+
+ let ns = NormalStruct { first_field: 640, second_field: 480 };
+ //~^ ERROR cannot create non-exhaustive struct
+
+ let NormalStruct { first_field, second_field } = ns;
+ //~^ ERROR `..` required with struct marked as non-exhaustive
+
+ let ts = TupleStruct(640, 480);
+ //~^ ERROR cannot initialize a tuple struct which contains private fields [E0423]
+
+ let ts_explicit = structs::TupleStruct(640, 480);
+ //~^ ERROR tuple struct constructor `TupleStruct` is private [E0603]
+
+ let TupleStruct { 0: first_field, 1: second_field } = ts;
+ //~^ ERROR `..` required with struct marked as non-exhaustive
+
+ let us = UnitStruct;
+ //~^ ERROR expected value, found struct `UnitStruct` [E0423]
+
+ let us_explicit = structs::UnitStruct;
+ //~^ ERROR unit struct `UnitStruct` is private [E0603]
+
+ let UnitStruct { } = us;
+ //~^ ERROR `..` required with struct marked as non-exhaustive
+}
+
+// Everything below this is expected to compile successfully.
+
+// We only test matching here as we cannot create non-exhaustive
+// structs from another crate. ie. they'll never pass in run-pass tests.
+fn match_structs(ns: NormalStruct, ts: TupleStruct, us: UnitStruct) {
+ let NormalStruct { first_field, second_field, .. } = ns;
+
+ let TupleStruct { 0: first, 1: second, .. } = ts;
+
+ let UnitStruct { .. } = us;
+}
diff --git a/tests/ui/rfc-2008-non-exhaustive/struct.stderr b/tests/ui/rfc-2008-non-exhaustive/struct.stderr
new file mode 100644
index 000000000..2cb9ba0d1
--- /dev/null
+++ b/tests/ui/rfc-2008-non-exhaustive/struct.stderr
@@ -0,0 +1,96 @@
+error[E0423]: expected value, found struct `UnitStruct`
+ --> $DIR/struct.rs:29:14
+ |
+LL | let us = UnitStruct;
+ | ^^^^^^^^^^ constructor is not visible here due to private fields
+
+error[E0603]: tuple struct constructor `TupleStruct` is private
+ --> $DIR/struct.rs:23:32
+ |
+LL | let ts_explicit = structs::TupleStruct(640, 480);
+ | ^^^^^^^^^^^ private tuple struct constructor
+ |
+ ::: $DIR/auxiliary/structs.rs:12:24
+ |
+LL | pub struct TupleStruct(pub u16, pub u16);
+ | ---------------- a constructor is private if any of the fields is private
+ |
+note: the tuple struct constructor `TupleStruct` is defined here
+ --> $DIR/auxiliary/structs.rs:12:1
+ |
+LL | pub struct TupleStruct(pub u16, pub u16);
+ | ^^^^^^^^^^^^^^^^^^^^^^
+
+error[E0603]: unit struct `UnitStruct` is private
+ --> $DIR/struct.rs:32:32
+ |
+LL | let us_explicit = structs::UnitStruct;
+ | ^^^^^^^^^^ private unit struct
+ |
+note: the unit struct `UnitStruct` is defined here
+ --> $DIR/auxiliary/structs.rs:9:1
+ |
+LL | pub struct UnitStruct;
+ | ^^^^^^^^^^^^^^^^^^^^^
+
+error[E0639]: cannot create non-exhaustive struct using struct expression
+ --> $DIR/struct.rs:7:14
+ |
+LL | let fr = FunctionalRecord {
+ | ______________^
+LL | |
+LL | | first_field: 1920,
+LL | | second_field: 1080,
+LL | | ..FunctionalRecord::default()
+LL | | };
+ | |_____^
+
+error[E0639]: cannot create non-exhaustive struct using struct expression
+ --> $DIR/struct.rs:14:14
+ |
+LL | let ns = NormalStruct { first_field: 640, second_field: 480 };
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error[E0638]: `..` required with struct marked as non-exhaustive
+ --> $DIR/struct.rs:17:9
+ |
+LL | let NormalStruct { first_field, second_field } = ns;
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+ |
+help: add `..` at the end of the field list to ignore all other fields
+ |
+LL | let NormalStruct { first_field, second_field , .. } = ns;
+ | ~~~~~~
+
+error[E0423]: cannot initialize a tuple struct which contains private fields
+ --> $DIR/struct.rs:20:14
+ |
+LL | let ts = TupleStruct(640, 480);
+ | ^^^^^^^^^^^
+
+error[E0638]: `..` required with struct marked as non-exhaustive
+ --> $DIR/struct.rs:26:9
+ |
+LL | let TupleStruct { 0: first_field, 1: second_field } = ts;
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+ |
+help: add `..` at the end of the field list to ignore all other fields
+ |
+LL | let TupleStruct { 0: first_field, 1: second_field , .. } = ts;
+ | ~~~~~~
+
+error[E0638]: `..` required with struct marked as non-exhaustive
+ --> $DIR/struct.rs:35:9
+ |
+LL | let UnitStruct { } = us;
+ | ^^^^^^^^^^^^^^
+ |
+help: add `..` at the end of the field list to ignore all other fields
+ |
+LL | let UnitStruct { .. } = us;
+ | ~~~~
+
+error: aborting due to 9 previous errors
+
+Some errors have detailed explanations: E0423, E0603, E0638, E0639.
+For more information about an error, try `rustc --explain E0423`.
diff --git a/tests/ui/rfc-2008-non-exhaustive/structs_same_crate.rs b/tests/ui/rfc-2008-non-exhaustive/structs_same_crate.rs
new file mode 100644
index 000000000..5f76b0cb2
--- /dev/null
+++ b/tests/ui/rfc-2008-non-exhaustive/structs_same_crate.rs
@@ -0,0 +1,32 @@
+// run-pass
+
+#![allow(unused_variables)]
+
+#[non_exhaustive]
+pub struct NormalStruct {
+ pub first_field: u16,
+ pub second_field: u16,
+}
+
+#[non_exhaustive]
+pub struct UnitStruct;
+
+#[non_exhaustive]
+pub struct TupleStruct (pub u16, pub u16);
+
+fn main() {
+ let ns = NormalStruct { first_field: 640, second_field: 480 };
+
+ let NormalStruct { first_field, second_field } = ns;
+
+ let ts = TupleStruct { 0: 340, 1: 480 };
+ let ts_constructor = TupleStruct(340, 480);
+
+ let TupleStruct { 0: first, 1: second } = ts;
+ let TupleStruct(first, second) = ts_constructor;
+
+ let us = UnitStruct {};
+ let us_constructor = UnitStruct;
+
+ let UnitStruct { } = us;
+}
diff --git a/tests/ui/rfc-2008-non-exhaustive/uninhabited/auxiliary/uninhabited.rs b/tests/ui/rfc-2008-non-exhaustive/uninhabited/auxiliary/uninhabited.rs
new file mode 100644
index 000000000..a2735d4cb
--- /dev/null
+++ b/tests/ui/rfc-2008-non-exhaustive/uninhabited/auxiliary/uninhabited.rs
@@ -0,0 +1,32 @@
+#![crate_type = "rlib"]
+#![feature(never_type)]
+
+#[non_exhaustive]
+pub enum UninhabitedEnum {
+}
+
+#[non_exhaustive]
+pub struct UninhabitedStruct {
+ _priv: !,
+}
+
+#[non_exhaustive]
+pub struct UninhabitedTupleStruct(!);
+
+pub enum UninhabitedVariants {
+ #[non_exhaustive] Tuple(!),
+ #[non_exhaustive] Struct { x: ! }
+}
+
+pub enum PartiallyInhabitedVariants {
+ Tuple(u8),
+ #[non_exhaustive] Struct { x: ! }
+}
+
+pub struct IndirectUninhabitedEnum(UninhabitedEnum);
+
+pub struct IndirectUninhabitedStruct(UninhabitedStruct);
+
+pub struct IndirectUninhabitedTupleStruct(UninhabitedTupleStruct);
+
+pub struct IndirectUninhabitedVariants(UninhabitedVariants);
diff --git a/tests/ui/rfc-2008-non-exhaustive/uninhabited/coercions.rs b/tests/ui/rfc-2008-non-exhaustive/uninhabited/coercions.rs
new file mode 100644
index 000000000..80b9dc4c1
--- /dev/null
+++ b/tests/ui/rfc-2008-non-exhaustive/uninhabited/coercions.rs
@@ -0,0 +1,38 @@
+// aux-build:uninhabited.rs
+#![feature(never_type)]
+
+extern crate uninhabited;
+
+use uninhabited::{
+ UninhabitedEnum,
+ UninhabitedStruct,
+ UninhabitedTupleStruct,
+ UninhabitedVariants,
+};
+
+// This test checks that uninhabited non-exhaustive types cannot coerce to any type, as the never
+// type can.
+
+struct A;
+
+fn can_coerce_never_type_to_anything(x: !) -> A {
+ x
+}
+
+fn cannot_coerce_empty_enum_to_anything(x: UninhabitedEnum) -> A {
+ x //~ ERROR mismatched types
+}
+
+fn cannot_coerce_empty_tuple_struct_to_anything(x: UninhabitedTupleStruct) -> A {
+ x //~ ERROR mismatched types
+}
+
+fn cannot_coerce_empty_struct_to_anything(x: UninhabitedStruct) -> A {
+ x //~ ERROR mismatched types
+}
+
+fn cannot_coerce_enum_with_empty_variants_to_anything(x: UninhabitedVariants) -> A {
+ x //~ ERROR mismatched types
+}
+
+fn main() {}
diff --git a/tests/ui/rfc-2008-non-exhaustive/uninhabited/coercions.stderr b/tests/ui/rfc-2008-non-exhaustive/uninhabited/coercions.stderr
new file mode 100644
index 000000000..f8ed156b5
--- /dev/null
+++ b/tests/ui/rfc-2008-non-exhaustive/uninhabited/coercions.stderr
@@ -0,0 +1,35 @@
+error[E0308]: mismatched types
+ --> $DIR/coercions.rs:23:5
+ |
+LL | fn cannot_coerce_empty_enum_to_anything(x: UninhabitedEnum) -> A {
+ | - expected `A` because of return type
+LL | x
+ | ^ expected struct `A`, found enum `UninhabitedEnum`
+
+error[E0308]: mismatched types
+ --> $DIR/coercions.rs:27:5
+ |
+LL | fn cannot_coerce_empty_tuple_struct_to_anything(x: UninhabitedTupleStruct) -> A {
+ | - expected `A` because of return type
+LL | x
+ | ^ expected struct `A`, found struct `UninhabitedTupleStruct`
+
+error[E0308]: mismatched types
+ --> $DIR/coercions.rs:31:5
+ |
+LL | fn cannot_coerce_empty_struct_to_anything(x: UninhabitedStruct) -> A {
+ | - expected `A` because of return type
+LL | x
+ | ^ expected struct `A`, found struct `UninhabitedStruct`
+
+error[E0308]: mismatched types
+ --> $DIR/coercions.rs:35:5
+ |
+LL | fn cannot_coerce_enum_with_empty_variants_to_anything(x: UninhabitedVariants) -> A {
+ | - expected `A` because of return type
+LL | x
+ | ^ expected struct `A`, found enum `UninhabitedVariants`
+
+error: aborting due to 4 previous errors
+
+For more information about this error, try `rustc --explain E0308`.
diff --git a/tests/ui/rfc-2008-non-exhaustive/uninhabited/coercions_same_crate.rs b/tests/ui/rfc-2008-non-exhaustive/uninhabited/coercions_same_crate.rs
new file mode 100644
index 000000000..6b911dd98
--- /dev/null
+++ b/tests/ui/rfc-2008-non-exhaustive/uninhabited/coercions_same_crate.rs
@@ -0,0 +1,45 @@
+#![feature(never_type)]
+
+#[non_exhaustive]
+pub enum UninhabitedEnum {
+}
+
+#[non_exhaustive]
+pub struct UninhabitedTupleStruct(!);
+
+#[non_exhaustive]
+pub struct UninhabitedStruct {
+ _priv: !,
+}
+
+pub enum UninhabitedVariants {
+ #[non_exhaustive] Tuple(!),
+ #[non_exhaustive] Struct { x: ! }
+}
+
+struct A;
+
+// This test checks that uninhabited non-exhaustive types defined in the same crate cannot coerce
+// to any type, as the never type can.
+
+fn can_coerce_never_type_to_anything(x: !) -> A {
+ x
+}
+
+fn cannot_coerce_empty_enum_to_anything(x: UninhabitedEnum) -> A {
+ x //~ ERROR mismatched types
+}
+
+fn cannot_coerce_empty_tuple_struct_to_anything(x: UninhabitedTupleStruct) -> A {
+ x //~ ERROR mismatched types
+}
+
+fn cannot_coerce_empty_struct_to_anything(x: UninhabitedStruct) -> A {
+ x //~ ERROR mismatched types
+}
+
+fn cannot_coerce_enum_with_empty_variants_to_anything(x: UninhabitedVariants) -> A {
+ x //~ ERROR mismatched types
+}
+
+fn main() {}
diff --git a/tests/ui/rfc-2008-non-exhaustive/uninhabited/coercions_same_crate.stderr b/tests/ui/rfc-2008-non-exhaustive/uninhabited/coercions_same_crate.stderr
new file mode 100644
index 000000000..fd2c56974
--- /dev/null
+++ b/tests/ui/rfc-2008-non-exhaustive/uninhabited/coercions_same_crate.stderr
@@ -0,0 +1,35 @@
+error[E0308]: mismatched types
+ --> $DIR/coercions_same_crate.rs:30:5
+ |
+LL | fn cannot_coerce_empty_enum_to_anything(x: UninhabitedEnum) -> A {
+ | - expected `A` because of return type
+LL | x
+ | ^ expected struct `A`, found enum `UninhabitedEnum`
+
+error[E0308]: mismatched types
+ --> $DIR/coercions_same_crate.rs:34:5
+ |
+LL | fn cannot_coerce_empty_tuple_struct_to_anything(x: UninhabitedTupleStruct) -> A {
+ | - expected `A` because of return type
+LL | x
+ | ^ expected struct `A`, found struct `UninhabitedTupleStruct`
+
+error[E0308]: mismatched types
+ --> $DIR/coercions_same_crate.rs:38:5
+ |
+LL | fn cannot_coerce_empty_struct_to_anything(x: UninhabitedStruct) -> A {
+ | - expected `A` because of return type
+LL | x
+ | ^ expected struct `A`, found struct `UninhabitedStruct`
+
+error[E0308]: mismatched types
+ --> $DIR/coercions_same_crate.rs:42:5
+ |
+LL | fn cannot_coerce_enum_with_empty_variants_to_anything(x: UninhabitedVariants) -> A {
+ | - expected `A` because of return type
+LL | x
+ | ^ expected struct `A`, found enum `UninhabitedVariants`
+
+error: aborting due to 4 previous errors
+
+For more information about this error, try `rustc --explain E0308`.
diff --git a/tests/ui/rfc-2008-non-exhaustive/uninhabited/indirect_match.rs b/tests/ui/rfc-2008-non-exhaustive/uninhabited/indirect_match.rs
new file mode 100644
index 000000000..98a7fdbc5
--- /dev/null
+++ b/tests/ui/rfc-2008-non-exhaustive/uninhabited/indirect_match.rs
@@ -0,0 +1,36 @@
+// aux-build:uninhabited.rs
+#![feature(never_type)]
+
+extern crate uninhabited;
+
+use uninhabited::{
+ IndirectUninhabitedEnum,
+ IndirectUninhabitedStruct,
+ IndirectUninhabitedTupleStruct,
+ IndirectUninhabitedVariants,
+};
+
+struct A;
+
+// This test checks that an empty match on a non-exhaustive uninhabited type through a level of
+// indirection from an extern crate will not compile.
+
+fn cannot_empty_match_on_empty_enum_to_anything(x: IndirectUninhabitedEnum) -> A {
+ match x {} //~ ERROR non-exhaustive patterns
+}
+
+fn cannot_empty_match_on_empty_struct_to_anything(x: IndirectUninhabitedStruct) -> A {
+ match x {} //~ ERROR non-exhaustive patterns
+}
+
+fn cannot_empty_match_on_empty_tuple_struct_to_anything(x: IndirectUninhabitedTupleStruct) -> A {
+ match x {} //~ ERROR non-exhaustive patterns
+}
+
+fn cannot_empty_match_on_enum_with_empty_variants_struct_to_anything(
+ x: IndirectUninhabitedVariants,
+) -> A {
+ match x {} //~ ERROR non-exhaustive patterns
+}
+
+fn main() {}
diff --git a/tests/ui/rfc-2008-non-exhaustive/uninhabited/indirect_match.stderr b/tests/ui/rfc-2008-non-exhaustive/uninhabited/indirect_match.stderr
new file mode 100644
index 000000000..66e93291c
--- /dev/null
+++ b/tests/ui/rfc-2008-non-exhaustive/uninhabited/indirect_match.stderr
@@ -0,0 +1,79 @@
+error[E0004]: non-exhaustive patterns: type `IndirectUninhabitedEnum` is non-empty
+ --> $DIR/indirect_match.rs:19:11
+ |
+LL | match x {}
+ | ^
+ |
+note: `IndirectUninhabitedEnum` defined here
+ --> $DIR/auxiliary/uninhabited.rs:26:1
+ |
+LL | pub struct IndirectUninhabitedEnum(UninhabitedEnum);
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+ = note: the matched value is of type `IndirectUninhabitedEnum`
+help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern as shown
+ |
+LL ~ match x {
+LL + _ => todo!(),
+LL ~ }
+ |
+
+error[E0004]: non-exhaustive patterns: type `IndirectUninhabitedStruct` is non-empty
+ --> $DIR/indirect_match.rs:23:11
+ |
+LL | match x {}
+ | ^
+ |
+note: `IndirectUninhabitedStruct` defined here
+ --> $DIR/auxiliary/uninhabited.rs:28:1
+ |
+LL | pub struct IndirectUninhabitedStruct(UninhabitedStruct);
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+ = note: the matched value is of type `IndirectUninhabitedStruct`
+help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern as shown
+ |
+LL ~ match x {
+LL + _ => todo!(),
+LL ~ }
+ |
+
+error[E0004]: non-exhaustive patterns: type `IndirectUninhabitedTupleStruct` is non-empty
+ --> $DIR/indirect_match.rs:27:11
+ |
+LL | match x {}
+ | ^
+ |
+note: `IndirectUninhabitedTupleStruct` defined here
+ --> $DIR/auxiliary/uninhabited.rs:30:1
+ |
+LL | pub struct IndirectUninhabitedTupleStruct(UninhabitedTupleStruct);
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+ = note: the matched value is of type `IndirectUninhabitedTupleStruct`
+help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern as shown
+ |
+LL ~ match x {
+LL + _ => todo!(),
+LL ~ }
+ |
+
+error[E0004]: non-exhaustive patterns: type `IndirectUninhabitedVariants` is non-empty
+ --> $DIR/indirect_match.rs:33:11
+ |
+LL | match x {}
+ | ^
+ |
+note: `IndirectUninhabitedVariants` defined here
+ --> $DIR/auxiliary/uninhabited.rs:32:1
+ |
+LL | pub struct IndirectUninhabitedVariants(UninhabitedVariants);
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+ = note: the matched value is of type `IndirectUninhabitedVariants`
+help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern as shown
+ |
+LL ~ match x {
+LL + _ => todo!(),
+LL ~ }
+ |
+
+error: aborting due to 4 previous errors
+
+For more information about this error, try `rustc --explain E0004`.
diff --git a/tests/ui/rfc-2008-non-exhaustive/uninhabited/indirect_match_same_crate.rs b/tests/ui/rfc-2008-non-exhaustive/uninhabited/indirect_match_same_crate.rs
new file mode 100644
index 000000000..8f090fe88
--- /dev/null
+++ b/tests/ui/rfc-2008-non-exhaustive/uninhabited/indirect_match_same_crate.rs
@@ -0,0 +1,51 @@
+#![feature(never_type)]
+
+#[non_exhaustive]
+pub enum UninhabitedEnum {
+}
+
+#[non_exhaustive]
+pub struct UninhabitedStruct {
+ _priv: !,
+}
+
+#[non_exhaustive]
+pub struct UninhabitedTupleStruct(!);
+
+pub enum UninhabitedVariants {
+ #[non_exhaustive] Tuple(!),
+ #[non_exhaustive] Struct { x: ! }
+}
+
+pub struct IndirectUninhabitedEnum(UninhabitedEnum);
+
+pub struct IndirectUninhabitedStruct(UninhabitedStruct);
+
+pub struct IndirectUninhabitedTupleStruct(UninhabitedTupleStruct);
+
+pub struct IndirectUninhabitedVariants(UninhabitedVariants);
+
+struct A;
+
+// This test checks that an empty match on a non-exhaustive uninhabited type through a level of
+// indirection from the defining crate will not compile without `#![feature(exhaustive_patterns)]`.
+
+fn cannot_empty_match_on_empty_enum_to_anything(x: IndirectUninhabitedEnum) -> A {
+ match x {} //~ ERROR non-exhaustive patterns
+}
+
+fn cannot_empty_match_on_empty_struct_to_anything(x: IndirectUninhabitedStruct) -> A {
+ match x {} //~ ERROR non-exhaustive patterns
+}
+
+fn cannot_empty_match_on_empty_tuple_struct_to_anything(x: IndirectUninhabitedTupleStruct) -> A {
+ match x {} //~ ERROR non-exhaustive patterns
+}
+
+fn cannot_empty_match_on_enum_with_empty_variants_struct_to_anything(
+ x: IndirectUninhabitedVariants,
+) -> A {
+ match x {} //~ ERROR non-exhaustive patterns
+}
+
+fn main() {}
diff --git a/tests/ui/rfc-2008-non-exhaustive/uninhabited/indirect_match_same_crate.stderr b/tests/ui/rfc-2008-non-exhaustive/uninhabited/indirect_match_same_crate.stderr
new file mode 100644
index 000000000..c12190541
--- /dev/null
+++ b/tests/ui/rfc-2008-non-exhaustive/uninhabited/indirect_match_same_crate.stderr
@@ -0,0 +1,79 @@
+error[E0004]: non-exhaustive patterns: type `IndirectUninhabitedEnum` is non-empty
+ --> $DIR/indirect_match_same_crate.rs:34:11
+ |
+LL | match x {}
+ | ^
+ |
+note: `IndirectUninhabitedEnum` defined here
+ --> $DIR/indirect_match_same_crate.rs:20:12
+ |
+LL | pub struct IndirectUninhabitedEnum(UninhabitedEnum);
+ | ^^^^^^^^^^^^^^^^^^^^^^^
+ = note: the matched value is of type `IndirectUninhabitedEnum`
+help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern as shown
+ |
+LL ~ match x {
+LL + _ => todo!(),
+LL ~ }
+ |
+
+error[E0004]: non-exhaustive patterns: type `IndirectUninhabitedStruct` is non-empty
+ --> $DIR/indirect_match_same_crate.rs:38:11
+ |
+LL | match x {}
+ | ^
+ |
+note: `IndirectUninhabitedStruct` defined here
+ --> $DIR/indirect_match_same_crate.rs:22:12
+ |
+LL | pub struct IndirectUninhabitedStruct(UninhabitedStruct);
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^
+ = note: the matched value is of type `IndirectUninhabitedStruct`
+help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern as shown
+ |
+LL ~ match x {
+LL + _ => todo!(),
+LL ~ }
+ |
+
+error[E0004]: non-exhaustive patterns: type `IndirectUninhabitedTupleStruct` is non-empty
+ --> $DIR/indirect_match_same_crate.rs:42:11
+ |
+LL | match x {}
+ | ^
+ |
+note: `IndirectUninhabitedTupleStruct` defined here
+ --> $DIR/indirect_match_same_crate.rs:24:12
+ |
+LL | pub struct IndirectUninhabitedTupleStruct(UninhabitedTupleStruct);
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+ = note: the matched value is of type `IndirectUninhabitedTupleStruct`
+help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern as shown
+ |
+LL ~ match x {
+LL + _ => todo!(),
+LL ~ }
+ |
+
+error[E0004]: non-exhaustive patterns: type `IndirectUninhabitedVariants` is non-empty
+ --> $DIR/indirect_match_same_crate.rs:48:11
+ |
+LL | match x {}
+ | ^
+ |
+note: `IndirectUninhabitedVariants` defined here
+ --> $DIR/indirect_match_same_crate.rs:26:12
+ |
+LL | pub struct IndirectUninhabitedVariants(UninhabitedVariants);
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^
+ = note: the matched value is of type `IndirectUninhabitedVariants`
+help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern as shown
+ |
+LL ~ match x {
+LL + _ => todo!(),
+LL ~ }
+ |
+
+error: aborting due to 4 previous errors
+
+For more information about this error, try `rustc --explain E0004`.
diff --git a/tests/ui/rfc-2008-non-exhaustive/uninhabited/indirect_match_with_exhaustive_patterns.rs b/tests/ui/rfc-2008-non-exhaustive/uninhabited/indirect_match_with_exhaustive_patterns.rs
new file mode 100644
index 000000000..be86519ec
--- /dev/null
+++ b/tests/ui/rfc-2008-non-exhaustive/uninhabited/indirect_match_with_exhaustive_patterns.rs
@@ -0,0 +1,40 @@
+// aux-build:uninhabited.rs
+#![deny(unreachable_patterns)]
+#![feature(exhaustive_patterns)]
+#![feature(never_type)]
+
+extern crate uninhabited;
+
+use uninhabited::{
+ IndirectUninhabitedEnum,
+ IndirectUninhabitedStruct,
+ IndirectUninhabitedTupleStruct,
+ IndirectUninhabitedVariants,
+};
+
+struct A;
+
+// This test checks that an empty match on a non-exhaustive uninhabited type through a level of
+// indirection from an extern crate will not compile. In particular, this enables the
+// `exhaustive_patterns` feature as this can change the branch used in the compiler to determine
+// this.
+
+fn cannot_empty_match_on_empty_enum_to_anything(x: IndirectUninhabitedEnum) -> A {
+ match x {} //~ ERROR non-exhaustive patterns
+}
+
+fn cannot_empty_match_on_empty_struct_to_anything(x: IndirectUninhabitedStruct) -> A {
+ match x {} //~ ERROR non-exhaustive patterns
+}
+
+fn cannot_empty_match_on_empty_tuple_struct_to_anything(x: IndirectUninhabitedTupleStruct) -> A {
+ match x {} //~ ERROR non-exhaustive patterns
+}
+
+fn cannot_empty_match_on_enum_with_empty_variants_struct_to_anything(
+ x: IndirectUninhabitedVariants,
+) -> A {
+ match x {} //~ ERROR non-exhaustive patterns
+}
+
+fn main() {}
diff --git a/tests/ui/rfc-2008-non-exhaustive/uninhabited/indirect_match_with_exhaustive_patterns.stderr b/tests/ui/rfc-2008-non-exhaustive/uninhabited/indirect_match_with_exhaustive_patterns.stderr
new file mode 100644
index 000000000..ef97c1fa1
--- /dev/null
+++ b/tests/ui/rfc-2008-non-exhaustive/uninhabited/indirect_match_with_exhaustive_patterns.stderr
@@ -0,0 +1,79 @@
+error[E0004]: non-exhaustive patterns: type `IndirectUninhabitedEnum` is non-empty
+ --> $DIR/indirect_match_with_exhaustive_patterns.rs:23:11
+ |
+LL | match x {}
+ | ^
+ |
+note: `IndirectUninhabitedEnum` defined here
+ --> $DIR/auxiliary/uninhabited.rs:26:1
+ |
+LL | pub struct IndirectUninhabitedEnum(UninhabitedEnum);
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+ = note: the matched value is of type `IndirectUninhabitedEnum`
+help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern as shown
+ |
+LL ~ match x {
+LL + _ => todo!(),
+LL ~ }
+ |
+
+error[E0004]: non-exhaustive patterns: type `IndirectUninhabitedStruct` is non-empty
+ --> $DIR/indirect_match_with_exhaustive_patterns.rs:27:11
+ |
+LL | match x {}
+ | ^
+ |
+note: `IndirectUninhabitedStruct` defined here
+ --> $DIR/auxiliary/uninhabited.rs:28:1
+ |
+LL | pub struct IndirectUninhabitedStruct(UninhabitedStruct);
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+ = note: the matched value is of type `IndirectUninhabitedStruct`
+help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern as shown
+ |
+LL ~ match x {
+LL + _ => todo!(),
+LL ~ }
+ |
+
+error[E0004]: non-exhaustive patterns: type `IndirectUninhabitedTupleStruct` is non-empty
+ --> $DIR/indirect_match_with_exhaustive_patterns.rs:31:11
+ |
+LL | match x {}
+ | ^
+ |
+note: `IndirectUninhabitedTupleStruct` defined here
+ --> $DIR/auxiliary/uninhabited.rs:30:1
+ |
+LL | pub struct IndirectUninhabitedTupleStruct(UninhabitedTupleStruct);
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+ = note: the matched value is of type `IndirectUninhabitedTupleStruct`
+help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern as shown
+ |
+LL ~ match x {
+LL + _ => todo!(),
+LL ~ }
+ |
+
+error[E0004]: non-exhaustive patterns: type `IndirectUninhabitedVariants` is non-empty
+ --> $DIR/indirect_match_with_exhaustive_patterns.rs:37:11
+ |
+LL | match x {}
+ | ^
+ |
+note: `IndirectUninhabitedVariants` defined here
+ --> $DIR/auxiliary/uninhabited.rs:32:1
+ |
+LL | pub struct IndirectUninhabitedVariants(UninhabitedVariants);
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+ = note: the matched value is of type `IndirectUninhabitedVariants`
+help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern as shown
+ |
+LL ~ match x {
+LL + _ => todo!(),
+LL ~ }
+ |
+
+error: aborting due to 4 previous errors
+
+For more information about this error, try `rustc --explain E0004`.
diff --git a/tests/ui/rfc-2008-non-exhaustive/uninhabited/indirect_match_with_exhaustive_patterns_same_crate.rs b/tests/ui/rfc-2008-non-exhaustive/uninhabited/indirect_match_with_exhaustive_patterns_same_crate.rs
new file mode 100644
index 000000000..60289aa78
--- /dev/null
+++ b/tests/ui/rfc-2008-non-exhaustive/uninhabited/indirect_match_with_exhaustive_patterns_same_crate.rs
@@ -0,0 +1,57 @@
+// check-pass
+
+#![deny(unreachable_patterns)]
+#![feature(exhaustive_patterns)]
+#![feature(never_type)]
+
+#[non_exhaustive]
+pub enum UninhabitedEnum {
+}
+
+#[non_exhaustive]
+pub struct UninhabitedStruct {
+ _priv: !,
+}
+
+#[non_exhaustive]
+pub struct UninhabitedTupleStruct(!);
+
+pub enum UninhabitedVariants {
+ #[non_exhaustive] Tuple(!),
+ #[non_exhaustive] Struct { x: ! }
+}
+
+pub struct IndirectUninhabitedEnum(UninhabitedEnum);
+
+pub struct IndirectUninhabitedStruct(UninhabitedStruct);
+
+pub struct IndirectUninhabitedTupleStruct(UninhabitedTupleStruct);
+
+pub struct IndirectUninhabitedVariants(UninhabitedVariants);
+
+struct A;
+
+// This test checks that an empty match on a non-exhaustive uninhabited type from the defining crate
+// will compile. In particular, this enables the `exhaustive_patterns` feature as this can
+// change the branch used in the compiler to determine this.
+// Codegen is skipped because tests with long names can cause issues on Windows CI, see #60648.
+
+fn cannot_empty_match_on_empty_enum_to_anything(x: IndirectUninhabitedEnum) -> A {
+ match x {}
+}
+
+fn cannot_empty_match_on_empty_struct_to_anything(x: IndirectUninhabitedStruct) -> A {
+ match x {}
+}
+
+fn cannot_empty_match_on_empty_tuple_struct_to_anything(x: IndirectUninhabitedTupleStruct) -> A {
+ match x {}
+}
+
+fn cannot_empty_match_on_enum_with_empty_variants_struct_to_anything(
+ x: IndirectUninhabitedVariants,
+) -> A {
+ match x {}
+}
+
+fn main() {}
diff --git a/tests/ui/rfc-2008-non-exhaustive/uninhabited/issue-65157-repeated-match-arm.rs b/tests/ui/rfc-2008-non-exhaustive/uninhabited/issue-65157-repeated-match-arm.rs
new file mode 100644
index 000000000..230ac7529
--- /dev/null
+++ b/tests/ui/rfc-2008-non-exhaustive/uninhabited/issue-65157-repeated-match-arm.rs
@@ -0,0 +1,21 @@
+// aux-build:uninhabited.rs
+#![deny(unreachable_patterns)]
+#![feature(never_type)]
+
+extern crate uninhabited;
+
+use uninhabited::PartiallyInhabitedVariants;
+
+// This test checks a redundant/useless pattern of a non-exhaustive enum/variant is still
+// warned against.
+
+pub fn foo(x: PartiallyInhabitedVariants) {
+ match x {
+ PartiallyInhabitedVariants::Struct { .. } => {},
+ PartiallyInhabitedVariants::Struct { .. } => {},
+ //~^ ERROR unreachable pattern
+ _ => {},
+ }
+}
+
+fn main() { }
diff --git a/tests/ui/rfc-2008-non-exhaustive/uninhabited/issue-65157-repeated-match-arm.stderr b/tests/ui/rfc-2008-non-exhaustive/uninhabited/issue-65157-repeated-match-arm.stderr
new file mode 100644
index 000000000..f39e6ee29
--- /dev/null
+++ b/tests/ui/rfc-2008-non-exhaustive/uninhabited/issue-65157-repeated-match-arm.stderr
@@ -0,0 +1,14 @@
+error: unreachable pattern
+ --> $DIR/issue-65157-repeated-match-arm.rs:15:9
+ |
+LL | PartiallyInhabitedVariants::Struct { .. } => {},
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+ |
+note: the lint level is defined here
+ --> $DIR/issue-65157-repeated-match-arm.rs:2:9
+ |
+LL | #![deny(unreachable_patterns)]
+ | ^^^^^^^^^^^^^^^^^^^^
+
+error: aborting due to previous error
+
diff --git a/tests/ui/rfc-2008-non-exhaustive/uninhabited/match.rs b/tests/ui/rfc-2008-non-exhaustive/uninhabited/match.rs
new file mode 100644
index 000000000..e54098d4d
--- /dev/null
+++ b/tests/ui/rfc-2008-non-exhaustive/uninhabited/match.rs
@@ -0,0 +1,34 @@
+// aux-build:uninhabited.rs
+#![feature(never_type)]
+
+extern crate uninhabited;
+
+use uninhabited::{
+ UninhabitedEnum,
+ UninhabitedStruct,
+ UninhabitedTupleStruct,
+ UninhabitedVariants,
+};
+
+struct A;
+
+// This test checks that an empty match on a non-exhaustive uninhabited type from an extern crate
+// will not compile.
+
+fn cannot_empty_match_on_empty_enum_to_anything(x: UninhabitedEnum) -> A {
+ match x {} //~ ERROR non-exhaustive patterns
+}
+
+fn cannot_empty_match_on_empty_struct_to_anything(x: UninhabitedStruct) -> A {
+ match x {} //~ ERROR non-exhaustive patterns
+}
+
+fn cannot_empty_match_on_empty_tuple_struct_to_anything(x: UninhabitedTupleStruct) -> A {
+ match x {} //~ ERROR non-exhaustive patterns
+}
+
+fn cannot_empty_match_on_enum_with_empty_variants_struct_to_anything(x: UninhabitedVariants) -> A {
+ match x {} //~ ERROR non-exhaustive patterns
+}
+
+fn main() {}
diff --git a/tests/ui/rfc-2008-non-exhaustive/uninhabited/match.stderr b/tests/ui/rfc-2008-non-exhaustive/uninhabited/match.stderr
new file mode 100644
index 000000000..a9c54af04
--- /dev/null
+++ b/tests/ui/rfc-2008-non-exhaustive/uninhabited/match.stderr
@@ -0,0 +1,83 @@
+error[E0004]: non-exhaustive patterns: type `UninhabitedEnum` is non-empty
+ --> $DIR/match.rs:19:11
+ |
+LL | match x {}
+ | ^
+ |
+note: `UninhabitedEnum` defined here
+ --> $DIR/auxiliary/uninhabited.rs:5:1
+ |
+LL | pub enum UninhabitedEnum {
+ | ^^^^^^^^^^^^^^^^^^^^^^^^
+ = note: the matched value is of type `UninhabitedEnum`, which is marked as non-exhaustive
+help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern as shown
+ |
+LL ~ match x {
+LL + _ => todo!(),
+LL ~ }
+ |
+
+error[E0004]: non-exhaustive patterns: type `UninhabitedStruct` is non-empty
+ --> $DIR/match.rs:23:11
+ |
+LL | match x {}
+ | ^
+ |
+note: `UninhabitedStruct` defined here
+ --> $DIR/auxiliary/uninhabited.rs:9:1
+ |
+LL | pub struct UninhabitedStruct {
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+ = note: the matched value is of type `UninhabitedStruct`
+help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern as shown
+ |
+LL ~ match x {
+LL + _ => todo!(),
+LL ~ }
+ |
+
+error[E0004]: non-exhaustive patterns: type `UninhabitedTupleStruct` is non-empty
+ --> $DIR/match.rs:27:11
+ |
+LL | match x {}
+ | ^
+ |
+note: `UninhabitedTupleStruct` defined here
+ --> $DIR/auxiliary/uninhabited.rs:14:1
+ |
+LL | pub struct UninhabitedTupleStruct(!);
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+ = note: the matched value is of type `UninhabitedTupleStruct`
+help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern as shown
+ |
+LL ~ match x {
+LL + _ => todo!(),
+LL ~ }
+ |
+
+error[E0004]: non-exhaustive patterns: `UninhabitedVariants::Tuple(_)` and `UninhabitedVariants::Struct { .. }` not covered
+ --> $DIR/match.rs:31:11
+ |
+LL | match x {}
+ | ^ patterns `UninhabitedVariants::Tuple(_)` and `UninhabitedVariants::Struct { .. }` not covered
+ |
+note: `UninhabitedVariants` defined here
+ --> $DIR/auxiliary/uninhabited.rs:17:23
+ |
+LL | pub enum UninhabitedVariants {
+ | ----------------------------
+LL | #[non_exhaustive] Tuple(!),
+ | ^^^^^ not covered
+LL | #[non_exhaustive] Struct { x: ! }
+ | ^^^^^^ not covered
+ = note: the matched value is of type `UninhabitedVariants`
+help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern, a match arm with multiple or-patterns as shown, or multiple match arms
+ |
+LL ~ match x {
+LL + UninhabitedVariants::Tuple(_) | UninhabitedVariants::Struct { .. } => todo!(),
+LL ~ }
+ |
+
+error: aborting due to 4 previous errors
+
+For more information about this error, try `rustc --explain E0004`.
diff --git a/tests/ui/rfc-2008-non-exhaustive/uninhabited/match_same_crate.rs b/tests/ui/rfc-2008-non-exhaustive/uninhabited/match_same_crate.rs
new file mode 100644
index 000000000..ebbdfba15
--- /dev/null
+++ b/tests/ui/rfc-2008-non-exhaustive/uninhabited/match_same_crate.rs
@@ -0,0 +1,41 @@
+#![feature(never_type)]
+
+#[non_exhaustive]
+pub enum UninhabitedEnum {
+}
+
+#[non_exhaustive]
+pub struct UninhabitedStruct {
+ _priv: !,
+}
+
+#[non_exhaustive]
+pub struct UninhabitedTupleStruct(!);
+
+pub enum UninhabitedVariants {
+ #[non_exhaustive] Tuple(!),
+ #[non_exhaustive] Struct { x: ! }
+}
+
+struct A;
+
+// This test checks that an empty match on a non-exhaustive uninhabited type from the defining crate
+// will compile.
+
+fn cannot_empty_match_on_empty_enum_to_anything(x: UninhabitedEnum) -> A {
+ match x {}
+}
+
+fn cannot_empty_match_on_empty_struct_to_anything(x: UninhabitedStruct) -> A {
+ match x {} //~ ERROR non-exhaustive patterns
+}
+
+fn cannot_empty_match_on_empty_tuple_struct_to_anything(x: UninhabitedTupleStruct) -> A {
+ match x {} //~ ERROR non-exhaustive patterns
+}
+
+fn cannot_empty_match_on_enum_with_empty_variants_struct_to_anything(x: UninhabitedVariants) -> A {
+ match x {} //~ ERROR non-exhaustive patterns
+}
+
+fn main() {}
diff --git a/tests/ui/rfc-2008-non-exhaustive/uninhabited/match_same_crate.stderr b/tests/ui/rfc-2008-non-exhaustive/uninhabited/match_same_crate.stderr
new file mode 100644
index 000000000..ec2a2f6f0
--- /dev/null
+++ b/tests/ui/rfc-2008-non-exhaustive/uninhabited/match_same_crate.stderr
@@ -0,0 +1,64 @@
+error[E0004]: non-exhaustive patterns: type `UninhabitedStruct` is non-empty
+ --> $DIR/match_same_crate.rs:30:11
+ |
+LL | match x {}
+ | ^
+ |
+note: `UninhabitedStruct` defined here
+ --> $DIR/match_same_crate.rs:8:12
+ |
+LL | pub struct UninhabitedStruct {
+ | ^^^^^^^^^^^^^^^^^
+ = note: the matched value is of type `UninhabitedStruct`
+help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern as shown
+ |
+LL ~ match x {
+LL + _ => todo!(),
+LL ~ }
+ |
+
+error[E0004]: non-exhaustive patterns: type `UninhabitedTupleStruct` is non-empty
+ --> $DIR/match_same_crate.rs:34:11
+ |
+LL | match x {}
+ | ^
+ |
+note: `UninhabitedTupleStruct` defined here
+ --> $DIR/match_same_crate.rs:13:12
+ |
+LL | pub struct UninhabitedTupleStruct(!);
+ | ^^^^^^^^^^^^^^^^^^^^^^
+ = note: the matched value is of type `UninhabitedTupleStruct`
+help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern as shown
+ |
+LL ~ match x {
+LL + _ => todo!(),
+LL ~ }
+ |
+
+error[E0004]: non-exhaustive patterns: `UninhabitedVariants::Tuple(_)` and `UninhabitedVariants::Struct { .. }` not covered
+ --> $DIR/match_same_crate.rs:38:11
+ |
+LL | match x {}
+ | ^ patterns `UninhabitedVariants::Tuple(_)` and `UninhabitedVariants::Struct { .. }` not covered
+ |
+note: `UninhabitedVariants` defined here
+ --> $DIR/match_same_crate.rs:16:23
+ |
+LL | pub enum UninhabitedVariants {
+ | -------------------
+LL | #[non_exhaustive] Tuple(!),
+ | ^^^^^ not covered
+LL | #[non_exhaustive] Struct { x: ! }
+ | ^^^^^^ not covered
+ = note: the matched value is of type `UninhabitedVariants`
+help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern, a match arm with multiple or-patterns as shown, or multiple match arms
+ |
+LL ~ match x {
+LL + UninhabitedVariants::Tuple(_) | UninhabitedVariants::Struct { .. } => todo!(),
+LL ~ }
+ |
+
+error: aborting due to 3 previous errors
+
+For more information about this error, try `rustc --explain E0004`.
diff --git a/tests/ui/rfc-2008-non-exhaustive/uninhabited/match_with_exhaustive_patterns.rs b/tests/ui/rfc-2008-non-exhaustive/uninhabited/match_with_exhaustive_patterns.rs
new file mode 100644
index 000000000..900dfff65
--- /dev/null
+++ b/tests/ui/rfc-2008-non-exhaustive/uninhabited/match_with_exhaustive_patterns.rs
@@ -0,0 +1,37 @@
+// aux-build:uninhabited.rs
+#![deny(unreachable_patterns)]
+#![feature(exhaustive_patterns)]
+#![feature(never_type)]
+
+extern crate uninhabited;
+
+use uninhabited::{
+ UninhabitedEnum,
+ UninhabitedStruct,
+ UninhabitedTupleStruct,
+ UninhabitedVariants,
+};
+
+struct A;
+
+// This test checks that an empty match on a non-exhaustive uninhabited type from an extern crate
+// will not compile. In particular, this enables the `exhaustive_patterns` feature as this can
+// change the branch used in the compiler to determine this.
+
+fn cannot_empty_match_on_empty_enum_to_anything(x: UninhabitedEnum) -> A {
+ match x {} //~ ERROR non-exhaustive patterns
+}
+
+fn cannot_empty_match_on_empty_struct_to_anything(x: UninhabitedStruct) -> A {
+ match x {} //~ ERROR non-exhaustive patterns
+}
+
+fn cannot_empty_match_on_empty_tuple_struct_to_anything(x: UninhabitedTupleStruct) -> A {
+ match x {} //~ ERROR non-exhaustive patterns
+}
+
+fn cannot_empty_match_on_enum_with_empty_variants_struct_to_anything(x: UninhabitedVariants) -> A {
+ match x {} //~ ERROR non-exhaustive patterns
+}
+
+fn main() {}
diff --git a/tests/ui/rfc-2008-non-exhaustive/uninhabited/match_with_exhaustive_patterns.stderr b/tests/ui/rfc-2008-non-exhaustive/uninhabited/match_with_exhaustive_patterns.stderr
new file mode 100644
index 000000000..b6b777ec5
--- /dev/null
+++ b/tests/ui/rfc-2008-non-exhaustive/uninhabited/match_with_exhaustive_patterns.stderr
@@ -0,0 +1,83 @@
+error[E0004]: non-exhaustive patterns: type `UninhabitedEnum` is non-empty
+ --> $DIR/match_with_exhaustive_patterns.rs:22:11
+ |
+LL | match x {}
+ | ^
+ |
+note: `UninhabitedEnum` defined here
+ --> $DIR/auxiliary/uninhabited.rs:5:1
+ |
+LL | pub enum UninhabitedEnum {
+ | ^^^^^^^^^^^^^^^^^^^^^^^^
+ = note: the matched value is of type `UninhabitedEnum`, which is marked as non-exhaustive
+help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern as shown
+ |
+LL ~ match x {
+LL + _ => todo!(),
+LL ~ }
+ |
+
+error[E0004]: non-exhaustive patterns: type `UninhabitedStruct` is non-empty
+ --> $DIR/match_with_exhaustive_patterns.rs:26:11
+ |
+LL | match x {}
+ | ^
+ |
+note: `UninhabitedStruct` defined here
+ --> $DIR/auxiliary/uninhabited.rs:9:1
+ |
+LL | pub struct UninhabitedStruct {
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+ = note: the matched value is of type `UninhabitedStruct`
+help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern as shown
+ |
+LL ~ match x {
+LL + _ => todo!(),
+LL ~ }
+ |
+
+error[E0004]: non-exhaustive patterns: type `UninhabitedTupleStruct` is non-empty
+ --> $DIR/match_with_exhaustive_patterns.rs:30:11
+ |
+LL | match x {}
+ | ^
+ |
+note: `UninhabitedTupleStruct` defined here
+ --> $DIR/auxiliary/uninhabited.rs:14:1
+ |
+LL | pub struct UninhabitedTupleStruct(!);
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+ = note: the matched value is of type `UninhabitedTupleStruct`
+help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern as shown
+ |
+LL ~ match x {
+LL + _ => todo!(),
+LL ~ }
+ |
+
+error[E0004]: non-exhaustive patterns: `UninhabitedVariants::Tuple(_)` and `UninhabitedVariants::Struct { .. }` not covered
+ --> $DIR/match_with_exhaustive_patterns.rs:34:11
+ |
+LL | match x {}
+ | ^ patterns `UninhabitedVariants::Tuple(_)` and `UninhabitedVariants::Struct { .. }` not covered
+ |
+note: `UninhabitedVariants` defined here
+ --> $DIR/auxiliary/uninhabited.rs:17:23
+ |
+LL | pub enum UninhabitedVariants {
+ | ----------------------------
+LL | #[non_exhaustive] Tuple(!),
+ | ^^^^^ not covered
+LL | #[non_exhaustive] Struct { x: ! }
+ | ^^^^^^ not covered
+ = note: the matched value is of type `UninhabitedVariants`
+help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern, a match arm with multiple or-patterns as shown, or multiple match arms
+ |
+LL ~ match x {
+LL + UninhabitedVariants::Tuple(_) | UninhabitedVariants::Struct { .. } => todo!(),
+LL ~ }
+ |
+
+error: aborting due to 4 previous errors
+
+For more information about this error, try `rustc --explain E0004`.
diff --git a/tests/ui/rfc-2008-non-exhaustive/uninhabited/match_with_exhaustive_patterns_same_crate.rs b/tests/ui/rfc-2008-non-exhaustive/uninhabited/match_with_exhaustive_patterns_same_crate.rs
new file mode 100644
index 000000000..de5530485
--- /dev/null
+++ b/tests/ui/rfc-2008-non-exhaustive/uninhabited/match_with_exhaustive_patterns_same_crate.rs
@@ -0,0 +1,47 @@
+// check-pass
+
+#![deny(unreachable_patterns)]
+#![feature(exhaustive_patterns)]
+#![feature(never_type)]
+
+#[non_exhaustive]
+pub enum UninhabitedEnum {
+}
+
+#[non_exhaustive]
+pub struct UninhabitedStruct {
+ _priv: !,
+}
+
+#[non_exhaustive]
+pub struct UninhabitedTupleStruct(!);
+
+pub enum UninhabitedVariants {
+ #[non_exhaustive] Tuple(!),
+ #[non_exhaustive] Struct { x: ! }
+}
+
+struct A;
+
+// This test checks that an empty match on a non-exhaustive uninhabited type from the defining crate
+// will compile. In particular, this enables the `exhaustive_patterns` feature as this can
+// change the branch used in the compiler to determine this.
+// Codegen is skipped because tests with long names can cause issues on Windows CI, see #60648.
+
+fn cannot_empty_match_on_empty_enum_to_anything(x: UninhabitedEnum) -> A {
+ match x {}
+}
+
+fn cannot_empty_match_on_empty_struct_to_anything(x: UninhabitedStruct) -> A {
+ match x {}
+}
+
+fn cannot_empty_match_on_empty_tuple_struct_to_anything(x: UninhabitedTupleStruct) -> A {
+ match x {}
+}
+
+fn cannot_empty_match_on_enum_with_empty_variants_struct_to_anything(x: UninhabitedVariants) -> A {
+ match x {}
+}
+
+fn main() {}
diff --git a/tests/ui/rfc-2008-non-exhaustive/uninhabited/patterns.rs b/tests/ui/rfc-2008-non-exhaustive/uninhabited/patterns.rs
new file mode 100644
index 000000000..221b5cf6b
--- /dev/null
+++ b/tests/ui/rfc-2008-non-exhaustive/uninhabited/patterns.rs
@@ -0,0 +1,59 @@
+// aux-build:uninhabited.rs
+// build-pass (FIXME(62277): could be check-pass?)
+#![deny(unreachable_patterns)]
+#![feature(exhaustive_patterns)]
+
+extern crate uninhabited;
+
+use uninhabited::{
+ PartiallyInhabitedVariants,
+ UninhabitedEnum,
+ UninhabitedStruct,
+ UninhabitedTupleStruct,
+ UninhabitedVariants,
+};
+
+fn uninhabited_enum() -> Option<UninhabitedEnum> {
+ None
+}
+
+fn uninhabited_variant() -> Option<UninhabitedVariants> {
+ None
+}
+
+fn partially_inhabited_variant() -> PartiallyInhabitedVariants {
+ PartiallyInhabitedVariants::Tuple(3)
+}
+
+fn uninhabited_struct() -> Option<UninhabitedStruct> {
+ None
+}
+
+fn uninhabited_tuple_struct() -> Option<UninhabitedTupleStruct> {
+ None
+}
+
+// This test checks that non-exhaustive types that would normally be considered uninhabited within
+// the defining crate are not considered uninhabited from extern crates.
+
+fn main() {
+ match uninhabited_enum() {
+ Some(_x) => (), // This line would normally error.
+ None => (),
+ }
+
+ match uninhabited_variant() {
+ Some(_x) => (), // This line would normally error.
+ None => (),
+ }
+
+ // This line would normally error.
+ while let PartiallyInhabitedVariants::Struct { x, .. } = partially_inhabited_variant() {
+ }
+
+ while let Some(_x) = uninhabited_struct() { // This line would normally error.
+ }
+
+ while let Some(_x) = uninhabited_tuple_struct() { // This line would normally error.
+ }
+}
diff --git a/tests/ui/rfc-2008-non-exhaustive/uninhabited/patterns_same_crate.rs b/tests/ui/rfc-2008-non-exhaustive/uninhabited/patterns_same_crate.rs
new file mode 100644
index 000000000..ffc496a97
--- /dev/null
+++ b/tests/ui/rfc-2008-non-exhaustive/uninhabited/patterns_same_crate.rs
@@ -0,0 +1,70 @@
+#![deny(unreachable_patterns)]
+#![feature(exhaustive_patterns)]
+#![feature(never_type)]
+
+#[non_exhaustive]
+pub enum UninhabitedEnum {
+}
+
+#[non_exhaustive]
+pub struct UninhabitedTupleStruct(!);
+
+#[non_exhaustive]
+pub struct UninhabitedStruct {
+ _priv: !,
+}
+
+pub enum UninhabitedVariants {
+ #[non_exhaustive] Tuple(!),
+ #[non_exhaustive] Struct { x: ! }
+}
+
+pub enum PartiallyInhabitedVariants {
+ Tuple(u8),
+ #[non_exhaustive] Struct { x: ! }
+}
+
+fn uninhabited_enum() -> Option<UninhabitedEnum> {
+ None
+}
+
+fn uninhabited_variant() -> Option<UninhabitedVariants> {
+ None
+}
+
+fn partially_inhabited_variant() -> PartiallyInhabitedVariants {
+ PartiallyInhabitedVariants::Tuple(3)
+}
+
+fn uninhabited_struct() -> Option<UninhabitedStruct> {
+ None
+}
+
+fn uninhabited_tuple_struct() -> Option<UninhabitedTupleStruct> {
+ None
+}
+
+// This test checks that non-exhaustive types that would normally be considered uninhabited within
+// the defining crate are still considered uninhabited.
+
+fn main() {
+ match uninhabited_enum() {
+ Some(_x) => (), //~ ERROR unreachable pattern
+ None => (),
+ }
+
+ match uninhabited_variant() {
+ Some(_x) => (), //~ ERROR unreachable pattern
+ None => (),
+ }
+
+ while let PartiallyInhabitedVariants::Struct { x } = partially_inhabited_variant() {
+ //~^ ERROR unreachable pattern
+ }
+
+ while let Some(_x) = uninhabited_struct() { //~ ERROR unreachable pattern
+ }
+
+ while let Some(_x) = uninhabited_tuple_struct() { //~ ERROR unreachable pattern
+ }
+}
diff --git a/tests/ui/rfc-2008-non-exhaustive/uninhabited/patterns_same_crate.stderr b/tests/ui/rfc-2008-non-exhaustive/uninhabited/patterns_same_crate.stderr
new file mode 100644
index 000000000..8bfd6e91f
--- /dev/null
+++ b/tests/ui/rfc-2008-non-exhaustive/uninhabited/patterns_same_crate.stderr
@@ -0,0 +1,38 @@
+error: unreachable pattern
+ --> $DIR/patterns_same_crate.rs:52:9
+ |
+LL | Some(_x) => (),
+ | ^^^^^^^^
+ |
+note: the lint level is defined here
+ --> $DIR/patterns_same_crate.rs:1:9
+ |
+LL | #![deny(unreachable_patterns)]
+ | ^^^^^^^^^^^^^^^^^^^^
+
+error: unreachable pattern
+ --> $DIR/patterns_same_crate.rs:57:9
+ |
+LL | Some(_x) => (),
+ | ^^^^^^^^
+
+error: unreachable pattern
+ --> $DIR/patterns_same_crate.rs:61:15
+ |
+LL | while let PartiallyInhabitedVariants::Struct { x } = partially_inhabited_variant() {
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: unreachable pattern
+ --> $DIR/patterns_same_crate.rs:65:15
+ |
+LL | while let Some(_x) = uninhabited_struct() {
+ | ^^^^^^^^
+
+error: unreachable pattern
+ --> $DIR/patterns_same_crate.rs:68:15
+ |
+LL | while let Some(_x) = uninhabited_tuple_struct() {
+ | ^^^^^^^^
+
+error: aborting due to 5 previous errors
+
diff --git a/tests/ui/rfc-2008-non-exhaustive/variant.rs b/tests/ui/rfc-2008-non-exhaustive/variant.rs
new file mode 100644
index 000000000..bc346aea5
--- /dev/null
+++ b/tests/ui/rfc-2008-non-exhaustive/variant.rs
@@ -0,0 +1,33 @@
+// aux-build:variants.rs
+
+extern crate variants;
+
+use variants::NonExhaustiveVariants;
+
+fn main() {
+ let variant_struct = NonExhaustiveVariants::Struct { field: 640 };
+ //~^ ERROR cannot create non-exhaustive variant
+
+ let variant_tuple = NonExhaustiveVariants::Tuple(640);
+ //~^ ERROR tuple variant `Tuple` is private [E0603]
+
+ let variant_unit = NonExhaustiveVariants::Unit;
+ //~^ ERROR unit variant `Unit` is private [E0603]
+
+ match variant_struct {
+ NonExhaustiveVariants::Unit => "",
+ //~^ ERROR unit variant `Unit` is private [E0603]
+ NonExhaustiveVariants::Tuple(fe_tpl) => "",
+ //~^ ERROR tuple variant `Tuple` is private [E0603]
+ NonExhaustiveVariants::Struct { field } => ""
+ //~^ ERROR `..` required with variant marked as non-exhaustive
+ };
+
+ if let NonExhaustiveVariants::Tuple(fe_tpl) = variant_struct {
+ //~^ ERROR tuple variant `Tuple` is private [E0603]
+ }
+
+ if let NonExhaustiveVariants::Struct { field } = variant_struct {
+ //~^ ERROR `..` required with variant marked as non-exhaustive
+ }
+}
diff --git a/tests/ui/rfc-2008-non-exhaustive/variant.stderr b/tests/ui/rfc-2008-non-exhaustive/variant.stderr
new file mode 100644
index 000000000..720b7b119
--- /dev/null
+++ b/tests/ui/rfc-2008-non-exhaustive/variant.stderr
@@ -0,0 +1,92 @@
+error[E0603]: tuple variant `Tuple` is private
+ --> $DIR/variant.rs:11:48
+ |
+LL | let variant_tuple = NonExhaustiveVariants::Tuple(640);
+ | ^^^^^ private tuple variant
+ |
+note: the tuple variant `Tuple` is defined here
+ --> $DIR/auxiliary/variants.rs:5:23
+ |
+LL | #[non_exhaustive] Tuple(u32),
+ | ^^^^^
+
+error[E0603]: unit variant `Unit` is private
+ --> $DIR/variant.rs:14:47
+ |
+LL | let variant_unit = NonExhaustiveVariants::Unit;
+ | ^^^^ private unit variant
+ |
+note: the unit variant `Unit` is defined here
+ --> $DIR/auxiliary/variants.rs:4:23
+ |
+LL | #[non_exhaustive] Unit,
+ | ^^^^
+
+error[E0603]: unit variant `Unit` is private
+ --> $DIR/variant.rs:18:32
+ |
+LL | NonExhaustiveVariants::Unit => "",
+ | ^^^^ private unit variant
+ |
+note: the unit variant `Unit` is defined here
+ --> $DIR/auxiliary/variants.rs:4:23
+ |
+LL | #[non_exhaustive] Unit,
+ | ^^^^
+
+error[E0603]: tuple variant `Tuple` is private
+ --> $DIR/variant.rs:20:32
+ |
+LL | NonExhaustiveVariants::Tuple(fe_tpl) => "",
+ | ^^^^^ private tuple variant
+ |
+note: the tuple variant `Tuple` is defined here
+ --> $DIR/auxiliary/variants.rs:5:23
+ |
+LL | #[non_exhaustive] Tuple(u32),
+ | ^^^^^
+
+error[E0603]: tuple variant `Tuple` is private
+ --> $DIR/variant.rs:26:35
+ |
+LL | if let NonExhaustiveVariants::Tuple(fe_tpl) = variant_struct {
+ | ^^^^^ private tuple variant
+ |
+note: the tuple variant `Tuple` is defined here
+ --> $DIR/auxiliary/variants.rs:5:23
+ |
+LL | #[non_exhaustive] Tuple(u32),
+ | ^^^^^
+
+error[E0639]: cannot create non-exhaustive variant using struct expression
+ --> $DIR/variant.rs:8:26
+ |
+LL | let variant_struct = NonExhaustiveVariants::Struct { field: 640 };
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error[E0638]: `..` required with variant marked as non-exhaustive
+ --> $DIR/variant.rs:22:9
+ |
+LL | NonExhaustiveVariants::Struct { field } => ""
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+ |
+help: add `..` at the end of the field list to ignore all other fields
+ |
+LL | NonExhaustiveVariants::Struct { field , .. } => ""
+ | ~~~~~~
+
+error[E0638]: `..` required with variant marked as non-exhaustive
+ --> $DIR/variant.rs:30:12
+ |
+LL | if let NonExhaustiveVariants::Struct { field } = variant_struct {
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+ |
+help: add `..` at the end of the field list to ignore all other fields
+ |
+LL | if let NonExhaustiveVariants::Struct { field , .. } = variant_struct {
+ | ~~~~~~
+
+error: aborting due to 8 previous errors
+
+Some errors have detailed explanations: E0603, E0638, E0639.
+For more information about an error, try `rustc --explain E0603`.
diff --git a/tests/ui/rfc-2008-non-exhaustive/variants_fictive_visibility.rs b/tests/ui/rfc-2008-non-exhaustive/variants_fictive_visibility.rs
new file mode 100644
index 000000000..dacaf489a
--- /dev/null
+++ b/tests/ui/rfc-2008-non-exhaustive/variants_fictive_visibility.rs
@@ -0,0 +1,12 @@
+// build-pass (FIXME(62277): could be check-pass?)
+// aux-build:variants.rs
+
+extern crate variants;
+
+const S: u8 = 0;
+
+// OK, `Struct` in value namespace is crate-private, so it's filtered away
+// and there's no conflict with the previously defined `const S`.
+use variants::NonExhaustiveVariants::Struct as S;
+
+fn main() {}
diff --git a/tests/ui/rfc-2008-non-exhaustive/variants_same_crate.rs b/tests/ui/rfc-2008-non-exhaustive/variants_same_crate.rs
new file mode 100644
index 000000000..5f2816ec6
--- /dev/null
+++ b/tests/ui/rfc-2008-non-exhaustive/variants_same_crate.rs
@@ -0,0 +1,18 @@
+// run-pass
+
+pub enum NonExhaustiveVariants {
+ #[non_exhaustive] Unit,
+ #[non_exhaustive] Tuple(u32),
+ #[non_exhaustive] Struct { field: u32 }
+}
+
+fn main() {
+ let variant_tuple = NonExhaustiveVariants::Tuple(340);
+ let _variant_struct = NonExhaustiveVariants::Struct { field: 340 };
+
+ match variant_tuple {
+ NonExhaustiveVariants::Unit => "",
+ NonExhaustiveVariants::Tuple(_fe_tpl) => "",
+ NonExhaustiveVariants::Struct { field: _ } => ""
+ };
+}