summaryrefslogtreecommitdiffstats
path: root/tests/ui/pattern/usefulness
diff options
context:
space:
mode:
Diffstat (limited to 'tests/ui/pattern/usefulness')
-rw-r--r--tests/ui/pattern/usefulness/always-inhabited-union-ref.rs32
-rw-r--r--tests/ui/pattern/usefulness/always-inhabited-union-ref.stderr37
-rw-r--r--tests/ui/pattern/usefulness/auxiliary/empty.rs10
-rw-r--r--tests/ui/pattern/usefulness/auxiliary/hidden.rs14
-rw-r--r--tests/ui/pattern/usefulness/auxiliary/unstable.rs23
-rw-r--r--tests/ui/pattern/usefulness/const-partial_eq-fallback-ice.rs18
-rw-r--r--tests/ui/pattern/usefulness/const-partial_eq-fallback-ice.stderr8
-rw-r--r--tests/ui/pattern/usefulness/const-pat-ice.rs11
-rw-r--r--tests/ui/pattern/usefulness/const-private-fields.rs30
-rw-r--r--tests/ui/pattern/usefulness/consts-opaque.rs145
-rw-r--r--tests/ui/pattern/usefulness/consts-opaque.stderr202
-rw-r--r--tests/ui/pattern/usefulness/deny-irrefutable-let-patterns.rs16
-rw-r--r--tests/ui/pattern/usefulness/deny-irrefutable-let-patterns.stderr34
-rw-r--r--tests/ui/pattern/usefulness/doc-hidden-fields.rs26
-rw-r--r--tests/ui/pattern/usefulness/doc-hidden-fields.stderr59
-rw-r--r--tests/ui/pattern/usefulness/doc-hidden-non-exhaustive.rs43
-rw-r--r--tests/ui/pattern/usefulness/doc-hidden-non-exhaustive.stderr102
-rw-r--r--tests/ui/pattern/usefulness/empty-match.exhaustive_patterns.stderr303
-rw-r--r--tests/ui/pattern/usefulness/empty-match.normal.stderr303
-rw-r--r--tests/ui/pattern/usefulness/empty-match.rs95
-rw-r--r--tests/ui/pattern/usefulness/floats.rs19
-rw-r--r--tests/ui/pattern/usefulness/floats.stderr28
-rw-r--r--tests/ui/pattern/usefulness/guards.rs22
-rw-r--r--tests/ui/pattern/usefulness/guards.stderr16
-rw-r--r--tests/ui/pattern/usefulness/integer-ranges/exhaustiveness.rs101
-rw-r--r--tests/ui/pattern/usefulness/integer-ranges/exhaustiveness.stderr149
-rw-r--r--tests/ui/pattern/usefulness/integer-ranges/overlapping_range_endpoints.rs59
-rw-r--r--tests/ui/pattern/usefulness/integer-ranges/overlapping_range_endpoints.stderr89
-rw-r--r--tests/ui/pattern/usefulness/integer-ranges/pointer-sized-int.allow.stderr17
-rw-r--r--tests/ui/pattern/usefulness/integer-ranges/pointer-sized-int.deny.stderr170
-rw-r--r--tests/ui/pattern/usefulness/integer-ranges/pointer-sized-int.rs50
-rw-r--r--tests/ui/pattern/usefulness/integer-ranges/precise_pointer_matching-message.rs18
-rw-r--r--tests/ui/pattern/usefulness/integer-ranges/precise_pointer_matching-message.stderr33
-rw-r--r--tests/ui/pattern/usefulness/integer-ranges/reachability.rs113
-rw-r--r--tests/ui/pattern/usefulness/integer-ranges/reachability.stderr154
-rw-r--r--tests/ui/pattern/usefulness/irrefutable-let-patterns.rs11
-rw-r--r--tests/ui/pattern/usefulness/irrefutable-unit.rs6
-rw-r--r--tests/ui/pattern/usefulness/issue-12116.rs21
-rw-r--r--tests/ui/pattern/usefulness/issue-12116.stderr14
-rw-r--r--tests/ui/pattern/usefulness/issue-12369.rs11
-rw-r--r--tests/ui/pattern/usefulness/issue-12369.stderr14
-rw-r--r--tests/ui/pattern/usefulness/issue-13727.rs15
-rw-r--r--tests/ui/pattern/usefulness/issue-13727.stderr14
-rw-r--r--tests/ui/pattern/usefulness/issue-15129.rs17
-rw-r--r--tests/ui/pattern/usefulness/issue-15129.stderr16
-rw-r--r--tests/ui/pattern/usefulness/issue-2111.rs11
-rw-r--r--tests/ui/pattern/usefulness/issue-2111.stderr16
-rw-r--r--tests/ui/pattern/usefulness/issue-30240-b.rs15
-rw-r--r--tests/ui/pattern/usefulness/issue-30240-b.stderr14
-rw-r--r--tests/ui/pattern/usefulness/issue-30240-rpass.rs14
-rw-r--r--tests/ui/pattern/usefulness/issue-30240.rs10
-rw-r--r--tests/ui/pattern/usefulness/issue-30240.stderr29
-rw-r--r--tests/ui/pattern/usefulness/issue-3096-1.rs3
-rw-r--r--tests/ui/pattern/usefulness/issue-3096-1.stderr17
-rw-r--r--tests/ui/pattern/usefulness/issue-3096-2.rs6
-rw-r--r--tests/ui/pattern/usefulness/issue-3096-2.stderr17
-rw-r--r--tests/ui/pattern/usefulness/issue-31221.rs34
-rw-r--r--tests/ui/pattern/usefulness/issue-31221.stderr32
-rw-r--r--tests/ui/pattern/usefulness/issue-31561.rs11
-rw-r--r--tests/ui/pattern/usefulness/issue-31561.stderr27
-rw-r--r--tests/ui/pattern/usefulness/issue-35609.rs43
-rw-r--r--tests/ui/pattern/usefulness/issue-35609.stderr119
-rw-r--r--tests/ui/pattern/usefulness/issue-3601.rs34
-rw-r--r--tests/ui/pattern/usefulness/issue-3601.stderr18
-rw-r--r--tests/ui/pattern/usefulness/issue-39362.rs18
-rw-r--r--tests/ui/pattern/usefulness/issue-39362.stderr23
-rw-r--r--tests/ui/pattern/usefulness/issue-40221.rs16
-rw-r--r--tests/ui/pattern/usefulness/issue-40221.stderr23
-rw-r--r--tests/ui/pattern/usefulness/issue-4321.rs8
-rw-r--r--tests/ui/pattern/usefulness/issue-4321.stderr16
-rw-r--r--tests/ui/pattern/usefulness/issue-50900.rs19
-rw-r--r--tests/ui/pattern/usefulness/issue-50900.stderr21
-rw-r--r--tests/ui/pattern/usefulness/issue-53820-slice-pattern-large-array.rs11
-rw-r--r--tests/ui/pattern/usefulness/issue-56379.rs14
-rw-r--r--tests/ui/pattern/usefulness/issue-56379.stderr27
-rw-r--r--tests/ui/pattern/usefulness/issue-57472.rs35
-rw-r--r--tests/ui/pattern/usefulness/issue-57472.stderr20
-rw-r--r--tests/ui/pattern/usefulness/issue-65413-constants-and-slices-exhaustiveness.rs15
-rw-r--r--tests/ui/pattern/usefulness/issue-66501.rs12
-rw-r--r--tests/ui/pattern/usefulness/issue-71930-type-of-match-scrutinee.rs22
-rw-r--r--tests/ui/pattern/usefulness/issue-72377.rs17
-rw-r--r--tests/ui/pattern/usefulness/issue-72377.stderr16
-rw-r--r--tests/ui/pattern/usefulness/issue-72476-and-89393-associated-type.rs56
-rw-r--r--tests/ui/pattern/usefulness/issue-78123-non-exhaustive-reference.rs12
-rw-r--r--tests/ui/pattern/usefulness/issue-78123-non-exhaustive-reference.stderr23
-rw-r--r--tests/ui/pattern/usefulness/issue-78549-ref-pat-and-str.rs25
-rw-r--r--tests/ui/pattern/usefulness/issue-80501-or-pat-and-macro.rs27
-rw-r--r--tests/ui/pattern/usefulness/issue-82772-match-box-as-struct.rs6
-rw-r--r--tests/ui/pattern/usefulness/issue-82772-match-box-as-struct.stderr9
-rw-r--r--tests/ui/pattern/usefulness/issue-88747.rs14
-rw-r--r--tests/ui/pattern/usefulness/match-arm-statics-2.rs62
-rw-r--r--tests/ui/pattern/usefulness/match-arm-statics-2.stderr54
-rw-r--r--tests/ui/pattern/usefulness/match-arm-statics.rs69
-rw-r--r--tests/ui/pattern/usefulness/match-arm-statics.stderr26
-rw-r--r--tests/ui/pattern/usefulness/match-byte-array-patterns-2.rs13
-rw-r--r--tests/ui/pattern/usefulness/match-byte-array-patterns-2.stderr29
-rw-r--r--tests/ui/pattern/usefulness/match-byte-array-patterns.rs55
-rw-r--r--tests/ui/pattern/usefulness/match-byte-array-patterns.stderr56
-rw-r--r--tests/ui/pattern/usefulness/match-non-exhaustive.rs4
-rw-r--r--tests/ui/pattern/usefulness/match-non-exhaustive.stderr27
-rw-r--r--tests/ui/pattern/usefulness/match-privately-empty.rs21
-rw-r--r--tests/ui/pattern/usefulness/match-privately-empty.stderr21
-rw-r--r--tests/ui/pattern/usefulness/match-ref-ice.rs16
-rw-r--r--tests/ui/pattern/usefulness/match-ref-ice.stderr14
-rw-r--r--tests/ui/pattern/usefulness/match-slice-patterns.rs12
-rw-r--r--tests/ui/pattern/usefulness/match-slice-patterns.stderr16
-rw-r--r--tests/ui/pattern/usefulness/match-vec-fixed.rs18
-rw-r--r--tests/ui/pattern/usefulness/match-vec-fixed.stderr20
-rw-r--r--tests/ui/pattern/usefulness/match-vec-unreachable.rs29
-rw-r--r--tests/ui/pattern/usefulness/match-vec-unreachable.stderr26
-rw-r--r--tests/ui/pattern/usefulness/nested-exhaustive-match.rs14
-rw-r--r--tests/ui/pattern/usefulness/non-exhaustive-defined-here.rs107
-rw-r--r--tests/ui/pattern/usefulness/non-exhaustive-defined-here.stderr194
-rw-r--r--tests/ui/pattern/usefulness/non-exhaustive-match-nested.rs19
-rw-r--r--tests/ui/pattern/usefulness/non-exhaustive-match-nested.stderr34
-rw-r--r--tests/ui/pattern/usefulness/non-exhaustive-match.rs63
-rw-r--r--tests/ui/pattern/usefulness/non-exhaustive-match.stderr121
-rw-r--r--tests/ui/pattern/usefulness/non-exhaustive-pattern-witness.rs89
-rw-r--r--tests/ui/pattern/usefulness/non-exhaustive-pattern-witness.stderr129
-rw-r--r--tests/ui/pattern/usefulness/refutable-pattern-errors.rs9
-rw-r--r--tests/ui/pattern/usefulness/refutable-pattern-errors.stderr25
-rw-r--r--tests/ui/pattern/usefulness/refutable-pattern-in-fn-arg.rs6
-rw-r--r--tests/ui/pattern/usefulness/refutable-pattern-in-fn-arg.stderr11
-rw-r--r--tests/ui/pattern/usefulness/slice-pattern-const-2.rs31
-rw-r--r--tests/ui/pattern/usefulness/slice-pattern-const-2.stderr32
-rw-r--r--tests/ui/pattern/usefulness/slice-pattern-const-3.rs31
-rw-r--r--tests/ui/pattern/usefulness/slice-pattern-const-3.stderr32
-rw-r--r--tests/ui/pattern/usefulness/slice-pattern-const.rs54
-rw-r--r--tests/ui/pattern/usefulness/slice-pattern-const.stderr62
-rw-r--r--tests/ui/pattern/usefulness/slice-patterns-exhaustiveness.rs129
-rw-r--r--tests/ui/pattern/usefulness/slice-patterns-exhaustiveness.stderr263
-rw-r--r--tests/ui/pattern/usefulness/slice-patterns-irrefutable.rs26
-rw-r--r--tests/ui/pattern/usefulness/slice-patterns-reachability.rs25
-rw-r--r--tests/ui/pattern/usefulness/slice-patterns-reachability.stderr44
-rw-r--r--tests/ui/pattern/usefulness/stable-gated-fields.rs16
-rw-r--r--tests/ui/pattern/usefulness/stable-gated-fields.stderr29
-rw-r--r--tests/ui/pattern/usefulness/stable-gated-patterns.rs18
-rw-r--r--tests/ui/pattern/usefulness/stable-gated-patterns.stderr42
-rw-r--r--tests/ui/pattern/usefulness/struct-like-enum-nonexhaustive.rs12
-rw-r--r--tests/ui/pattern/usefulness/struct-like-enum-nonexhaustive.stderr23
-rw-r--r--tests/ui/pattern/usefulness/struct-pattern-match-useless.rs15
-rw-r--r--tests/ui/pattern/usefulness/struct-pattern-match-useless.stderr16
-rw-r--r--tests/ui/pattern/usefulness/top-level-alternation.rs57
-rw-r--r--tests/ui/pattern/usefulness/top-level-alternation.stderr74
-rw-r--r--tests/ui/pattern/usefulness/tuple-struct-nonexhaustive.rs9
-rw-r--r--tests/ui/pattern/usefulness/tuple-struct-nonexhaustive.stderr21
-rw-r--r--tests/ui/pattern/usefulness/type_polymorphic_byte_str_literals.rs36
-rw-r--r--tests/ui/pattern/usefulness/type_polymorphic_byte_str_literals.stderr29
-rw-r--r--tests/ui/pattern/usefulness/uninhabited.rs143
-rw-r--r--tests/ui/pattern/usefulness/unstable-gated-fields.rs18
-rw-r--r--tests/ui/pattern/usefulness/unstable-gated-fields.stderr33
-rw-r--r--tests/ui/pattern/usefulness/unstable-gated-patterns.rs22
-rw-r--r--tests/ui/pattern/usefulness/unstable-gated-patterns.stderr24
153 files changed, 6438 insertions, 0 deletions
diff --git a/tests/ui/pattern/usefulness/always-inhabited-union-ref.rs b/tests/ui/pattern/usefulness/always-inhabited-union-ref.rs
new file mode 100644
index 000000000..7d1cac8a4
--- /dev/null
+++ b/tests/ui/pattern/usefulness/always-inhabited-union-ref.rs
@@ -0,0 +1,32 @@
+// The precise semantics of inhabitedness with respect to unions and references is currently
+// undecided. This test file currently checks a conservative choice.
+
+#![feature(exhaustive_patterns)]
+#![feature(never_type)]
+
+#![allow(dead_code)]
+#![allow(unreachable_code)]
+
+pub union Foo {
+ foo: !,
+}
+
+fn uninhab_ref() -> &'static ! {
+ unimplemented!()
+}
+
+fn uninhab_union() -> Foo {
+ unimplemented!()
+}
+
+fn match_on_uninhab() {
+ match uninhab_ref() {
+ //~^ ERROR non-exhaustive patterns: type `&!` is non-empty
+ }
+
+ match uninhab_union() {
+ //~^ ERROR non-exhaustive patterns: type `Foo` is non-empty
+ }
+}
+
+fn main() {}
diff --git a/tests/ui/pattern/usefulness/always-inhabited-union-ref.stderr b/tests/ui/pattern/usefulness/always-inhabited-union-ref.stderr
new file mode 100644
index 000000000..cd5c283f9
--- /dev/null
+++ b/tests/ui/pattern/usefulness/always-inhabited-union-ref.stderr
@@ -0,0 +1,37 @@
+error[E0004]: non-exhaustive patterns: type `&!` is non-empty
+ --> $DIR/always-inhabited-union-ref.rs:23:11
+ |
+LL | match uninhab_ref() {
+ | ^^^^^^^^^^^^^
+ |
+ = note: the matched value is of type `&!`
+ = note: references are always considered inhabited
+help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern as shown
+ |
+LL ~ match uninhab_ref() {
+LL + _ => todo!(),
+LL + }
+ |
+
+error[E0004]: non-exhaustive patterns: type `Foo` is non-empty
+ --> $DIR/always-inhabited-union-ref.rs:27:11
+ |
+LL | match uninhab_union() {
+ | ^^^^^^^^^^^^^^^
+ |
+note: `Foo` defined here
+ --> $DIR/always-inhabited-union-ref.rs:10:11
+ |
+LL | pub union Foo {
+ | ^^^
+ = note: the matched value is of type `Foo`
+help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern as shown
+ |
+LL ~ match uninhab_union() {
+LL + _ => todo!(),
+LL + }
+ |
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0004`.
diff --git a/tests/ui/pattern/usefulness/auxiliary/empty.rs b/tests/ui/pattern/usefulness/auxiliary/empty.rs
new file mode 100644
index 000000000..29a03c9e8
--- /dev/null
+++ b/tests/ui/pattern/usefulness/auxiliary/empty.rs
@@ -0,0 +1,10 @@
+#![crate_type = "rlib"]
+pub enum EmptyForeignEnum {}
+
+pub struct VisiblyUninhabitedForeignStruct {
+ pub field: EmptyForeignEnum,
+}
+
+pub struct SecretlyUninhabitedForeignStruct {
+ _priv: EmptyForeignEnum,
+}
diff --git a/tests/ui/pattern/usefulness/auxiliary/hidden.rs b/tests/ui/pattern/usefulness/auxiliary/hidden.rs
new file mode 100644
index 000000000..364514ba1
--- /dev/null
+++ b/tests/ui/pattern/usefulness/auxiliary/hidden.rs
@@ -0,0 +1,14 @@
+pub enum HiddenEnum {
+ A,
+ B,
+ #[doc(hidden)]
+ C,
+}
+
+#[derive(Default)]
+pub struct HiddenStruct {
+ pub one: u8,
+ pub two: bool,
+ #[doc(hidden)]
+ pub hide: usize,
+}
diff --git a/tests/ui/pattern/usefulness/auxiliary/unstable.rs b/tests/ui/pattern/usefulness/auxiliary/unstable.rs
new file mode 100644
index 000000000..a06b3a6e4
--- /dev/null
+++ b/tests/ui/pattern/usefulness/auxiliary/unstable.rs
@@ -0,0 +1,23 @@
+#![feature(staged_api)]
+#![stable(feature = "stable_test_feature", since = "1.0.0")]
+
+#[stable(feature = "stable_test_feature", since = "1.0.0")]
+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,
+}
+
+#[derive(Default)]
+#[stable(feature = "stable_test_feature", since = "1.0.0")]
+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,
+}
diff --git a/tests/ui/pattern/usefulness/const-partial_eq-fallback-ice.rs b/tests/ui/pattern/usefulness/const-partial_eq-fallback-ice.rs
new file mode 100644
index 000000000..02599d7c0
--- /dev/null
+++ b/tests/ui/pattern/usefulness/const-partial_eq-fallback-ice.rs
@@ -0,0 +1,18 @@
+#![allow(warnings)]
+
+struct MyType;
+
+impl PartialEq<usize> for MyType {
+ fn eq(&self, y: &usize) -> bool {
+ true
+ }
+}
+
+const CONSTANT: &&MyType = &&MyType;
+
+fn main() {
+ if let CONSTANT = &&MyType {
+ //~^ ERROR must be annotated with `#[derive(PartialEq, Eq)]`
+ println!("did match!");
+ }
+}
diff --git a/tests/ui/pattern/usefulness/const-partial_eq-fallback-ice.stderr b/tests/ui/pattern/usefulness/const-partial_eq-fallback-ice.stderr
new file mode 100644
index 000000000..358421cd6
--- /dev/null
+++ b/tests/ui/pattern/usefulness/const-partial_eq-fallback-ice.stderr
@@ -0,0 +1,8 @@
+error: to use a constant of type `MyType` in a pattern, `MyType` must be annotated with `#[derive(PartialEq, Eq)]`
+ --> $DIR/const-partial_eq-fallback-ice.rs:14:12
+ |
+LL | if let CONSTANT = &&MyType {
+ | ^^^^^^^^
+
+error: aborting due to previous error
+
diff --git a/tests/ui/pattern/usefulness/const-pat-ice.rs b/tests/ui/pattern/usefulness/const-pat-ice.rs
new file mode 100644
index 000000000..abfacf393
--- /dev/null
+++ b/tests/ui/pattern/usefulness/const-pat-ice.rs
@@ -0,0 +1,11 @@
+// check-pass
+
+const FOO: &&&u32 = &&&42;
+
+fn main() {
+ match unimplemented!() {
+ &&&42 => {},
+ FOO => {},
+ _ => {},
+ }
+}
diff --git a/tests/ui/pattern/usefulness/const-private-fields.rs b/tests/ui/pattern/usefulness/const-private-fields.rs
new file mode 100644
index 000000000..06c832ca4
--- /dev/null
+++ b/tests/ui/pattern/usefulness/const-private-fields.rs
@@ -0,0 +1,30 @@
+// check-pass
+//
+// Check that we don't ignore private fields in usefulness checking
+#![deny(unreachable_patterns)]
+
+mod inner {
+ #[derive(PartialEq, Eq)]
+ pub struct PrivateField {
+ pub x: bool,
+ y: bool,
+ }
+
+ pub const FOO: PrivateField = PrivateField { x: true, y: true };
+ pub const BAR: PrivateField = PrivateField { x: true, y: false };
+}
+use inner::*;
+
+fn main() {
+ match FOO {
+ FOO => {}
+ BAR => {}
+ _ => {}
+ }
+
+ match FOO {
+ FOO => {}
+ PrivateField { x: true, .. } => {}
+ _ => {}
+ }
+}
diff --git a/tests/ui/pattern/usefulness/consts-opaque.rs b/tests/ui/pattern/usefulness/consts-opaque.rs
new file mode 100644
index 000000000..ca4fcd85b
--- /dev/null
+++ b/tests/ui/pattern/usefulness/consts-opaque.rs
@@ -0,0 +1,145 @@
+// This file tests the exhaustiveness algorithm on opaque constants. Most of the examples give
+// unnecessary warnings because const_to_pat.rs converts a constant pattern to a wildcard when the
+// constant is not allowed as a pattern. This is an edge case so we may not care to fix it.
+// See also https://github.com/rust-lang/rust/issues/78057
+
+#![deny(unreachable_patterns)]
+
+#[derive(PartialEq)]
+struct Foo(i32);
+impl Eq for Foo {}
+const FOO: Foo = Foo(42);
+const FOO_REF: &Foo = &Foo(42);
+const FOO_REF_REF: &&Foo = &&Foo(42);
+
+#[derive(PartialEq)]
+struct Bar;
+impl Eq for Bar {}
+const BAR: Bar = Bar;
+
+#[derive(PartialEq)]
+enum Baz {
+ Baz1,
+ Baz2
+}
+impl Eq for Baz {}
+const BAZ: Baz = Baz::Baz1;
+
+fn main() {
+ match FOO {
+ FOO => {}
+ //~^ ERROR must be annotated with `#[derive(PartialEq, Eq)]`
+ _ => {} // should not be emitting unreachable warning
+ //~^ ERROR unreachable pattern
+ }
+
+ match FOO_REF {
+ FOO_REF => {}
+ //~^ ERROR must be annotated with `#[derive(PartialEq, Eq)]`
+ Foo(_) => {} // should not be emitting unreachable warning
+ //~^ ERROR unreachable pattern
+ }
+
+ // This used to cause an ICE (https://github.com/rust-lang/rust/issues/78071)
+ match FOO_REF_REF {
+ FOO_REF_REF => {}
+ //~^ WARNING must be annotated with `#[derive(PartialEq, Eq)]`
+ //~| WARNING this was previously accepted by the compiler but is being phased out
+ Foo(_) => {}
+ }
+
+ match BAR {
+ Bar => {}
+ BAR => {} // should not be emitting unreachable warning
+ //~^ ERROR must be annotated with `#[derive(PartialEq, Eq)]`
+ //~| ERROR unreachable pattern
+ _ => {}
+ //~^ ERROR unreachable pattern
+ }
+
+ match BAR {
+ BAR => {}
+ //~^ ERROR must be annotated with `#[derive(PartialEq, Eq)]`
+ Bar => {} // should not be emitting unreachable warning
+ //~^ ERROR unreachable pattern
+ _ => {}
+ //~^ ERROR unreachable pattern
+ }
+
+ match BAR {
+ BAR => {}
+ //~^ ERROR must be annotated with `#[derive(PartialEq, Eq)]`
+ BAR => {} // should not be emitting unreachable warning
+ //~^ ERROR must be annotated with `#[derive(PartialEq, Eq)]`
+ //~| ERROR unreachable pattern
+ _ => {} // should not be emitting unreachable warning
+ //~^ ERROR unreachable pattern
+ }
+
+ match BAZ {
+ BAZ => {}
+ //~^ ERROR must be annotated with `#[derive(PartialEq, Eq)]`
+ Baz::Baz1 => {} // should not be emitting unreachable warning
+ //~^ ERROR unreachable pattern
+ _ => {}
+ //~^ ERROR unreachable pattern
+ }
+
+ match BAZ {
+ Baz::Baz1 => {}
+ BAZ => {}
+ //~^ ERROR must be annotated with `#[derive(PartialEq, Eq)]`
+ _ => {}
+ //~^ ERROR unreachable pattern
+ }
+
+ match BAZ {
+ BAZ => {}
+ //~^ ERROR must be annotated with `#[derive(PartialEq, Eq)]`
+ Baz::Baz2 => {} // should not be emitting unreachable warning
+ //~^ ERROR unreachable pattern
+ _ => {} // should not be emitting unreachable warning
+ //~^ ERROR unreachable pattern
+ }
+
+ type Quux = fn(usize, usize) -> usize;
+ fn quux(a: usize, b: usize) -> usize { a + b }
+ const QUUX: Quux = quux;
+
+ match QUUX {
+ QUUX => {}
+ QUUX => {}
+ _ => {}
+ }
+
+ #[derive(PartialEq, Eq)]
+ struct Wrap<T>(T);
+ const WRAPQUUX: Wrap<Quux> = Wrap(quux);
+
+ match WRAPQUUX {
+ WRAPQUUX => {}
+ WRAPQUUX => {}
+ Wrap(_) => {}
+ }
+
+ match WRAPQUUX {
+ Wrap(_) => {}
+ WRAPQUUX => {} // detected unreachable because we do inspect the `Wrap` layer
+ //~^ ERROR unreachable pattern
+ }
+
+ #[derive(PartialEq, Eq)]
+ enum WhoKnows<T> {
+ Yay(T),
+ Nope,
+ };
+ const WHOKNOWSQUUX: WhoKnows<Quux> = WhoKnows::Yay(quux);
+
+ match WHOKNOWSQUUX {
+ WHOKNOWSQUUX => {}
+ WhoKnows::Yay(_) => {}
+ WHOKNOWSQUUX => {} // detected unreachable because we do inspect the `WhoKnows` layer
+ //~^ ERROR unreachable pattern
+ WhoKnows::Nope => {}
+ }
+}
diff --git a/tests/ui/pattern/usefulness/consts-opaque.stderr b/tests/ui/pattern/usefulness/consts-opaque.stderr
new file mode 100644
index 000000000..35396751a
--- /dev/null
+++ b/tests/ui/pattern/usefulness/consts-opaque.stderr
@@ -0,0 +1,202 @@
+error: to use a constant of type `Foo` in a pattern, `Foo` must be annotated with `#[derive(PartialEq, Eq)]`
+ --> $DIR/consts-opaque.rs:30:9
+ |
+LL | FOO => {}
+ | ^^^
+
+error: unreachable pattern
+ --> $DIR/consts-opaque.rs:32:9
+ |
+LL | FOO => {}
+ | --- matches any value
+LL |
+LL | _ => {} // should not be emitting unreachable warning
+ | ^ unreachable pattern
+ |
+note: the lint level is defined here
+ --> $DIR/consts-opaque.rs:6:9
+ |
+LL | #![deny(unreachable_patterns)]
+ | ^^^^^^^^^^^^^^^^^^^^
+
+error: to use a constant of type `Foo` in a pattern, `Foo` must be annotated with `#[derive(PartialEq, Eq)]`
+ --> $DIR/consts-opaque.rs:37:9
+ |
+LL | FOO_REF => {}
+ | ^^^^^^^
+
+error: unreachable pattern
+ --> $DIR/consts-opaque.rs:39:9
+ |
+LL | FOO_REF => {}
+ | ------- matches any value
+LL |
+LL | Foo(_) => {} // should not be emitting unreachable warning
+ | ^^^^^^ unreachable pattern
+
+warning: to use a constant of type `Foo` in a pattern, `Foo` must be annotated with `#[derive(PartialEq, Eq)]`
+ --> $DIR/consts-opaque.rs:45:9
+ |
+LL | FOO_REF_REF => {}
+ | ^^^^^^^^^^^
+ |
+ = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+ = note: for more information, see issue #62411 <https://github.com/rust-lang/rust/issues/62411>
+ = note: `#[warn(indirect_structural_match)]` on by default
+
+error: to use a constant of type `Bar` in a pattern, `Bar` must be annotated with `#[derive(PartialEq, Eq)]`
+ --> $DIR/consts-opaque.rs:53:9
+ |
+LL | BAR => {} // should not be emitting unreachable warning
+ | ^^^
+
+error: unreachable pattern
+ --> $DIR/consts-opaque.rs:53:9
+ |
+LL | Bar => {}
+ | --- matches any value
+LL | BAR => {} // should not be emitting unreachable warning
+ | ^^^ unreachable pattern
+
+error: unreachable pattern
+ --> $DIR/consts-opaque.rs:56:9
+ |
+LL | Bar => {}
+ | --- matches any value
+...
+LL | _ => {}
+ | ^ unreachable pattern
+
+error: to use a constant of type `Bar` in a pattern, `Bar` must be annotated with `#[derive(PartialEq, Eq)]`
+ --> $DIR/consts-opaque.rs:61:9
+ |
+LL | BAR => {}
+ | ^^^
+
+error: unreachable pattern
+ --> $DIR/consts-opaque.rs:63:9
+ |
+LL | BAR => {}
+ | --- matches any value
+LL |
+LL | Bar => {} // should not be emitting unreachable warning
+ | ^^^ unreachable pattern
+
+error: unreachable pattern
+ --> $DIR/consts-opaque.rs:65:9
+ |
+LL | BAR => {}
+ | --- matches any value
+...
+LL | _ => {}
+ | ^ unreachable pattern
+
+error: to use a constant of type `Bar` in a pattern, `Bar` must be annotated with `#[derive(PartialEq, Eq)]`
+ --> $DIR/consts-opaque.rs:70:9
+ |
+LL | BAR => {}
+ | ^^^
+
+error: to use a constant of type `Bar` in a pattern, `Bar` must be annotated with `#[derive(PartialEq, Eq)]`
+ --> $DIR/consts-opaque.rs:72:9
+ |
+LL | BAR => {} // should not be emitting unreachable warning
+ | ^^^
+
+error: unreachable pattern
+ --> $DIR/consts-opaque.rs:72:9
+ |
+LL | BAR => {}
+ | --- matches any value
+LL |
+LL | BAR => {} // should not be emitting unreachable warning
+ | ^^^ unreachable pattern
+
+error: unreachable pattern
+ --> $DIR/consts-opaque.rs:75:9
+ |
+LL | BAR => {}
+ | --- matches any value
+...
+LL | _ => {} // should not be emitting unreachable warning
+ | ^ unreachable pattern
+
+error: to use a constant of type `Baz` in a pattern, `Baz` must be annotated with `#[derive(PartialEq, Eq)]`
+ --> $DIR/consts-opaque.rs:80:9
+ |
+LL | BAZ => {}
+ | ^^^
+
+error: unreachable pattern
+ --> $DIR/consts-opaque.rs:82:9
+ |
+LL | BAZ => {}
+ | --- matches any value
+LL |
+LL | Baz::Baz1 => {} // should not be emitting unreachable warning
+ | ^^^^^^^^^ unreachable pattern
+
+error: unreachable pattern
+ --> $DIR/consts-opaque.rs:84:9
+ |
+LL | BAZ => {}
+ | --- matches any value
+...
+LL | _ => {}
+ | ^ unreachable pattern
+
+error: to use a constant of type `Baz` in a pattern, `Baz` must be annotated with `#[derive(PartialEq, Eq)]`
+ --> $DIR/consts-opaque.rs:90:9
+ |
+LL | BAZ => {}
+ | ^^^
+
+error: unreachable pattern
+ --> $DIR/consts-opaque.rs:92:9
+ |
+LL | BAZ => {}
+ | --- matches any value
+LL |
+LL | _ => {}
+ | ^ unreachable pattern
+
+error: to use a constant of type `Baz` in a pattern, `Baz` must be annotated with `#[derive(PartialEq, Eq)]`
+ --> $DIR/consts-opaque.rs:97:9
+ |
+LL | BAZ => {}
+ | ^^^
+
+error: unreachable pattern
+ --> $DIR/consts-opaque.rs:99:9
+ |
+LL | BAZ => {}
+ | --- matches any value
+LL |
+LL | Baz::Baz2 => {} // should not be emitting unreachable warning
+ | ^^^^^^^^^ unreachable pattern
+
+error: unreachable pattern
+ --> $DIR/consts-opaque.rs:101:9
+ |
+LL | BAZ => {}
+ | --- matches any value
+...
+LL | _ => {} // should not be emitting unreachable warning
+ | ^ unreachable pattern
+
+error: unreachable pattern
+ --> $DIR/consts-opaque.rs:127:9
+ |
+LL | Wrap(_) => {}
+ | ------- matches any value
+LL | WRAPQUUX => {} // detected unreachable because we do inspect the `Wrap` layer
+ | ^^^^^^^^ unreachable pattern
+
+error: unreachable pattern
+ --> $DIR/consts-opaque.rs:141:9
+ |
+LL | WHOKNOWSQUUX => {} // detected unreachable because we do inspect the `WhoKnows` layer
+ | ^^^^^^^^^^^^
+
+error: aborting due to 24 previous errors; 1 warning emitted
+
diff --git a/tests/ui/pattern/usefulness/deny-irrefutable-let-patterns.rs b/tests/ui/pattern/usefulness/deny-irrefutable-let-patterns.rs
new file mode 100644
index 000000000..c85af7f3b
--- /dev/null
+++ b/tests/ui/pattern/usefulness/deny-irrefutable-let-patterns.rs
@@ -0,0 +1,16 @@
+#![feature(if_let_guard)]
+
+#![deny(irrefutable_let_patterns)]
+
+fn main() {
+ if let _ = 5 {} //~ ERROR irrefutable `if let` pattern
+
+ while let _ = 5 { //~ ERROR irrefutable `while let` pattern
+ break;
+ }
+
+ match 5 {
+ _ if let _ = 2 => {} //~ ERROR irrefutable `if let` guard pattern
+ _ => {}
+ }
+}
diff --git a/tests/ui/pattern/usefulness/deny-irrefutable-let-patterns.stderr b/tests/ui/pattern/usefulness/deny-irrefutable-let-patterns.stderr
new file mode 100644
index 000000000..cdb6b5c7a
--- /dev/null
+++ b/tests/ui/pattern/usefulness/deny-irrefutable-let-patterns.stderr
@@ -0,0 +1,34 @@
+error: irrefutable `if let` pattern
+ --> $DIR/deny-irrefutable-let-patterns.rs:6:8
+ |
+LL | if let _ = 5 {}
+ | ^^^^^^^^^
+ |
+ = note: this pattern will always match, so the `if let` is useless
+ = help: consider replacing the `if let` with a `let`
+note: the lint level is defined here
+ --> $DIR/deny-irrefutable-let-patterns.rs:3:9
+ |
+LL | #![deny(irrefutable_let_patterns)]
+ | ^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: irrefutable `while let` pattern
+ --> $DIR/deny-irrefutable-let-patterns.rs:8:11
+ |
+LL | while let _ = 5 {
+ | ^^^^^^^^^
+ |
+ = note: this pattern will always match, so the loop will never exit
+ = help: consider instead using a `loop { ... }` with a `let` inside it
+
+error: irrefutable `if let` guard pattern
+ --> $DIR/deny-irrefutable-let-patterns.rs:13:18
+ |
+LL | _ if let _ = 2 => {}
+ | ^
+ |
+ = note: this pattern will always match, so the guard is useless
+ = help: consider removing the guard and adding a `let` inside the match arm
+
+error: aborting due to 3 previous errors
+
diff --git a/tests/ui/pattern/usefulness/doc-hidden-fields.rs b/tests/ui/pattern/usefulness/doc-hidden-fields.rs
new file mode 100644
index 000000000..4163b87dc
--- /dev/null
+++ b/tests/ui/pattern/usefulness/doc-hidden-fields.rs
@@ -0,0 +1,26 @@
+// aux-build:hidden.rs
+
+extern crate hidden;
+
+use hidden::HiddenStruct;
+
+struct InCrate {
+ a: usize,
+ b: bool,
+ #[doc(hidden)]
+ im_hidden: u8
+}
+
+fn main() {
+ let HiddenStruct { one, two } = HiddenStruct::default();
+ //~^ pattern requires `..` due to inaccessible fields
+
+ let HiddenStruct { one } = HiddenStruct::default();
+ //~^ pattern does not mention field `two` and inaccessible fields
+
+ let HiddenStruct { one, hide } = HiddenStruct::default();
+ //~^ pattern does not mention field `two`
+
+ let InCrate { a, b } = InCrate { a: 0, b: false, im_hidden: 0 };
+ //~^ pattern does not mention field `im_hidden`
+}
diff --git a/tests/ui/pattern/usefulness/doc-hidden-fields.stderr b/tests/ui/pattern/usefulness/doc-hidden-fields.stderr
new file mode 100644
index 000000000..f277bfbc8
--- /dev/null
+++ b/tests/ui/pattern/usefulness/doc-hidden-fields.stderr
@@ -0,0 +1,59 @@
+error: pattern requires `..` due to inaccessible fields
+ --> $DIR/doc-hidden-fields.rs:15:9
+ |
+LL | let HiddenStruct { one, two } = HiddenStruct::default();
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^
+ |
+help: ignore the inaccessible and unused fields
+ |
+LL | let HiddenStruct { one, two, .. } = HiddenStruct::default();
+ | ++++
+
+error[E0027]: pattern does not mention field `two` and inaccessible fields
+ --> $DIR/doc-hidden-fields.rs:18:9
+ |
+LL | let HiddenStruct { one } = HiddenStruct::default();
+ | ^^^^^^^^^^^^^^^^^^^^ missing field `two` and inaccessible fields
+ |
+help: include the missing field in the pattern and ignore the inaccessible fields
+ |
+LL | let HiddenStruct { one, two, .. } = HiddenStruct::default();
+ | ~~~~~~~~~~~
+help: if you don't care about this missing field, you can explicitly ignore it
+ |
+LL | let HiddenStruct { one, .. } = HiddenStruct::default();
+ | ~~~~~~
+
+error[E0027]: pattern does not mention field `two`
+ --> $DIR/doc-hidden-fields.rs:21:9
+ |
+LL | let HiddenStruct { one, hide } = HiddenStruct::default();
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^ missing field `two`
+ |
+help: include the missing field in the pattern
+ |
+LL | let HiddenStruct { one, hide, two } = HiddenStruct::default();
+ | ~~~~~~~
+help: if you don't care about this missing field, you can explicitly ignore it
+ |
+LL | let HiddenStruct { one, hide, .. } = HiddenStruct::default();
+ | ~~~~~~
+
+error[E0027]: pattern does not mention field `im_hidden`
+ --> $DIR/doc-hidden-fields.rs:24:9
+ |
+LL | let InCrate { a, b } = InCrate { a: 0, b: false, im_hidden: 0 };
+ | ^^^^^^^^^^^^^^^^ missing field `im_hidden`
+ |
+help: include the missing field in the pattern
+ |
+LL | let InCrate { a, b, im_hidden } = InCrate { a: 0, b: false, im_hidden: 0 };
+ | ~~~~~~~~~~~~~
+help: if you don't care about this missing field, you can explicitly ignore it
+ |
+LL | let InCrate { a, b, .. } = InCrate { a: 0, b: false, im_hidden: 0 };
+ | ~~~~~~
+
+error: aborting due to 4 previous errors
+
+For more information about this error, try `rustc --explain E0027`.
diff --git a/tests/ui/pattern/usefulness/doc-hidden-non-exhaustive.rs b/tests/ui/pattern/usefulness/doc-hidden-non-exhaustive.rs
new file mode 100644
index 000000000..5d4181a30
--- /dev/null
+++ b/tests/ui/pattern/usefulness/doc-hidden-non-exhaustive.rs
@@ -0,0 +1,43 @@
+// aux-build:hidden.rs
+
+extern crate hidden;
+
+use hidden::HiddenEnum;
+
+enum InCrate {
+ A,
+ B,
+ #[doc(hidden)]
+ C,
+}
+
+fn main() {
+ match HiddenEnum::A {
+ HiddenEnum::A => {}
+ HiddenEnum::B => {}
+ }
+ //~^^^^ non-exhaustive patterns: `_` not covered
+
+ match HiddenEnum::A {
+ HiddenEnum::A => {}
+ HiddenEnum::C => {}
+ }
+ //~^^^^ non-exhaustive patterns: `HiddenEnum::B` not covered
+
+ match HiddenEnum::A {
+ HiddenEnum::A => {}
+ }
+ //~^^^ non-exhaustive patterns: `HiddenEnum::B` and `_` not covered
+
+ match None {
+ None => {}
+ Some(HiddenEnum::A) => {}
+ }
+ //~^^^^ non-exhaustive patterns: `Some(HiddenEnum::B)` and `Some(_)` not covered
+
+ match InCrate::A {
+ InCrate::A => {}
+ InCrate::B => {}
+ }
+ //~^^^^ non-exhaustive patterns: `InCrate::C` not covered
+}
diff --git a/tests/ui/pattern/usefulness/doc-hidden-non-exhaustive.stderr b/tests/ui/pattern/usefulness/doc-hidden-non-exhaustive.stderr
new file mode 100644
index 000000000..17e1a2304
--- /dev/null
+++ b/tests/ui/pattern/usefulness/doc-hidden-non-exhaustive.stderr
@@ -0,0 +1,102 @@
+error[E0004]: non-exhaustive patterns: `_` not covered
+ --> $DIR/doc-hidden-non-exhaustive.rs:15:11
+ |
+LL | match HiddenEnum::A {
+ | ^^^^^^^^^^^^^ pattern `_` not covered
+ |
+note: `HiddenEnum` defined here
+ --> $DIR/auxiliary/hidden.rs:1:1
+ |
+LL | pub enum HiddenEnum {
+ | ^^^^^^^^^^^^^^^^^^^
+ = note: the matched value is of type `HiddenEnum`
+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 ~ HiddenEnum::B => {}
+LL + _ => todo!()
+ |
+
+error[E0004]: non-exhaustive patterns: `HiddenEnum::B` not covered
+ --> $DIR/doc-hidden-non-exhaustive.rs:21:11
+ |
+LL | match HiddenEnum::A {
+ | ^^^^^^^^^^^^^ pattern `HiddenEnum::B` not covered
+ |
+note: `HiddenEnum` defined here
+ --> $DIR/auxiliary/hidden.rs:3:5
+ |
+LL | pub enum HiddenEnum {
+ | -------------------
+LL | A,
+LL | B,
+ | ^ not covered
+ = note: the matched value is of type `HiddenEnum`
+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 ~ HiddenEnum::C => {}
+LL + HiddenEnum::B => todo!()
+ |
+
+error[E0004]: non-exhaustive patterns: `HiddenEnum::B` and `_` not covered
+ --> $DIR/doc-hidden-non-exhaustive.rs:27:11
+ |
+LL | match HiddenEnum::A {
+ | ^^^^^^^^^^^^^ patterns `HiddenEnum::B` and `_` not covered
+ |
+note: `HiddenEnum` defined here
+ --> $DIR/auxiliary/hidden.rs:3:5
+ |
+LL | pub enum HiddenEnum {
+ | -------------------
+LL | A,
+LL | B,
+ | ^ not covered
+ = note: the matched value is of type `HiddenEnum`
+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 ~ HiddenEnum::A => {}
+LL + HiddenEnum::B | _ => todo!()
+ |
+
+error[E0004]: non-exhaustive patterns: `Some(HiddenEnum::B)` and `Some(_)` not covered
+ --> $DIR/doc-hidden-non-exhaustive.rs:32:11
+ |
+LL | match None {
+ | ^^^^ patterns `Some(HiddenEnum::B)` and `Some(_)` not covered
+ |
+note: `Option<HiddenEnum>` defined here
+ --> $SRC_DIR/core/src/option.rs:LL:COL
+ ::: $SRC_DIR/core/src/option.rs:LL:COL
+ |
+ = note: not covered
+ = note: the matched value is of type `Option<HiddenEnum>`
+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 ~ Some(HiddenEnum::A) => {}
+LL + Some(HiddenEnum::B) | Some(_) => todo!()
+ |
+
+error[E0004]: non-exhaustive patterns: `InCrate::C` not covered
+ --> $DIR/doc-hidden-non-exhaustive.rs:38:11
+ |
+LL | match InCrate::A {
+ | ^^^^^^^^^^ pattern `InCrate::C` not covered
+ |
+note: `InCrate` defined here
+ --> $DIR/doc-hidden-non-exhaustive.rs:11:5
+ |
+LL | enum InCrate {
+ | -------
+...
+LL | C,
+ | ^ not covered
+ = note: the matched value is of type `InCrate`
+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 ~ InCrate::B => {}
+LL + InCrate::C => todo!()
+ |
+
+error: aborting due to 5 previous errors
+
+For more information about this error, try `rustc --explain E0004`.
diff --git a/tests/ui/pattern/usefulness/empty-match.exhaustive_patterns.stderr b/tests/ui/pattern/usefulness/empty-match.exhaustive_patterns.stderr
new file mode 100644
index 000000000..5e12bc1d2
--- /dev/null
+++ b/tests/ui/pattern/usefulness/empty-match.exhaustive_patterns.stderr
@@ -0,0 +1,303 @@
+error: unreachable pattern
+ --> $DIR/empty-match.rs:37:9
+ |
+LL | _ => {},
+ | ^
+ |
+note: the lint level is defined here
+ --> $DIR/empty-match.rs:8:9
+ |
+LL | #![deny(unreachable_patterns)]
+ | ^^^^^^^^^^^^^^^^^^^^
+
+error: unreachable pattern
+ --> $DIR/empty-match.rs:40:9
+ |
+LL | _ if false => {},
+ | ^
+
+error: unreachable pattern
+ --> $DIR/empty-match.rs:47:9
+ |
+LL | _ => {},
+ | ^
+
+error: unreachable pattern
+ --> $DIR/empty-match.rs:50:9
+ |
+LL | _ if false => {},
+ | ^
+
+error: unreachable pattern
+ --> $DIR/empty-match.rs:57:9
+ |
+LL | _ => {},
+ | ^
+
+error: unreachable pattern
+ --> $DIR/empty-match.rs:60:9
+ |
+LL | _ if false => {},
+ | ^
+
+error[E0004]: non-exhaustive patterns: type `u8` is non-empty
+ --> $DIR/empty-match.rs:78:20
+ |
+LL | match_no_arms!(0u8);
+ | ^^^
+ |
+ = note: the matched value is of type `u8`
+ = help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern
+
+error[E0004]: non-exhaustive patterns: type `NonEmptyStruct1` is non-empty
+ --> $DIR/empty-match.rs:79:20
+ |
+LL | match_no_arms!(NonEmptyStruct1);
+ | ^^^^^^^^^^^^^^^
+ |
+note: `NonEmptyStruct1` defined here
+ --> $DIR/empty-match.rs:14:8
+ |
+LL | struct NonEmptyStruct1;
+ | ^^^^^^^^^^^^^^^
+ = note: the matched value is of type `NonEmptyStruct1`
+ = help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern
+
+error[E0004]: non-exhaustive patterns: type `NonEmptyStruct2` is non-empty
+ --> $DIR/empty-match.rs:80:20
+ |
+LL | match_no_arms!(NonEmptyStruct2(true));
+ | ^^^^^^^^^^^^^^^^^^^^^
+ |
+note: `NonEmptyStruct2` defined here
+ --> $DIR/empty-match.rs:15:8
+ |
+LL | struct NonEmptyStruct2(bool);
+ | ^^^^^^^^^^^^^^^
+ = note: the matched value is of type `NonEmptyStruct2`
+ = help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern
+
+error[E0004]: non-exhaustive patterns: type `NonEmptyUnion1` is non-empty
+ --> $DIR/empty-match.rs:81:20
+ |
+LL | match_no_arms!((NonEmptyUnion1 { foo: () }));
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+ |
+note: `NonEmptyUnion1` defined here
+ --> $DIR/empty-match.rs:16:7
+ |
+LL | union NonEmptyUnion1 {
+ | ^^^^^^^^^^^^^^
+ = note: the matched value is of type `NonEmptyUnion1`
+ = help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern
+
+error[E0004]: non-exhaustive patterns: type `NonEmptyUnion2` is non-empty
+ --> $DIR/empty-match.rs:82:20
+ |
+LL | match_no_arms!((NonEmptyUnion2 { foo: () }));
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+ |
+note: `NonEmptyUnion2` defined here
+ --> $DIR/empty-match.rs:19:7
+ |
+LL | union NonEmptyUnion2 {
+ | ^^^^^^^^^^^^^^
+ = note: the matched value is of type `NonEmptyUnion2`
+ = help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern
+
+error[E0004]: non-exhaustive patterns: `NonEmptyEnum1::Foo(_)` not covered
+ --> $DIR/empty-match.rs:83:20
+ |
+LL | match_no_arms!(NonEmptyEnum1::Foo(true));
+ | ^^^^^^^^^^^^^^^^^^^^^^^^ pattern `NonEmptyEnum1::Foo(_)` not covered
+ |
+note: `NonEmptyEnum1` defined here
+ --> $DIR/empty-match.rs:24:5
+ |
+LL | enum NonEmptyEnum1 {
+ | -------------
+LL | Foo(bool),
+ | ^^^ not covered
+ = note: the matched value is of type `NonEmptyEnum1`
+ = help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern or an explicit pattern
+
+error[E0004]: non-exhaustive patterns: `NonEmptyEnum2::Foo(_)` and `NonEmptyEnum2::Bar` not covered
+ --> $DIR/empty-match.rs:84:20
+ |
+LL | match_no_arms!(NonEmptyEnum2::Foo(true));
+ | ^^^^^^^^^^^^^^^^^^^^^^^^ patterns `NonEmptyEnum2::Foo(_)` and `NonEmptyEnum2::Bar` not covered
+ |
+note: `NonEmptyEnum2` defined here
+ --> $DIR/empty-match.rs:27:5
+ |
+LL | enum NonEmptyEnum2 {
+ | -------------
+LL | Foo(bool),
+ | ^^^ not covered
+LL | Bar,
+ | ^^^ not covered
+ = note: the matched value is of type `NonEmptyEnum2`
+ = help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern or multiple match arms
+
+error[E0004]: non-exhaustive patterns: `NonEmptyEnum5::V1`, `NonEmptyEnum5::V2`, `NonEmptyEnum5::V3` and 2 more not covered
+ --> $DIR/empty-match.rs:85:20
+ |
+LL | match_no_arms!(NonEmptyEnum5::V1);
+ | ^^^^^^^^^^^^^^^^^ patterns `NonEmptyEnum5::V1`, `NonEmptyEnum5::V2`, `NonEmptyEnum5::V3` and 2 more not covered
+ |
+note: `NonEmptyEnum5` defined here
+ --> $DIR/empty-match.rs:30:6
+ |
+LL | enum NonEmptyEnum5 {
+ | ^^^^^^^^^^^^^
+ = note: the matched value is of type `NonEmptyEnum5`
+ = help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern or multiple match arms
+
+error[E0004]: non-exhaustive patterns: `_` not covered
+ --> $DIR/empty-match.rs:87:24
+ |
+LL | match_guarded_arm!(0u8);
+ | ^^^ pattern `_` not covered
+ |
+ = note: the matched value is of type `u8`
+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 ~ _ if false => {}
+LL + _ => todo!()
+ |
+
+error[E0004]: non-exhaustive patterns: `NonEmptyStruct1` not covered
+ --> $DIR/empty-match.rs:88:24
+ |
+LL | match_guarded_arm!(NonEmptyStruct1);
+ | ^^^^^^^^^^^^^^^ pattern `NonEmptyStruct1` not covered
+ |
+note: `NonEmptyStruct1` defined here
+ --> $DIR/empty-match.rs:14:8
+ |
+LL | struct NonEmptyStruct1;
+ | ^^^^^^^^^^^^^^^
+ = note: the matched value is of type `NonEmptyStruct1`
+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 ~ _ if false => {}
+LL + NonEmptyStruct1 => todo!()
+ |
+
+error[E0004]: non-exhaustive patterns: `NonEmptyStruct2(_)` not covered
+ --> $DIR/empty-match.rs:89:24
+ |
+LL | match_guarded_arm!(NonEmptyStruct2(true));
+ | ^^^^^^^^^^^^^^^^^^^^^ pattern `NonEmptyStruct2(_)` not covered
+ |
+note: `NonEmptyStruct2` defined here
+ --> $DIR/empty-match.rs:15:8
+ |
+LL | struct NonEmptyStruct2(bool);
+ | ^^^^^^^^^^^^^^^
+ = note: the matched value is of type `NonEmptyStruct2`
+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 ~ _ if false => {}
+LL + NonEmptyStruct2(_) => todo!()
+ |
+
+error[E0004]: non-exhaustive patterns: `NonEmptyUnion1 { .. }` not covered
+ --> $DIR/empty-match.rs:90:24
+ |
+LL | match_guarded_arm!((NonEmptyUnion1 { foo: () }));
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ pattern `NonEmptyUnion1 { .. }` not covered
+ |
+note: `NonEmptyUnion1` defined here
+ --> $DIR/empty-match.rs:16:7
+ |
+LL | union NonEmptyUnion1 {
+ | ^^^^^^^^^^^^^^
+ = note: the matched value is of type `NonEmptyUnion1`
+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 ~ _ if false => {}
+LL + NonEmptyUnion1 { .. } => todo!()
+ |
+
+error[E0004]: non-exhaustive patterns: `NonEmptyUnion2 { .. }` not covered
+ --> $DIR/empty-match.rs:91:24
+ |
+LL | match_guarded_arm!((NonEmptyUnion2 { foo: () }));
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ pattern `NonEmptyUnion2 { .. }` not covered
+ |
+note: `NonEmptyUnion2` defined here
+ --> $DIR/empty-match.rs:19:7
+ |
+LL | union NonEmptyUnion2 {
+ | ^^^^^^^^^^^^^^
+ = note: the matched value is of type `NonEmptyUnion2`
+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 ~ _ if false => {}
+LL + NonEmptyUnion2 { .. } => todo!()
+ |
+
+error[E0004]: non-exhaustive patterns: `NonEmptyEnum1::Foo(_)` not covered
+ --> $DIR/empty-match.rs:92:24
+ |
+LL | match_guarded_arm!(NonEmptyEnum1::Foo(true));
+ | ^^^^^^^^^^^^^^^^^^^^^^^^ pattern `NonEmptyEnum1::Foo(_)` not covered
+ |
+note: `NonEmptyEnum1` defined here
+ --> $DIR/empty-match.rs:24:5
+ |
+LL | enum NonEmptyEnum1 {
+ | -------------
+LL | Foo(bool),
+ | ^^^ not covered
+ = note: the matched value is of type `NonEmptyEnum1`
+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 ~ _ if false => {}
+LL + NonEmptyEnum1::Foo(_) => todo!()
+ |
+
+error[E0004]: non-exhaustive patterns: `NonEmptyEnum2::Foo(_)` and `NonEmptyEnum2::Bar` not covered
+ --> $DIR/empty-match.rs:93:24
+ |
+LL | match_guarded_arm!(NonEmptyEnum2::Foo(true));
+ | ^^^^^^^^^^^^^^^^^^^^^^^^ patterns `NonEmptyEnum2::Foo(_)` and `NonEmptyEnum2::Bar` not covered
+ |
+note: `NonEmptyEnum2` defined here
+ --> $DIR/empty-match.rs:27:5
+ |
+LL | enum NonEmptyEnum2 {
+ | -------------
+LL | Foo(bool),
+ | ^^^ not covered
+LL | Bar,
+ | ^^^ not covered
+ = note: the matched value is of type `NonEmptyEnum2`
+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 ~ _ if false => {}
+LL + NonEmptyEnum2::Foo(_) | NonEmptyEnum2::Bar => todo!()
+ |
+
+error[E0004]: non-exhaustive patterns: `NonEmptyEnum5::V1`, `NonEmptyEnum5::V2`, `NonEmptyEnum5::V3` and 2 more not covered
+ --> $DIR/empty-match.rs:94:24
+ |
+LL | match_guarded_arm!(NonEmptyEnum5::V1);
+ | ^^^^^^^^^^^^^^^^^ patterns `NonEmptyEnum5::V1`, `NonEmptyEnum5::V2`, `NonEmptyEnum5::V3` and 2 more not covered
+ |
+note: `NonEmptyEnum5` defined here
+ --> $DIR/empty-match.rs:30:6
+ |
+LL | enum NonEmptyEnum5 {
+ | ^^^^^^^^^^^^^
+ = note: the matched value is of type `NonEmptyEnum5`
+help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern as shown, or multiple match arms
+ |
+LL ~ _ if false => {}
+LL + _ => todo!()
+ |
+
+error: aborting due to 22 previous errors
+
+For more information about this error, try `rustc --explain E0004`.
diff --git a/tests/ui/pattern/usefulness/empty-match.normal.stderr b/tests/ui/pattern/usefulness/empty-match.normal.stderr
new file mode 100644
index 000000000..5e12bc1d2
--- /dev/null
+++ b/tests/ui/pattern/usefulness/empty-match.normal.stderr
@@ -0,0 +1,303 @@
+error: unreachable pattern
+ --> $DIR/empty-match.rs:37:9
+ |
+LL | _ => {},
+ | ^
+ |
+note: the lint level is defined here
+ --> $DIR/empty-match.rs:8:9
+ |
+LL | #![deny(unreachable_patterns)]
+ | ^^^^^^^^^^^^^^^^^^^^
+
+error: unreachable pattern
+ --> $DIR/empty-match.rs:40:9
+ |
+LL | _ if false => {},
+ | ^
+
+error: unreachable pattern
+ --> $DIR/empty-match.rs:47:9
+ |
+LL | _ => {},
+ | ^
+
+error: unreachable pattern
+ --> $DIR/empty-match.rs:50:9
+ |
+LL | _ if false => {},
+ | ^
+
+error: unreachable pattern
+ --> $DIR/empty-match.rs:57:9
+ |
+LL | _ => {},
+ | ^
+
+error: unreachable pattern
+ --> $DIR/empty-match.rs:60:9
+ |
+LL | _ if false => {},
+ | ^
+
+error[E0004]: non-exhaustive patterns: type `u8` is non-empty
+ --> $DIR/empty-match.rs:78:20
+ |
+LL | match_no_arms!(0u8);
+ | ^^^
+ |
+ = note: the matched value is of type `u8`
+ = help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern
+
+error[E0004]: non-exhaustive patterns: type `NonEmptyStruct1` is non-empty
+ --> $DIR/empty-match.rs:79:20
+ |
+LL | match_no_arms!(NonEmptyStruct1);
+ | ^^^^^^^^^^^^^^^
+ |
+note: `NonEmptyStruct1` defined here
+ --> $DIR/empty-match.rs:14:8
+ |
+LL | struct NonEmptyStruct1;
+ | ^^^^^^^^^^^^^^^
+ = note: the matched value is of type `NonEmptyStruct1`
+ = help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern
+
+error[E0004]: non-exhaustive patterns: type `NonEmptyStruct2` is non-empty
+ --> $DIR/empty-match.rs:80:20
+ |
+LL | match_no_arms!(NonEmptyStruct2(true));
+ | ^^^^^^^^^^^^^^^^^^^^^
+ |
+note: `NonEmptyStruct2` defined here
+ --> $DIR/empty-match.rs:15:8
+ |
+LL | struct NonEmptyStruct2(bool);
+ | ^^^^^^^^^^^^^^^
+ = note: the matched value is of type `NonEmptyStruct2`
+ = help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern
+
+error[E0004]: non-exhaustive patterns: type `NonEmptyUnion1` is non-empty
+ --> $DIR/empty-match.rs:81:20
+ |
+LL | match_no_arms!((NonEmptyUnion1 { foo: () }));
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+ |
+note: `NonEmptyUnion1` defined here
+ --> $DIR/empty-match.rs:16:7
+ |
+LL | union NonEmptyUnion1 {
+ | ^^^^^^^^^^^^^^
+ = note: the matched value is of type `NonEmptyUnion1`
+ = help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern
+
+error[E0004]: non-exhaustive patterns: type `NonEmptyUnion2` is non-empty
+ --> $DIR/empty-match.rs:82:20
+ |
+LL | match_no_arms!((NonEmptyUnion2 { foo: () }));
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+ |
+note: `NonEmptyUnion2` defined here
+ --> $DIR/empty-match.rs:19:7
+ |
+LL | union NonEmptyUnion2 {
+ | ^^^^^^^^^^^^^^
+ = note: the matched value is of type `NonEmptyUnion2`
+ = help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern
+
+error[E0004]: non-exhaustive patterns: `NonEmptyEnum1::Foo(_)` not covered
+ --> $DIR/empty-match.rs:83:20
+ |
+LL | match_no_arms!(NonEmptyEnum1::Foo(true));
+ | ^^^^^^^^^^^^^^^^^^^^^^^^ pattern `NonEmptyEnum1::Foo(_)` not covered
+ |
+note: `NonEmptyEnum1` defined here
+ --> $DIR/empty-match.rs:24:5
+ |
+LL | enum NonEmptyEnum1 {
+ | -------------
+LL | Foo(bool),
+ | ^^^ not covered
+ = note: the matched value is of type `NonEmptyEnum1`
+ = help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern or an explicit pattern
+
+error[E0004]: non-exhaustive patterns: `NonEmptyEnum2::Foo(_)` and `NonEmptyEnum2::Bar` not covered
+ --> $DIR/empty-match.rs:84:20
+ |
+LL | match_no_arms!(NonEmptyEnum2::Foo(true));
+ | ^^^^^^^^^^^^^^^^^^^^^^^^ patterns `NonEmptyEnum2::Foo(_)` and `NonEmptyEnum2::Bar` not covered
+ |
+note: `NonEmptyEnum2` defined here
+ --> $DIR/empty-match.rs:27:5
+ |
+LL | enum NonEmptyEnum2 {
+ | -------------
+LL | Foo(bool),
+ | ^^^ not covered
+LL | Bar,
+ | ^^^ not covered
+ = note: the matched value is of type `NonEmptyEnum2`
+ = help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern or multiple match arms
+
+error[E0004]: non-exhaustive patterns: `NonEmptyEnum5::V1`, `NonEmptyEnum5::V2`, `NonEmptyEnum5::V3` and 2 more not covered
+ --> $DIR/empty-match.rs:85:20
+ |
+LL | match_no_arms!(NonEmptyEnum5::V1);
+ | ^^^^^^^^^^^^^^^^^ patterns `NonEmptyEnum5::V1`, `NonEmptyEnum5::V2`, `NonEmptyEnum5::V3` and 2 more not covered
+ |
+note: `NonEmptyEnum5` defined here
+ --> $DIR/empty-match.rs:30:6
+ |
+LL | enum NonEmptyEnum5 {
+ | ^^^^^^^^^^^^^
+ = note: the matched value is of type `NonEmptyEnum5`
+ = help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern or multiple match arms
+
+error[E0004]: non-exhaustive patterns: `_` not covered
+ --> $DIR/empty-match.rs:87:24
+ |
+LL | match_guarded_arm!(0u8);
+ | ^^^ pattern `_` not covered
+ |
+ = note: the matched value is of type `u8`
+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 ~ _ if false => {}
+LL + _ => todo!()
+ |
+
+error[E0004]: non-exhaustive patterns: `NonEmptyStruct1` not covered
+ --> $DIR/empty-match.rs:88:24
+ |
+LL | match_guarded_arm!(NonEmptyStruct1);
+ | ^^^^^^^^^^^^^^^ pattern `NonEmptyStruct1` not covered
+ |
+note: `NonEmptyStruct1` defined here
+ --> $DIR/empty-match.rs:14:8
+ |
+LL | struct NonEmptyStruct1;
+ | ^^^^^^^^^^^^^^^
+ = note: the matched value is of type `NonEmptyStruct1`
+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 ~ _ if false => {}
+LL + NonEmptyStruct1 => todo!()
+ |
+
+error[E0004]: non-exhaustive patterns: `NonEmptyStruct2(_)` not covered
+ --> $DIR/empty-match.rs:89:24
+ |
+LL | match_guarded_arm!(NonEmptyStruct2(true));
+ | ^^^^^^^^^^^^^^^^^^^^^ pattern `NonEmptyStruct2(_)` not covered
+ |
+note: `NonEmptyStruct2` defined here
+ --> $DIR/empty-match.rs:15:8
+ |
+LL | struct NonEmptyStruct2(bool);
+ | ^^^^^^^^^^^^^^^
+ = note: the matched value is of type `NonEmptyStruct2`
+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 ~ _ if false => {}
+LL + NonEmptyStruct2(_) => todo!()
+ |
+
+error[E0004]: non-exhaustive patterns: `NonEmptyUnion1 { .. }` not covered
+ --> $DIR/empty-match.rs:90:24
+ |
+LL | match_guarded_arm!((NonEmptyUnion1 { foo: () }));
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ pattern `NonEmptyUnion1 { .. }` not covered
+ |
+note: `NonEmptyUnion1` defined here
+ --> $DIR/empty-match.rs:16:7
+ |
+LL | union NonEmptyUnion1 {
+ | ^^^^^^^^^^^^^^
+ = note: the matched value is of type `NonEmptyUnion1`
+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 ~ _ if false => {}
+LL + NonEmptyUnion1 { .. } => todo!()
+ |
+
+error[E0004]: non-exhaustive patterns: `NonEmptyUnion2 { .. }` not covered
+ --> $DIR/empty-match.rs:91:24
+ |
+LL | match_guarded_arm!((NonEmptyUnion2 { foo: () }));
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ pattern `NonEmptyUnion2 { .. }` not covered
+ |
+note: `NonEmptyUnion2` defined here
+ --> $DIR/empty-match.rs:19:7
+ |
+LL | union NonEmptyUnion2 {
+ | ^^^^^^^^^^^^^^
+ = note: the matched value is of type `NonEmptyUnion2`
+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 ~ _ if false => {}
+LL + NonEmptyUnion2 { .. } => todo!()
+ |
+
+error[E0004]: non-exhaustive patterns: `NonEmptyEnum1::Foo(_)` not covered
+ --> $DIR/empty-match.rs:92:24
+ |
+LL | match_guarded_arm!(NonEmptyEnum1::Foo(true));
+ | ^^^^^^^^^^^^^^^^^^^^^^^^ pattern `NonEmptyEnum1::Foo(_)` not covered
+ |
+note: `NonEmptyEnum1` defined here
+ --> $DIR/empty-match.rs:24:5
+ |
+LL | enum NonEmptyEnum1 {
+ | -------------
+LL | Foo(bool),
+ | ^^^ not covered
+ = note: the matched value is of type `NonEmptyEnum1`
+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 ~ _ if false => {}
+LL + NonEmptyEnum1::Foo(_) => todo!()
+ |
+
+error[E0004]: non-exhaustive patterns: `NonEmptyEnum2::Foo(_)` and `NonEmptyEnum2::Bar` not covered
+ --> $DIR/empty-match.rs:93:24
+ |
+LL | match_guarded_arm!(NonEmptyEnum2::Foo(true));
+ | ^^^^^^^^^^^^^^^^^^^^^^^^ patterns `NonEmptyEnum2::Foo(_)` and `NonEmptyEnum2::Bar` not covered
+ |
+note: `NonEmptyEnum2` defined here
+ --> $DIR/empty-match.rs:27:5
+ |
+LL | enum NonEmptyEnum2 {
+ | -------------
+LL | Foo(bool),
+ | ^^^ not covered
+LL | Bar,
+ | ^^^ not covered
+ = note: the matched value is of type `NonEmptyEnum2`
+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 ~ _ if false => {}
+LL + NonEmptyEnum2::Foo(_) | NonEmptyEnum2::Bar => todo!()
+ |
+
+error[E0004]: non-exhaustive patterns: `NonEmptyEnum5::V1`, `NonEmptyEnum5::V2`, `NonEmptyEnum5::V3` and 2 more not covered
+ --> $DIR/empty-match.rs:94:24
+ |
+LL | match_guarded_arm!(NonEmptyEnum5::V1);
+ | ^^^^^^^^^^^^^^^^^ patterns `NonEmptyEnum5::V1`, `NonEmptyEnum5::V2`, `NonEmptyEnum5::V3` and 2 more not covered
+ |
+note: `NonEmptyEnum5` defined here
+ --> $DIR/empty-match.rs:30:6
+ |
+LL | enum NonEmptyEnum5 {
+ | ^^^^^^^^^^^^^
+ = note: the matched value is of type `NonEmptyEnum5`
+help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern as shown, or multiple match arms
+ |
+LL ~ _ if false => {}
+LL + _ => todo!()
+ |
+
+error: aborting due to 22 previous errors
+
+For more information about this error, try `rustc --explain E0004`.
diff --git a/tests/ui/pattern/usefulness/empty-match.rs b/tests/ui/pattern/usefulness/empty-match.rs
new file mode 100644
index 000000000..9cdc0413b
--- /dev/null
+++ b/tests/ui/pattern/usefulness/empty-match.rs
@@ -0,0 +1,95 @@
+// aux-build:empty.rs
+// revisions: normal exhaustive_patterns
+//
+// This tests a match with no arms on various types.
+#![feature(never_type)]
+#![feature(never_type_fallback)]
+#![cfg_attr(exhaustive_patterns, feature(exhaustive_patterns))]
+#![deny(unreachable_patterns)]
+
+extern crate empty;
+
+enum EmptyEnum {}
+
+struct NonEmptyStruct1;
+struct NonEmptyStruct2(bool);
+union NonEmptyUnion1 {
+ foo: (),
+}
+union NonEmptyUnion2 {
+ foo: (),
+ bar: (),
+}
+enum NonEmptyEnum1 {
+ Foo(bool),
+}
+enum NonEmptyEnum2 {
+ Foo(bool),
+ Bar,
+}
+enum NonEmptyEnum5 {
+ V1, V2, V3, V4, V5,
+}
+
+fn empty_enum(x: EmptyEnum) {
+ match x {} // ok
+ match x {
+ _ => {}, //~ ERROR unreachable pattern
+ }
+ match x {
+ _ if false => {}, //~ ERROR unreachable pattern
+ }
+}
+
+fn empty_foreign_enum(x: empty::EmptyForeignEnum) {
+ match x {} // ok
+ match x {
+ _ => {}, //~ ERROR unreachable pattern
+ }
+ match x {
+ _ if false => {}, //~ ERROR unreachable pattern
+ }
+}
+
+fn never(x: !) {
+ match x {} // ok
+ match x {
+ _ => {}, //~ ERROR unreachable pattern
+ }
+ match x {
+ _ if false => {}, //~ ERROR unreachable pattern
+ }
+}
+
+macro_rules! match_no_arms {
+ ($e:expr) => {
+ match $e {}
+ };
+}
+macro_rules! match_guarded_arm {
+ ($e:expr) => {
+ match $e {
+ _ if false => {}
+ }
+ };
+}
+
+fn main() {
+ match_no_arms!(0u8); //~ ERROR type `u8` is non-empty
+ match_no_arms!(NonEmptyStruct1); //~ ERROR type `NonEmptyStruct1` is non-empty
+ match_no_arms!(NonEmptyStruct2(true)); //~ ERROR type `NonEmptyStruct2` is non-empty
+ match_no_arms!((NonEmptyUnion1 { foo: () })); //~ ERROR type `NonEmptyUnion1` is non-empty
+ match_no_arms!((NonEmptyUnion2 { foo: () })); //~ ERROR type `NonEmptyUnion2` is non-empty
+ match_no_arms!(NonEmptyEnum1::Foo(true)); //~ ERROR `NonEmptyEnum1::Foo(_)` not covered
+ match_no_arms!(NonEmptyEnum2::Foo(true)); //~ ERROR `NonEmptyEnum2::Foo(_)` and `NonEmptyEnum2::Bar` not covered
+ match_no_arms!(NonEmptyEnum5::V1); //~ ERROR `NonEmptyEnum5::V1`, `NonEmptyEnum5::V2`, `NonEmptyEnum5::V3` and 2 more not covered
+
+ match_guarded_arm!(0u8); //~ ERROR `_` not covered
+ match_guarded_arm!(NonEmptyStruct1); //~ ERROR `NonEmptyStruct1` not covered
+ match_guarded_arm!(NonEmptyStruct2(true)); //~ ERROR `NonEmptyStruct2(_)` not covered
+ match_guarded_arm!((NonEmptyUnion1 { foo: () })); //~ ERROR `NonEmptyUnion1 { .. }` not covered
+ match_guarded_arm!((NonEmptyUnion2 { foo: () })); //~ ERROR `NonEmptyUnion2 { .. }` not covered
+ match_guarded_arm!(NonEmptyEnum1::Foo(true)); //~ ERROR `NonEmptyEnum1::Foo(_)` not covered
+ match_guarded_arm!(NonEmptyEnum2::Foo(true)); //~ ERROR `NonEmptyEnum2::Foo(_)` and `NonEmptyEnum2::Bar` not covered
+ match_guarded_arm!(NonEmptyEnum5::V1); //~ ERROR `NonEmptyEnum5::V1`, `NonEmptyEnum5::V2`, `NonEmptyEnum5::V3` and 2 more not covered
+}
diff --git a/tests/ui/pattern/usefulness/floats.rs b/tests/ui/pattern/usefulness/floats.rs
new file mode 100644
index 000000000..095f5ac9a
--- /dev/null
+++ b/tests/ui/pattern/usefulness/floats.rs
@@ -0,0 +1,19 @@
+#![allow(illegal_floating_point_literal_pattern)]
+#![deny(unreachable_patterns)]
+
+fn main() {
+ match 0.0 {
+ 0.0..=1.0 => {}
+ _ => {} // ok
+ }
+
+ match 0.0 { //~ ERROR non-exhaustive patterns
+ 0.0..=1.0 => {}
+ }
+
+ match 1.0f64 {
+ 0.01f64 ..= 6.5f64 => {}
+ 0.02f64 => {} //~ ERROR unreachable pattern
+ _ => {}
+ };
+}
diff --git a/tests/ui/pattern/usefulness/floats.stderr b/tests/ui/pattern/usefulness/floats.stderr
new file mode 100644
index 000000000..c926e50b3
--- /dev/null
+++ b/tests/ui/pattern/usefulness/floats.stderr
@@ -0,0 +1,28 @@
+error[E0004]: non-exhaustive patterns: `_` not covered
+ --> $DIR/floats.rs:10:11
+ |
+LL | match 0.0 {
+ | ^^^ pattern `_` not covered
+ |
+ = note: the matched value is of type `f64`
+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 ~ 0.0..=1.0 => {}
+LL + _ => todo!()
+ |
+
+error: unreachable pattern
+ --> $DIR/floats.rs:16:7
+ |
+LL | 0.02f64 => {}
+ | ^^^^^^^
+ |
+note: the lint level is defined here
+ --> $DIR/floats.rs:2:9
+ |
+LL | #![deny(unreachable_patterns)]
+ | ^^^^^^^^^^^^^^^^^^^^
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0004`.
diff --git a/tests/ui/pattern/usefulness/guards.rs b/tests/ui/pattern/usefulness/guards.rs
new file mode 100644
index 000000000..b15440cf6
--- /dev/null
+++ b/tests/ui/pattern/usefulness/guards.rs
@@ -0,0 +1,22 @@
+#![feature(exclusive_range_pattern)]
+#![deny(unreachable_patterns)]
+
+enum Q { R(Option<usize>) }
+
+pub fn main() {
+ match Q::R(None) {
+ Q::R(S) if S.is_some() => {}
+ _ => {}
+ }
+
+ match 0u8 { //~ ERROR non-exhaustive patterns
+ 0 .. 128 => {}
+ 128 ..= 255 if true => {}
+ }
+
+ match 0u8 {
+ 0 .. 128 => {}
+ 128 ..= 255 if false => {}
+ 128 ..= 255 => {} // ok, because previous arm was guarded
+ }
+}
diff --git a/tests/ui/pattern/usefulness/guards.stderr b/tests/ui/pattern/usefulness/guards.stderr
new file mode 100644
index 000000000..0c1563c16
--- /dev/null
+++ b/tests/ui/pattern/usefulness/guards.stderr
@@ -0,0 +1,16 @@
+error[E0004]: non-exhaustive patterns: `128_u8..=u8::MAX` not covered
+ --> $DIR/guards.rs:12:11
+ |
+LL | match 0u8 {
+ | ^^^ pattern `128_u8..=u8::MAX` not covered
+ |
+ = note: the matched value is of type `u8`
+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 ~ 128 ..= 255 if true => {}
+LL + 128_u8..=u8::MAX => todo!()
+ |
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0004`.
diff --git a/tests/ui/pattern/usefulness/integer-ranges/exhaustiveness.rs b/tests/ui/pattern/usefulness/integer-ranges/exhaustiveness.rs
new file mode 100644
index 000000000..0f5f49c4c
--- /dev/null
+++ b/tests/ui/pattern/usefulness/integer-ranges/exhaustiveness.rs
@@ -0,0 +1,101 @@
+#![feature(exclusive_range_pattern)]
+#![allow(overlapping_range_endpoints)]
+#![deny(unreachable_patterns)]
+
+macro_rules! m {
+ ($s:expr, $($t:tt)+) => {
+ match $s { $($t)+ => {} }
+ }
+}
+
+macro_rules! test_int {
+ ($s:expr, $min:path, $max:path) => {
+ m!($s, $min..=$max);
+ m!($s, $min..5 | 5..=$max);
+ m!($s, $min..=4 | 5..=$max);
+ m!($s, $min..$max | $max);
+ m!(($s, true), ($min..5, true) | (5..=$max, true) | ($min..=$max, false));
+ }
+}
+
+fn main() {
+ test_int!(0u8, u8::MIN, u8::MAX);
+ test_int!(0u16, u16::MIN, u16::MAX);
+ test_int!(0u32, u32::MIN, u32::MAX);
+ test_int!(0u64, u64::MIN, u64::MAX);
+ test_int!(0u128, u128::MIN, u128::MAX);
+
+ test_int!(0i8, i8::MIN, i8::MAX);
+ test_int!(0i16, i16::MIN, i16::MAX);
+ test_int!(0i32, i32::MIN, i32::MAX);
+ test_int!(0i64, i64::MIN, i64::MAX);
+ test_int!(0i128, i128::MIN, i128::MAX);
+
+ m!('a', '\u{0}'..=char::MAX);
+ m!('a', '\u{0}'..='\u{10_FFFF}');
+ // We can get away with just covering the following two ranges, which correspond to all valid
+ // Unicode Scalar Values.
+ m!('a', '\u{0}'..='\u{D7FF}' | '\u{E000}'..=char::MAX);
+ m!('a', '\u{0}'..'\u{D7FF}' | '\u{D7FF}' | '\u{E000}'..=char::MAX);
+
+ let 0..=255 = 0u8;
+ let -128..=127 = 0i8;
+ let -2147483648..=2147483647 = 0i32;
+ let '\u{0000}'..='\u{10FFFF}' = 'v';
+
+ // Almost exhaustive
+ m!(0u8, 0..255); //~ ERROR non-exhaustive patterns
+ m!(0u8, 0..=254); //~ ERROR non-exhaustive patterns
+ m!(0u8, 1..=255); //~ ERROR non-exhaustive patterns
+ m!(0u8, 0..42 | 43..=255); //~ ERROR non-exhaustive patterns
+ m!(0i8, -128..127); //~ ERROR non-exhaustive patterns
+ m!(0i8, -128..=126); //~ ERROR non-exhaustive patterns
+ m!(0i8, -127..=127); //~ ERROR non-exhaustive patterns
+ match 0i8 { //~ ERROR non-exhaustive patterns
+ i8::MIN ..= -1 => {}
+ 1 ..= i8::MAX => {}
+ }
+ const ALMOST_MAX: u128 = u128::MAX - 1;
+ m!(0u128, 0..=ALMOST_MAX); //~ ERROR non-exhaustive patterns
+ m!(0u128, 0..=4); //~ ERROR non-exhaustive patterns
+ m!(0u128, 1..=u128::MAX); //~ ERROR non-exhaustive patterns
+
+ // More complicatedly (non-)exhaustive
+ match 0u8 {
+ 0 ..= 30 => {}
+ 20 ..= 70 => {}
+ 50 ..= 255 => {}
+ }
+ match (0u8, true) { //~ ERROR non-exhaustive patterns
+ (0 ..= 125, false) => {}
+ (128 ..= 255, false) => {}
+ (0 ..= 255, true) => {}
+ }
+ match (0u8, true) { // ok
+ (0 ..= 125, false) => {}
+ (128 ..= 255, false) => {}
+ (0 ..= 255, true) => {}
+ (125 .. 128, false) => {}
+ }
+ match (true, 0u8) {
+ (true, 0 ..= 255) => {}
+ (false, 0 ..= 125) => {}
+ (false, 128 ..= 255) => {}
+ (false, 125 .. 128) => {}
+ }
+ match Some(0u8) {
+ None => {}
+ Some(0 ..= 125) => {}
+ Some(128 ..= 255) => {}
+ Some(125 .. 128) => {}
+ }
+ const FOO: u8 = 41;
+ const BAR: &u8 = &42;
+ match &0u8 {
+ 0..41 => {}
+ &FOO => {}
+ BAR => {}
+ 43..=255 => {}
+ }
+
+}
diff --git a/tests/ui/pattern/usefulness/integer-ranges/exhaustiveness.stderr b/tests/ui/pattern/usefulness/integer-ranges/exhaustiveness.stderr
new file mode 100644
index 000000000..f30ba05df
--- /dev/null
+++ b/tests/ui/pattern/usefulness/integer-ranges/exhaustiveness.stderr
@@ -0,0 +1,149 @@
+error[E0004]: non-exhaustive patterns: `u8::MAX` not covered
+ --> $DIR/exhaustiveness.rs:47:8
+ |
+LL | m!(0u8, 0..255);
+ | ^^^ pattern `u8::MAX` not covered
+ |
+ = note: the matched value is of type `u8`
+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 $s { $($t)+ => {}, u8::MAX => todo!() }
+ | ++++++++++++++++++++
+
+error[E0004]: non-exhaustive patterns: `u8::MAX` not covered
+ --> $DIR/exhaustiveness.rs:48:8
+ |
+LL | m!(0u8, 0..=254);
+ | ^^^ pattern `u8::MAX` not covered
+ |
+ = note: the matched value is of type `u8`
+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 $s { $($t)+ => {}, u8::MAX => todo!() }
+ | ++++++++++++++++++++
+
+error[E0004]: non-exhaustive patterns: `0_u8` not covered
+ --> $DIR/exhaustiveness.rs:49:8
+ |
+LL | m!(0u8, 1..=255);
+ | ^^^ pattern `0_u8` not covered
+ |
+ = note: the matched value is of type `u8`
+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 $s { $($t)+ => {}, 0_u8 => todo!() }
+ | +++++++++++++++++
+
+error[E0004]: non-exhaustive patterns: `42_u8` not covered
+ --> $DIR/exhaustiveness.rs:50:8
+ |
+LL | m!(0u8, 0..42 | 43..=255);
+ | ^^^ pattern `42_u8` not covered
+ |
+ = note: the matched value is of type `u8`
+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 $s { $($t)+ => {}, 42_u8 => todo!() }
+ | ++++++++++++++++++
+
+error[E0004]: non-exhaustive patterns: `i8::MAX` not covered
+ --> $DIR/exhaustiveness.rs:51:8
+ |
+LL | m!(0i8, -128..127);
+ | ^^^ pattern `i8::MAX` not covered
+ |
+ = note: the matched value is of type `i8`
+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 $s { $($t)+ => {}, i8::MAX => todo!() }
+ | ++++++++++++++++++++
+
+error[E0004]: non-exhaustive patterns: `i8::MAX` not covered
+ --> $DIR/exhaustiveness.rs:52:8
+ |
+LL | m!(0i8, -128..=126);
+ | ^^^ pattern `i8::MAX` not covered
+ |
+ = note: the matched value is of type `i8`
+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 $s { $($t)+ => {}, i8::MAX => todo!() }
+ | ++++++++++++++++++++
+
+error[E0004]: non-exhaustive patterns: `i8::MIN` not covered
+ --> $DIR/exhaustiveness.rs:53:8
+ |
+LL | m!(0i8, -127..=127);
+ | ^^^ pattern `i8::MIN` not covered
+ |
+ = note: the matched value is of type `i8`
+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 $s { $($t)+ => {}, i8::MIN => todo!() }
+ | ++++++++++++++++++++
+
+error[E0004]: non-exhaustive patterns: `0_i8` not covered
+ --> $DIR/exhaustiveness.rs:54:11
+ |
+LL | match 0i8 {
+ | ^^^ pattern `0_i8` not covered
+ |
+ = note: the matched value is of type `i8`
+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 ~ 1 ..= i8::MAX => {}
+LL + 0_i8 => todo!()
+ |
+
+error[E0004]: non-exhaustive patterns: `u128::MAX` not covered
+ --> $DIR/exhaustiveness.rs:59:8
+ |
+LL | m!(0u128, 0..=ALMOST_MAX);
+ | ^^^^^ pattern `u128::MAX` not covered
+ |
+ = note: the matched value is of type `u128`
+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 $s { $($t)+ => {}, u128::MAX => todo!() }
+ | ++++++++++++++++++++++
+
+error[E0004]: non-exhaustive patterns: `5_u128..=u128::MAX` not covered
+ --> $DIR/exhaustiveness.rs:60:8
+ |
+LL | m!(0u128, 0..=4);
+ | ^^^^^ pattern `5_u128..=u128::MAX` not covered
+ |
+ = note: the matched value is of type `u128`
+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 $s { $($t)+ => {}, 5_u128..=u128::MAX => todo!() }
+ | +++++++++++++++++++++++++++++++
+
+error[E0004]: non-exhaustive patterns: `0_u128` not covered
+ --> $DIR/exhaustiveness.rs:61:8
+ |
+LL | m!(0u128, 1..=u128::MAX);
+ | ^^^^^ pattern `0_u128` not covered
+ |
+ = note: the matched value is of type `u128`
+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 $s { $($t)+ => {}, 0_u128 => todo!() }
+ | +++++++++++++++++++
+
+error[E0004]: non-exhaustive patterns: `(126_u8..=127_u8, false)` not covered
+ --> $DIR/exhaustiveness.rs:69:11
+ |
+LL | match (0u8, true) {
+ | ^^^^^^^^^^^ pattern `(126_u8..=127_u8, false)` not covered
+ |
+ = note: the matched value is of type `(u8, bool)`
+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 ~ (0 ..= 255, true) => {}
+LL + (126_u8..=127_u8, false) => todo!()
+ |
+
+error: aborting due to 12 previous errors
+
+For more information about this error, try `rustc --explain E0004`.
diff --git a/tests/ui/pattern/usefulness/integer-ranges/overlapping_range_endpoints.rs b/tests/ui/pattern/usefulness/integer-ranges/overlapping_range_endpoints.rs
new file mode 100644
index 000000000..5ea92b070
--- /dev/null
+++ b/tests/ui/pattern/usefulness/integer-ranges/overlapping_range_endpoints.rs
@@ -0,0 +1,59 @@
+#![feature(exclusive_range_pattern)]
+#![deny(overlapping_range_endpoints)]
+
+macro_rules! m {
+ ($s:expr, $t1:pat, $t2:pat) => {
+ match $s {
+ $t1 => {}
+ $t2 => {}
+ _ => {}
+ }
+ }
+}
+
+fn main() {
+ m!(0u8, 20..=30, 30..=40); //~ ERROR multiple patterns overlap on their endpoints
+ m!(0u8, 30..=40, 20..=30); //~ ERROR multiple patterns overlap on their endpoints
+ m!(0u8, 20..=30, 31..=40);
+ m!(0u8, 20..=30, 29..=40);
+ m!(0u8, 20.. 30, 29..=40); //~ ERROR multiple patterns overlap on their endpoints
+ m!(0u8, 20.. 30, 28..=40);
+ m!(0u8, 20.. 30, 30..=40);
+ m!(0u8, 20..=30, 30..=30);
+ m!(0u8, 20..=30, 30..=31); //~ ERROR multiple patterns overlap on their endpoints
+ m!(0u8, 20..=30, 29..=30);
+ m!(0u8, 20..=30, 20..=20);
+ m!(0u8, 20..=30, 20..=21);
+ m!(0u8, 20..=30, 19..=20); //~ ERROR multiple patterns overlap on their endpoints
+ m!(0u8, 20..=30, 20);
+ m!(0u8, 20..=30, 25);
+ m!(0u8, 20..=30, 30);
+ m!(0u8, 20.. 30, 29);
+ m!(0u8, 20, 20..=30);
+ m!(0u8, 25, 20..=30);
+ m!(0u8, 30, 20..=30);
+
+ match 0u8 {
+ 0..=10 => {}
+ 20..=30 => {}
+ 10..=20 => {} //~ ERROR multiple patterns overlap on their endpoints
+ _ => {}
+ }
+ match (0u8, true) {
+ (0..=10, true) => {}
+ (10..20, true) => {} // not detected
+ (10..20, false) => {}
+ _ => {}
+ }
+ match (true, 0u8) {
+ (true, 0..=10) => {}
+ (true, 10..20) => {} //~ ERROR multiple patterns overlap on their endpoints
+ (false, 10..20) => {}
+ _ => {}
+ }
+ match Some(0u8) {
+ Some(0..=10) => {}
+ Some(10..20) => {} //~ ERROR multiple patterns overlap on their endpoints
+ _ => {}
+ }
+}
diff --git a/tests/ui/pattern/usefulness/integer-ranges/overlapping_range_endpoints.stderr b/tests/ui/pattern/usefulness/integer-ranges/overlapping_range_endpoints.stderr
new file mode 100644
index 000000000..ea0e8f6e4
--- /dev/null
+++ b/tests/ui/pattern/usefulness/integer-ranges/overlapping_range_endpoints.stderr
@@ -0,0 +1,89 @@
+error: multiple patterns overlap on their endpoints
+ --> $DIR/overlapping_range_endpoints.rs:15:22
+ |
+LL | m!(0u8, 20..=30, 30..=40);
+ | ------- ^^^^^^^ ... with this range
+ | |
+ | this range overlaps on `30_u8`...
+ |
+ = note: you likely meant to write mutually exclusive ranges
+note: the lint level is defined here
+ --> $DIR/overlapping_range_endpoints.rs:2:9
+ |
+LL | #![deny(overlapping_range_endpoints)]
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: multiple patterns overlap on their endpoints
+ --> $DIR/overlapping_range_endpoints.rs:16:22
+ |
+LL | m!(0u8, 30..=40, 20..=30);
+ | ------- ^^^^^^^ ... with this range
+ | |
+ | this range overlaps on `30_u8`...
+ |
+ = note: you likely meant to write mutually exclusive ranges
+
+error: multiple patterns overlap on their endpoints
+ --> $DIR/overlapping_range_endpoints.rs:19:22
+ |
+LL | m!(0u8, 20.. 30, 29..=40);
+ | ------- ^^^^^^^ ... with this range
+ | |
+ | this range overlaps on `29_u8`...
+ |
+ = note: you likely meant to write mutually exclusive ranges
+
+error: multiple patterns overlap on their endpoints
+ --> $DIR/overlapping_range_endpoints.rs:23:22
+ |
+LL | m!(0u8, 20..=30, 30..=31);
+ | ------- ^^^^^^^ ... with this range
+ | |
+ | this range overlaps on `30_u8`...
+ |
+ = note: you likely meant to write mutually exclusive ranges
+
+error: multiple patterns overlap on their endpoints
+ --> $DIR/overlapping_range_endpoints.rs:27:22
+ |
+LL | m!(0u8, 20..=30, 19..=20);
+ | ------- ^^^^^^^ ... with this range
+ | |
+ | this range overlaps on `20_u8`...
+ |
+ = note: you likely meant to write mutually exclusive ranges
+
+error: multiple patterns overlap on their endpoints
+ --> $DIR/overlapping_range_endpoints.rs:39:9
+ |
+LL | 0..=10 => {}
+ | ------ this range overlaps on `10_u8`...
+LL | 20..=30 => {}
+ | ------- this range overlaps on `20_u8`...
+LL | 10..=20 => {}
+ | ^^^^^^^ ... with this range
+ |
+ = note: you likely meant to write mutually exclusive ranges
+
+error: multiple patterns overlap on their endpoints
+ --> $DIR/overlapping_range_endpoints.rs:50:16
+ |
+LL | (true, 0..=10) => {}
+ | ------ this range overlaps on `10_u8`...
+LL | (true, 10..20) => {}
+ | ^^^^^^ ... with this range
+ |
+ = note: you likely meant to write mutually exclusive ranges
+
+error: multiple patterns overlap on their endpoints
+ --> $DIR/overlapping_range_endpoints.rs:56:14
+ |
+LL | Some(0..=10) => {}
+ | ------ this range overlaps on `10_u8`...
+LL | Some(10..20) => {}
+ | ^^^^^^ ... with this range
+ |
+ = note: you likely meant to write mutually exclusive ranges
+
+error: aborting due to 8 previous errors
+
diff --git a/tests/ui/pattern/usefulness/integer-ranges/pointer-sized-int.allow.stderr b/tests/ui/pattern/usefulness/integer-ranges/pointer-sized-int.allow.stderr
new file mode 100644
index 000000000..9f277fa1e
--- /dev/null
+++ b/tests/ui/pattern/usefulness/integer-ranges/pointer-sized-int.allow.stderr
@@ -0,0 +1,17 @@
+error[E0004]: non-exhaustive patterns: type `usize` is non-empty
+ --> $DIR/pointer-sized-int.rs:48:11
+ |
+LL | match 7usize {}
+ | ^^^^^^
+ |
+ = note: the matched value is of type `usize`
+help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern as shown
+ |
+LL ~ match 7usize {
+LL + _ => todo!(),
+LL + }
+ |
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0004`.
diff --git a/tests/ui/pattern/usefulness/integer-ranges/pointer-sized-int.deny.stderr b/tests/ui/pattern/usefulness/integer-ranges/pointer-sized-int.deny.stderr
new file mode 100644
index 000000000..e3eb98ccd
--- /dev/null
+++ b/tests/ui/pattern/usefulness/integer-ranges/pointer-sized-int.deny.stderr
@@ -0,0 +1,170 @@
+error[E0004]: non-exhaustive patterns: `_` not covered
+ --> $DIR/pointer-sized-int.rs:12:11
+ |
+LL | match 0usize {
+ | ^^^^^^ pattern `_` not covered
+ |
+ = note: the matched value is of type `usize`
+ = note: `usize` does not have a fixed maximum value, so a wildcard `_` is necessary to match exhaustively
+ = help: add `#![feature(precise_pointer_size_matching)]` to the crate attributes to enable precise `usize` matching
+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 ~ 0 ..= usize::MAX => {}
+LL + _ => todo!()
+ |
+
+error[E0004]: non-exhaustive patterns: `_` not covered
+ --> $DIR/pointer-sized-int.rs:17:11
+ |
+LL | match 0isize {
+ | ^^^^^^ pattern `_` not covered
+ |
+ = note: the matched value is of type `isize`
+ = note: `isize` does not have a fixed maximum value, so a wildcard `_` is necessary to match exhaustively
+ = help: add `#![feature(precise_pointer_size_matching)]` to the crate attributes to enable precise `isize` matching
+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 ~ isize::MIN ..= isize::MAX => {}
+LL + _ => todo!()
+ |
+
+error[E0004]: non-exhaustive patterns: `_` not covered
+ --> $DIR/pointer-sized-int.rs:22:8
+ |
+LL | m!(0usize, 0..=usize::MAX);
+ | ^^^^^^ pattern `_` not covered
+ |
+ = note: the matched value is of type `usize`
+ = note: `usize` does not have a fixed maximum value, so a wildcard `_` is necessary to match exhaustively
+ = help: add `#![feature(precise_pointer_size_matching)]` to the crate attributes to enable precise `usize` matching
+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 $s { $($t)+ => {}, _ => todo!() }
+ | ++++++++++++++
+
+error[E0004]: non-exhaustive patterns: `_` not covered
+ --> $DIR/pointer-sized-int.rs:24:8
+ |
+LL | m!(0usize, 0..5 | 5..=usize::MAX);
+ | ^^^^^^ pattern `_` not covered
+ |
+ = note: the matched value is of type `usize`
+ = note: `usize` does not have a fixed maximum value, so a wildcard `_` is necessary to match exhaustively
+ = help: add `#![feature(precise_pointer_size_matching)]` to the crate attributes to enable precise `usize` matching
+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 $s { $($t)+ => {}, _ => todo!() }
+ | ++++++++++++++
+
+error[E0004]: non-exhaustive patterns: `_` not covered
+ --> $DIR/pointer-sized-int.rs:26:8
+ |
+LL | m!(0usize, 0..usize::MAX | usize::MAX);
+ | ^^^^^^ pattern `_` not covered
+ |
+ = note: the matched value is of type `usize`
+ = note: `usize` does not have a fixed maximum value, so a wildcard `_` is necessary to match exhaustively
+ = help: add `#![feature(precise_pointer_size_matching)]` to the crate attributes to enable precise `usize` matching
+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 $s { $($t)+ => {}, _ => todo!() }
+ | ++++++++++++++
+
+error[E0004]: non-exhaustive patterns: `(_, _)` not covered
+ --> $DIR/pointer-sized-int.rs:28:8
+ |
+LL | m!((0usize, true), (0..5, true) | (5..=usize::MAX, true) | (0..=usize::MAX, false));
+ | ^^^^^^^^^^^^^^ pattern `(_, _)` not covered
+ |
+ = note: the matched value is of type `(usize, bool)`
+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 $s { $($t)+ => {}, (_, _) => todo!() }
+ | +++++++++++++++++++
+
+error[E0004]: non-exhaustive patterns: `_` not covered
+ --> $DIR/pointer-sized-int.rs:31:8
+ |
+LL | m!(0isize, isize::MIN..=isize::MAX);
+ | ^^^^^^ pattern `_` not covered
+ |
+ = note: the matched value is of type `isize`
+ = note: `isize` does not have a fixed maximum value, so a wildcard `_` is necessary to match exhaustively
+ = help: add `#![feature(precise_pointer_size_matching)]` to the crate attributes to enable precise `isize` matching
+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 $s { $($t)+ => {}, _ => todo!() }
+ | ++++++++++++++
+
+error[E0004]: non-exhaustive patterns: `_` not covered
+ --> $DIR/pointer-sized-int.rs:33:8
+ |
+LL | m!(0isize, isize::MIN..5 | 5..=isize::MAX);
+ | ^^^^^^ pattern `_` not covered
+ |
+ = note: the matched value is of type `isize`
+ = note: `isize` does not have a fixed maximum value, so a wildcard `_` is necessary to match exhaustively
+ = help: add `#![feature(precise_pointer_size_matching)]` to the crate attributes to enable precise `isize` matching
+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 $s { $($t)+ => {}, _ => todo!() }
+ | ++++++++++++++
+
+error[E0004]: non-exhaustive patterns: `_` not covered
+ --> $DIR/pointer-sized-int.rs:35:8
+ |
+LL | m!(0isize, isize::MIN..isize::MAX | isize::MAX);
+ | ^^^^^^ pattern `_` not covered
+ |
+ = note: the matched value is of type `isize`
+ = note: `isize` does not have a fixed maximum value, so a wildcard `_` is necessary to match exhaustively
+ = help: add `#![feature(precise_pointer_size_matching)]` to the crate attributes to enable precise `isize` matching
+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 $s { $($t)+ => {}, _ => todo!() }
+ | ++++++++++++++
+
+error[E0004]: non-exhaustive patterns: `(_, _)` not covered
+ --> $DIR/pointer-sized-int.rs:37:8
+ |
+LL | m!((0isize, true), (isize::MIN..5, true)
+ | ^^^^^^^^^^^^^^ pattern `(_, _)` not covered
+ |
+ = note: the matched value is of type `(isize, bool)`
+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 $s { $($t)+ => {}, (_, _) => todo!() }
+ | +++++++++++++++++++
+
+error[E0004]: non-exhaustive patterns: `_` not covered
+ --> $DIR/pointer-sized-int.rs:41:11
+ |
+LL | match 0isize {
+ | ^^^^^^ pattern `_` not covered
+ |
+ = note: the matched value is of type `isize`
+ = note: `isize` does not have a fixed maximum value, so a wildcard `_` is necessary to match exhaustively
+ = help: add `#![feature(precise_pointer_size_matching)]` to the crate attributes to enable precise `isize` matching
+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 ~ 1 ..= isize::MAX => {}
+LL + _ => todo!()
+ |
+
+error[E0004]: non-exhaustive patterns: type `usize` is non-empty
+ --> $DIR/pointer-sized-int.rs:48:11
+ |
+LL | match 7usize {}
+ | ^^^^^^
+ |
+ = note: the matched value is of type `usize`
+help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern as shown
+ |
+LL ~ match 7usize {
+LL + _ => todo!(),
+LL + }
+ |
+
+error: aborting due to 12 previous errors
+
+For more information about this error, try `rustc --explain E0004`.
diff --git a/tests/ui/pattern/usefulness/integer-ranges/pointer-sized-int.rs b/tests/ui/pattern/usefulness/integer-ranges/pointer-sized-int.rs
new file mode 100644
index 000000000..1ed18c267
--- /dev/null
+++ b/tests/ui/pattern/usefulness/integer-ranges/pointer-sized-int.rs
@@ -0,0 +1,50 @@
+// revisions: allow deny
+#![feature(exclusive_range_pattern)]
+#![cfg_attr(allow, feature(precise_pointer_size_matching))]
+
+macro_rules! m {
+ ($s:expr, $($t:tt)+) => {
+ match $s { $($t)+ => {} }
+ }
+}
+
+fn main() {
+ match 0usize {
+ //[deny]~^ ERROR non-exhaustive patterns
+ 0 ..= usize::MAX => {}
+ }
+
+ match 0isize {
+ //[deny]~^ ERROR non-exhaustive patterns
+ isize::MIN ..= isize::MAX => {}
+ }
+
+ m!(0usize, 0..=usize::MAX);
+ //[deny]~^ ERROR non-exhaustive patterns
+ m!(0usize, 0..5 | 5..=usize::MAX);
+ //[deny]~^ ERROR non-exhaustive patterns
+ m!(0usize, 0..usize::MAX | usize::MAX);
+ //[deny]~^ ERROR non-exhaustive patterns
+ m!((0usize, true), (0..5, true) | (5..=usize::MAX, true) | (0..=usize::MAX, false));
+ //[deny]~^ ERROR non-exhaustive patterns
+
+ m!(0isize, isize::MIN..=isize::MAX);
+ //[deny]~^ ERROR non-exhaustive patterns
+ m!(0isize, isize::MIN..5 | 5..=isize::MAX);
+ //[deny]~^ ERROR non-exhaustive patterns
+ m!(0isize, isize::MIN..isize::MAX | isize::MAX);
+ //[deny]~^ ERROR non-exhaustive patterns
+ m!((0isize, true), (isize::MIN..5, true)
+ | (5..=isize::MAX, true) | (isize::MIN..=isize::MAX, false));
+ //[deny]~^^ ERROR non-exhaustive patterns
+
+ match 0isize {
+ //[deny]~^ ERROR non-exhaustive patterns
+ isize::MIN ..= -1 => {}
+ 0 => {}
+ 1 ..= isize::MAX => {}
+ }
+
+ match 7usize {}
+ //~^ ERROR non-exhaustive patterns
+}
diff --git a/tests/ui/pattern/usefulness/integer-ranges/precise_pointer_matching-message.rs b/tests/ui/pattern/usefulness/integer-ranges/precise_pointer_matching-message.rs
new file mode 100644
index 000000000..a2aa655ca
--- /dev/null
+++ b/tests/ui/pattern/usefulness/integer-ranges/precise_pointer_matching-message.rs
@@ -0,0 +1,18 @@
+// This tests that the lint message explains the reason for the error.
+fn main() {
+ match 0usize {
+ //~^ ERROR non-exhaustive patterns: `_` not covered
+ //~| NOTE pattern `_` not covered
+ //~| NOTE the matched value is of type `usize`
+ //~| NOTE `usize` does not have a fixed maximum value
+ 0..=usize::MAX => {}
+ }
+
+ match 0isize {
+ //~^ ERROR non-exhaustive patterns: `_` not covered
+ //~| NOTE pattern `_` not covered
+ //~| NOTE the matched value is of type `isize`
+ //~| NOTE `isize` does not have a fixed maximum value
+ isize::MIN..=isize::MAX => {}
+ }
+}
diff --git a/tests/ui/pattern/usefulness/integer-ranges/precise_pointer_matching-message.stderr b/tests/ui/pattern/usefulness/integer-ranges/precise_pointer_matching-message.stderr
new file mode 100644
index 000000000..30492c982
--- /dev/null
+++ b/tests/ui/pattern/usefulness/integer-ranges/precise_pointer_matching-message.stderr
@@ -0,0 +1,33 @@
+error[E0004]: non-exhaustive patterns: `_` not covered
+ --> $DIR/precise_pointer_matching-message.rs:3:11
+ |
+LL | match 0usize {
+ | ^^^^^^ pattern `_` not covered
+ |
+ = note: the matched value is of type `usize`
+ = note: `usize` does not have a fixed maximum value, so a wildcard `_` is necessary to match exhaustively
+ = help: add `#![feature(precise_pointer_size_matching)]` to the crate attributes to enable precise `usize` matching
+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 ~ 0..=usize::MAX => {}
+LL + _ => todo!()
+ |
+
+error[E0004]: non-exhaustive patterns: `_` not covered
+ --> $DIR/precise_pointer_matching-message.rs:11:11
+ |
+LL | match 0isize {
+ | ^^^^^^ pattern `_` not covered
+ |
+ = note: the matched value is of type `isize`
+ = note: `isize` does not have a fixed maximum value, so a wildcard `_` is necessary to match exhaustively
+ = help: add `#![feature(precise_pointer_size_matching)]` to the crate attributes to enable precise `isize` matching
+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 ~ isize::MIN..=isize::MAX => {}
+LL + _ => todo!()
+ |
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0004`.
diff --git a/tests/ui/pattern/usefulness/integer-ranges/reachability.rs b/tests/ui/pattern/usefulness/integer-ranges/reachability.rs
new file mode 100644
index 000000000..fb4d59b05
--- /dev/null
+++ b/tests/ui/pattern/usefulness/integer-ranges/reachability.rs
@@ -0,0 +1,113 @@
+#![feature(exclusive_range_pattern)]
+#![allow(overlapping_range_endpoints)]
+#![deny(unreachable_patterns)]
+
+macro_rules! m {
+ ($s:expr, $t1:pat, $t2:pat) => {
+ match $s {
+ $t1 => {}
+ $t2 => {}
+ _ => {}
+ }
+ }
+}
+
+fn main() {
+ m!(0u8, 42, 41);
+ m!(0u8, 42, 42); //~ ERROR unreachable pattern
+ m!(0u8, 42, 43);
+
+ m!(0u8, 20..=30, 19);
+ m!(0u8, 20..=30, 20); //~ ERROR unreachable pattern
+ m!(0u8, 20..=30, 21); //~ ERROR unreachable pattern
+ m!(0u8, 20..=30, 25); //~ ERROR unreachable pattern
+ m!(0u8, 20..=30, 29); //~ ERROR unreachable pattern
+ m!(0u8, 20..=30, 30); //~ ERROR unreachable pattern
+ m!(0u8, 20..=30, 31);
+ m!(0u8, 20..30, 19);
+ m!(0u8, 20..30, 20); //~ ERROR unreachable pattern
+ m!(0u8, 20..30, 21); //~ ERROR unreachable pattern
+ m!(0u8, 20..30, 25); //~ ERROR unreachable pattern
+ m!(0u8, 20..30, 29); //~ ERROR unreachable pattern
+ m!(0u8, 20..30, 30);
+ m!(0u8, 20..30, 31);
+
+ m!(0u8, 20..=30, 20..=30); //~ ERROR unreachable pattern
+ m!(0u8, 20.. 30, 20.. 30); //~ ERROR unreachable pattern
+ m!(0u8, 20..=30, 20.. 30); //~ ERROR unreachable pattern
+ m!(0u8, 20..=30, 19..=30);
+ m!(0u8, 20..=30, 21..=30); //~ ERROR unreachable pattern
+ m!(0u8, 20..=30, 20..=29); //~ ERROR unreachable pattern
+ m!(0u8, 20..=30, 20..=31);
+ m!('a', 'A'..='z', 'a'..='z'); //~ ERROR unreachable pattern
+
+ match 0u8 {
+ 5 => {},
+ 6 => {},
+ 7 => {},
+ 8 => {},
+ 5..=8 => {}, //~ ERROR unreachable pattern
+ _ => {},
+ }
+ match 0u8 {
+ 0..10 => {},
+ 10..20 => {},
+ 5..15 => {}, //~ ERROR unreachable pattern
+ _ => {},
+ }
+ match 0u8 {
+ 0..10 => {},
+ 10..20 => {},
+ 20..30 => {},
+ 5..25 => {}, //~ ERROR unreachable pattern
+ _ => {},
+ }
+ match 0u8 {
+ 0..10 => {},
+ 10 => {},
+ 11..=23 => {},
+ 19..30 => {},
+ 5..25 => {}, //~ ERROR unreachable pattern
+ _ => {},
+ }
+ match 0usize {
+ 0..10 => {},
+ 10..20 => {},
+ 5..15 => {}, //~ ERROR unreachable pattern
+ _ => {},
+ }
+ // Chars between '\u{D7FF}' and '\u{E000}' are invalid even though ranges that contain them are
+ // allowed.
+ match 'a' {
+ _ => {},
+ '\u{D7FF}'..='\u{E000}' => {}, //~ ERROR unreachable pattern
+ }
+ match 'a' {
+ '\u{0}'..='\u{D7FF}' => {},
+ '\u{E000}'..='\u{10_FFFF}' => {},
+ '\u{D7FF}'..='\u{E000}' => {}, // FIXME should be unreachable
+ }
+
+ match (0u8, true) {
+ (0..=255, false) => {}
+ (0..=255, true) => {} // ok
+ }
+ match (true, 0u8) {
+ (false, 0..=255) => {}
+ (true, 0..=255) => {} // ok
+ }
+
+ const FOO: i32 = 42;
+ const BAR: &i32 = &42;
+ match &0 {
+ &42 => {}
+ &FOO => {} //~ ERROR unreachable pattern
+ BAR => {} //~ ERROR unreachable pattern
+ _ => {}
+ }
+ // Regression test, see https://github.com/rust-lang/rust/pull/66326#issuecomment-552889933
+ match &0 {
+ BAR => {} // ok
+ _ => {}
+ }
+}
diff --git a/tests/ui/pattern/usefulness/integer-ranges/reachability.stderr b/tests/ui/pattern/usefulness/integer-ranges/reachability.stderr
new file mode 100644
index 000000000..0ffb0ffd8
--- /dev/null
+++ b/tests/ui/pattern/usefulness/integer-ranges/reachability.stderr
@@ -0,0 +1,154 @@
+error: unreachable pattern
+ --> $DIR/reachability.rs:17:17
+ |
+LL | m!(0u8, 42, 42);
+ | ^^
+ |
+note: the lint level is defined here
+ --> $DIR/reachability.rs:3:9
+ |
+LL | #![deny(unreachable_patterns)]
+ | ^^^^^^^^^^^^^^^^^^^^
+
+error: unreachable pattern
+ --> $DIR/reachability.rs:21:22
+ |
+LL | m!(0u8, 20..=30, 20);
+ | ^^
+
+error: unreachable pattern
+ --> $DIR/reachability.rs:22:22
+ |
+LL | m!(0u8, 20..=30, 21);
+ | ^^
+
+error: unreachable pattern
+ --> $DIR/reachability.rs:23:22
+ |
+LL | m!(0u8, 20..=30, 25);
+ | ^^
+
+error: unreachable pattern
+ --> $DIR/reachability.rs:24:22
+ |
+LL | m!(0u8, 20..=30, 29);
+ | ^^
+
+error: unreachable pattern
+ --> $DIR/reachability.rs:25:22
+ |
+LL | m!(0u8, 20..=30, 30);
+ | ^^
+
+error: unreachable pattern
+ --> $DIR/reachability.rs:28:21
+ |
+LL | m!(0u8, 20..30, 20);
+ | ^^
+
+error: unreachable pattern
+ --> $DIR/reachability.rs:29:21
+ |
+LL | m!(0u8, 20..30, 21);
+ | ^^
+
+error: unreachable pattern
+ --> $DIR/reachability.rs:30:21
+ |
+LL | m!(0u8, 20..30, 25);
+ | ^^
+
+error: unreachable pattern
+ --> $DIR/reachability.rs:31:21
+ |
+LL | m!(0u8, 20..30, 29);
+ | ^^
+
+error: unreachable pattern
+ --> $DIR/reachability.rs:35:22
+ |
+LL | m!(0u8, 20..=30, 20..=30);
+ | ^^^^^^^
+
+error: unreachable pattern
+ --> $DIR/reachability.rs:36:22
+ |
+LL | m!(0u8, 20.. 30, 20.. 30);
+ | ^^^^^^^
+
+error: unreachable pattern
+ --> $DIR/reachability.rs:37:22
+ |
+LL | m!(0u8, 20..=30, 20.. 30);
+ | ^^^^^^^
+
+error: unreachable pattern
+ --> $DIR/reachability.rs:39:22
+ |
+LL | m!(0u8, 20..=30, 21..=30);
+ | ^^^^^^^
+
+error: unreachable pattern
+ --> $DIR/reachability.rs:40:22
+ |
+LL | m!(0u8, 20..=30, 20..=29);
+ | ^^^^^^^
+
+error: unreachable pattern
+ --> $DIR/reachability.rs:42:24
+ |
+LL | m!('a', 'A'..='z', 'a'..='z');
+ | ^^^^^^^^^
+
+error: unreachable pattern
+ --> $DIR/reachability.rs:49:9
+ |
+LL | 5..=8 => {},
+ | ^^^^^
+
+error: unreachable pattern
+ --> $DIR/reachability.rs:55:9
+ |
+LL | 5..15 => {},
+ | ^^^^^
+
+error: unreachable pattern
+ --> $DIR/reachability.rs:62:9
+ |
+LL | 5..25 => {},
+ | ^^^^^
+
+error: unreachable pattern
+ --> $DIR/reachability.rs:70:9
+ |
+LL | 5..25 => {},
+ | ^^^^^
+
+error: unreachable pattern
+ --> $DIR/reachability.rs:76:9
+ |
+LL | 5..15 => {},
+ | ^^^^^
+
+error: unreachable pattern
+ --> $DIR/reachability.rs:83:9
+ |
+LL | _ => {},
+ | - matches any value
+LL | '\u{D7FF}'..='\u{E000}' => {},
+ | ^^^^^^^^^^^^^^^^^^^^^^^ unreachable pattern
+
+error: unreachable pattern
+ --> $DIR/reachability.rs:104:9
+ |
+LL | &FOO => {}
+ | ^^^^
+
+error: unreachable pattern
+ --> $DIR/reachability.rs:105:9
+ |
+LL | BAR => {}
+ | ^^^
+
+error: aborting due to 24 previous errors
+
diff --git a/tests/ui/pattern/usefulness/irrefutable-let-patterns.rs b/tests/ui/pattern/usefulness/irrefutable-let-patterns.rs
new file mode 100644
index 000000000..d400ef0bb
--- /dev/null
+++ b/tests/ui/pattern/usefulness/irrefutable-let-patterns.rs
@@ -0,0 +1,11 @@
+// run-pass
+
+#![allow(irrefutable_let_patterns)]
+
+fn main() {
+ if let _ = 5 {}
+
+ while let _ = 5 {
+ break;
+ }
+}
diff --git a/tests/ui/pattern/usefulness/irrefutable-unit.rs b/tests/ui/pattern/usefulness/irrefutable-unit.rs
new file mode 100644
index 000000000..dd8f03b6d
--- /dev/null
+++ b/tests/ui/pattern/usefulness/irrefutable-unit.rs
@@ -0,0 +1,6 @@
+// run-pass
+// pretty-expanded FIXME #23616
+
+pub fn main() {
+ let ((),()) = ((),());
+}
diff --git a/tests/ui/pattern/usefulness/issue-12116.rs b/tests/ui/pattern/usefulness/issue-12116.rs
new file mode 100644
index 000000000..3cb92a540
--- /dev/null
+++ b/tests/ui/pattern/usefulness/issue-12116.rs
@@ -0,0 +1,21 @@
+#![feature(box_patterns)]
+#![allow(dead_code)]
+#![allow(unused_variables)]
+#![deny(unreachable_patterns)]
+
+
+enum IntList {
+ Cons(isize, Box<IntList>),
+ Nil
+}
+
+fn tail(source_list: &IntList) -> IntList {
+ match source_list {
+ &IntList::Cons(val, box ref next_list) => tail(next_list),
+ &IntList::Cons(val, box IntList::Nil) => IntList::Cons(val, Box::new(IntList::Nil)),
+ //~^ ERROR unreachable pattern
+ _ => panic!(),
+ }
+}
+
+fn main() {}
diff --git a/tests/ui/pattern/usefulness/issue-12116.stderr b/tests/ui/pattern/usefulness/issue-12116.stderr
new file mode 100644
index 000000000..7f15c4703
--- /dev/null
+++ b/tests/ui/pattern/usefulness/issue-12116.stderr
@@ -0,0 +1,14 @@
+error: unreachable pattern
+ --> $DIR/issue-12116.rs:15:9
+ |
+LL | &IntList::Cons(val, box IntList::Nil) => IntList::Cons(val, Box::new(IntList::Nil)),
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+ |
+note: the lint level is defined here
+ --> $DIR/issue-12116.rs:4:9
+ |
+LL | #![deny(unreachable_patterns)]
+ | ^^^^^^^^^^^^^^^^^^^^
+
+error: aborting due to previous error
+
diff --git a/tests/ui/pattern/usefulness/issue-12369.rs b/tests/ui/pattern/usefulness/issue-12369.rs
new file mode 100644
index 000000000..0481c1fd9
--- /dev/null
+++ b/tests/ui/pattern/usefulness/issue-12369.rs
@@ -0,0 +1,11 @@
+#![deny(unreachable_patterns)]
+
+fn main() {
+ let sl = vec![1,2,3];
+ let v: isize = match &*sl {
+ &[] => 0,
+ &[a,b,c] => 3,
+ &[a, ref rest @ ..] => a,
+ &[10,a, ref rest @ ..] => 10 //~ ERROR: unreachable pattern
+ };
+}
diff --git a/tests/ui/pattern/usefulness/issue-12369.stderr b/tests/ui/pattern/usefulness/issue-12369.stderr
new file mode 100644
index 000000000..aab2be78c
--- /dev/null
+++ b/tests/ui/pattern/usefulness/issue-12369.stderr
@@ -0,0 +1,14 @@
+error: unreachable pattern
+ --> $DIR/issue-12369.rs:9:9
+ |
+LL | &[10,a, ref rest @ ..] => 10
+ | ^^^^^^^^^^^^^^^^^^^^^^
+ |
+note: the lint level is defined here
+ --> $DIR/issue-12369.rs:1:9
+ |
+LL | #![deny(unreachable_patterns)]
+ | ^^^^^^^^^^^^^^^^^^^^
+
+error: aborting due to previous error
+
diff --git a/tests/ui/pattern/usefulness/issue-13727.rs b/tests/ui/pattern/usefulness/issue-13727.rs
new file mode 100644
index 000000000..7fb565ef3
--- /dev/null
+++ b/tests/ui/pattern/usefulness/issue-13727.rs
@@ -0,0 +1,15 @@
+#![allow(overflowing_literals)]
+#![deny(unreachable_patterns)]
+
+fn test(val: u8) {
+ match val {
+ 256 => print!("0b1110\n"),
+ 512 => print!("0b1111\n"),
+ //~^ ERROR: unreachable pattern
+ _ => print!("fail\n"),
+ }
+}
+
+fn main() {
+ test(1);
+}
diff --git a/tests/ui/pattern/usefulness/issue-13727.stderr b/tests/ui/pattern/usefulness/issue-13727.stderr
new file mode 100644
index 000000000..07ca56a56
--- /dev/null
+++ b/tests/ui/pattern/usefulness/issue-13727.stderr
@@ -0,0 +1,14 @@
+error: unreachable pattern
+ --> $DIR/issue-13727.rs:7:5
+ |
+LL | 512 => print!("0b1111\n"),
+ | ^^^
+ |
+note: the lint level is defined here
+ --> $DIR/issue-13727.rs:2:9
+ |
+LL | #![deny(unreachable_patterns)]
+ | ^^^^^^^^^^^^^^^^^^^^
+
+error: aborting due to previous error
+
diff --git a/tests/ui/pattern/usefulness/issue-15129.rs b/tests/ui/pattern/usefulness/issue-15129.rs
new file mode 100644
index 000000000..f02e5c0c6
--- /dev/null
+++ b/tests/ui/pattern/usefulness/issue-15129.rs
@@ -0,0 +1,17 @@
+pub enum T {
+ T1(()),
+ T2(()),
+}
+
+pub enum V {
+ V1(isize),
+ V2(bool),
+}
+
+fn main() {
+ match (T::T1(()), V::V2(true)) {
+ //~^ ERROR non-exhaustive patterns: `(T::T1(()), V::V2(_))` and `(T::T2(()), V::V1(_))` not covered
+ (T::T1(()), V::V1(i)) => (),
+ (T::T2(()), V::V2(b)) => (),
+ }
+}
diff --git a/tests/ui/pattern/usefulness/issue-15129.stderr b/tests/ui/pattern/usefulness/issue-15129.stderr
new file mode 100644
index 000000000..ee8410b76
--- /dev/null
+++ b/tests/ui/pattern/usefulness/issue-15129.stderr
@@ -0,0 +1,16 @@
+error[E0004]: non-exhaustive patterns: `(T::T1(()), V::V2(_))` and `(T::T2(()), V::V1(_))` not covered
+ --> $DIR/issue-15129.rs:12:11
+ |
+LL | match (T::T1(()), V::V2(true)) {
+ | ^^^^^^^^^^^^^^^^^^^^^^^^ patterns `(T::T1(()), V::V2(_))` and `(T::T2(()), V::V1(_))` not covered
+ |
+ = note: the matched value is of type `(T, V)`
+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 ~ (T::T2(()), V::V2(b)) => (),
+LL ~ (T::T1(()), V::V2(_)) | (T::T2(()), V::V1(_)) => todo!(),
+ |
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0004`.
diff --git a/tests/ui/pattern/usefulness/issue-2111.rs b/tests/ui/pattern/usefulness/issue-2111.rs
new file mode 100644
index 000000000..d27beaeff
--- /dev/null
+++ b/tests/ui/pattern/usefulness/issue-2111.rs
@@ -0,0 +1,11 @@
+fn foo(a: Option<usize>, b: Option<usize>) {
+ match (a, b) {
+ //~^ ERROR: non-exhaustive patterns: `(None, None)` and `(Some(_), Some(_))` not covered
+ (Some(a), Some(b)) if a == b => {}
+ (Some(_), None) | (None, Some(_)) => {}
+ }
+}
+
+fn main() {
+ foo(None, None);
+}
diff --git a/tests/ui/pattern/usefulness/issue-2111.stderr b/tests/ui/pattern/usefulness/issue-2111.stderr
new file mode 100644
index 000000000..01890b73c
--- /dev/null
+++ b/tests/ui/pattern/usefulness/issue-2111.stderr
@@ -0,0 +1,16 @@
+error[E0004]: non-exhaustive patterns: `(None, None)` and `(Some(_), Some(_))` not covered
+ --> $DIR/issue-2111.rs:2:11
+ |
+LL | match (a, b) {
+ | ^^^^^^ patterns `(None, None)` and `(Some(_), Some(_))` not covered
+ |
+ = note: the matched value is of type `(Option<usize>, Option<usize>)`
+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 ~ (Some(_), None) | (None, Some(_)) => {}
+LL + (None, None) | (Some(_), Some(_)) => todo!()
+ |
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0004`.
diff --git a/tests/ui/pattern/usefulness/issue-30240-b.rs b/tests/ui/pattern/usefulness/issue-30240-b.rs
new file mode 100644
index 000000000..01a6e7d8c
--- /dev/null
+++ b/tests/ui/pattern/usefulness/issue-30240-b.rs
@@ -0,0 +1,15 @@
+#![deny(unreachable_patterns)]
+
+fn main() {
+ match "world" {
+ "hello" => {}
+ _ => {},
+ }
+
+ match "world" {
+ ref _x if false => {}
+ "hello" => {}
+ "hello" => {} //~ ERROR unreachable pattern
+ _ => {},
+ }
+}
diff --git a/tests/ui/pattern/usefulness/issue-30240-b.stderr b/tests/ui/pattern/usefulness/issue-30240-b.stderr
new file mode 100644
index 000000000..59d64bc25
--- /dev/null
+++ b/tests/ui/pattern/usefulness/issue-30240-b.stderr
@@ -0,0 +1,14 @@
+error: unreachable pattern
+ --> $DIR/issue-30240-b.rs:12:9
+ |
+LL | "hello" => {}
+ | ^^^^^^^
+ |
+note: the lint level is defined here
+ --> $DIR/issue-30240-b.rs:1:9
+ |
+LL | #![deny(unreachable_patterns)]
+ | ^^^^^^^^^^^^^^^^^^^^
+
+error: aborting due to previous error
+
diff --git a/tests/ui/pattern/usefulness/issue-30240-rpass.rs b/tests/ui/pattern/usefulness/issue-30240-rpass.rs
new file mode 100644
index 000000000..ab16614fd
--- /dev/null
+++ b/tests/ui/pattern/usefulness/issue-30240-rpass.rs
@@ -0,0 +1,14 @@
+// run-pass
+fn main() {
+ let &ref a = &[0i32] as &[_];
+ assert_eq!(a, &[0i32] as &[_]);
+
+ let &ref a = "hello";
+ assert_eq!(a, "hello");
+
+ match "foo" {
+ "fool" => unreachable!(),
+ "foo" => {},
+ ref _x => unreachable!()
+ }
+}
diff --git a/tests/ui/pattern/usefulness/issue-30240.rs b/tests/ui/pattern/usefulness/issue-30240.rs
new file mode 100644
index 000000000..a0c0d1626
--- /dev/null
+++ b/tests/ui/pattern/usefulness/issue-30240.rs
@@ -0,0 +1,10 @@
+fn main() {
+ match "world" { //~ ERROR non-exhaustive patterns: `&_`
+ "hello" => {}
+ }
+
+ match "world" { //~ ERROR non-exhaustive patterns: `&_`
+ ref _x if false => {}
+ "hello" => {}
+ }
+}
diff --git a/tests/ui/pattern/usefulness/issue-30240.stderr b/tests/ui/pattern/usefulness/issue-30240.stderr
new file mode 100644
index 000000000..759fdeafe
--- /dev/null
+++ b/tests/ui/pattern/usefulness/issue-30240.stderr
@@ -0,0 +1,29 @@
+error[E0004]: non-exhaustive patterns: `&_` not covered
+ --> $DIR/issue-30240.rs:2:11
+ |
+LL | match "world" {
+ | ^^^^^^^ pattern `&_` not covered
+ |
+ = note: the matched value is of type `&str`
+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 ~ "hello" => {}
+LL + &_ => todo!()
+ |
+
+error[E0004]: non-exhaustive patterns: `&_` not covered
+ --> $DIR/issue-30240.rs:6:11
+ |
+LL | match "world" {
+ | ^^^^^^^ pattern `&_` not covered
+ |
+ = note: the matched value is of type `&str`
+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 ~ "hello" => {}
+LL + &_ => todo!()
+ |
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0004`.
diff --git a/tests/ui/pattern/usefulness/issue-3096-1.rs b/tests/ui/pattern/usefulness/issue-3096-1.rs
new file mode 100644
index 000000000..edc3b3223
--- /dev/null
+++ b/tests/ui/pattern/usefulness/issue-3096-1.rs
@@ -0,0 +1,3 @@
+fn main() {
+ match () { } //~ ERROR non-exhaustive
+}
diff --git a/tests/ui/pattern/usefulness/issue-3096-1.stderr b/tests/ui/pattern/usefulness/issue-3096-1.stderr
new file mode 100644
index 000000000..d8884394f
--- /dev/null
+++ b/tests/ui/pattern/usefulness/issue-3096-1.stderr
@@ -0,0 +1,17 @@
+error[E0004]: non-exhaustive patterns: type `()` is non-empty
+ --> $DIR/issue-3096-1.rs:2:11
+ |
+LL | match () { }
+ | ^^
+ |
+ = note: the matched value is of type `()`
+help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern as shown
+ |
+LL ~ match () {
+LL + _ => todo!(),
+LL ~ }
+ |
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0004`.
diff --git a/tests/ui/pattern/usefulness/issue-3096-2.rs b/tests/ui/pattern/usefulness/issue-3096-2.rs
new file mode 100644
index 000000000..a26e42580
--- /dev/null
+++ b/tests/ui/pattern/usefulness/issue-3096-2.rs
@@ -0,0 +1,6 @@
+enum Bottom { }
+
+fn main() {
+ let x = &() as *const () as *const Bottom;
+ match x { } //~ ERROR non-exhaustive patterns
+}
diff --git a/tests/ui/pattern/usefulness/issue-3096-2.stderr b/tests/ui/pattern/usefulness/issue-3096-2.stderr
new file mode 100644
index 000000000..2df8911ba
--- /dev/null
+++ b/tests/ui/pattern/usefulness/issue-3096-2.stderr
@@ -0,0 +1,17 @@
+error[E0004]: non-exhaustive patterns: type `*const Bottom` is non-empty
+ --> $DIR/issue-3096-2.rs:5:11
+ |
+LL | match x { }
+ | ^
+ |
+ = note: the matched value is of type `*const Bottom`
+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 previous error
+
+For more information about this error, try `rustc --explain E0004`.
diff --git a/tests/ui/pattern/usefulness/issue-31221.rs b/tests/ui/pattern/usefulness/issue-31221.rs
new file mode 100644
index 000000000..e03f1ec5b
--- /dev/null
+++ b/tests/ui/pattern/usefulness/issue-31221.rs
@@ -0,0 +1,34 @@
+#![allow(dead_code)]
+#![allow(unused_variables)]
+#![allow(non_snake_case)]
+#![deny(unreachable_patterns)]
+
+#[derive(Clone, Copy)]
+enum Enum {
+ Var1,
+ Var2,
+}
+
+fn main() {
+ use Enum::*;
+ let s = Var1;
+ match s {
+ Var1 => (),
+ Var3 => (),
+ Var2 => (),
+ //~^ ERROR unreachable pattern
+ };
+ match &s {
+ &Var1 => (),
+ &Var3 => (),
+ &Var2 => (),
+ //~^ ERROR unreachable pattern
+ };
+ let t = (Var1, Var1);
+ match t {
+ (Var1, b) => (),
+ (c, d) => (),
+ anything => ()
+ //~^ ERROR unreachable pattern
+ };
+}
diff --git a/tests/ui/pattern/usefulness/issue-31221.stderr b/tests/ui/pattern/usefulness/issue-31221.stderr
new file mode 100644
index 000000000..7d3491444
--- /dev/null
+++ b/tests/ui/pattern/usefulness/issue-31221.stderr
@@ -0,0 +1,32 @@
+error: unreachable pattern
+ --> $DIR/issue-31221.rs:18:9
+ |
+LL | Var3 => (),
+ | ---- matches any value
+LL | Var2 => (),
+ | ^^^^ unreachable pattern
+ |
+note: the lint level is defined here
+ --> $DIR/issue-31221.rs:4:9
+ |
+LL | #![deny(unreachable_patterns)]
+ | ^^^^^^^^^^^^^^^^^^^^
+
+error: unreachable pattern
+ --> $DIR/issue-31221.rs:24:9
+ |
+LL | &Var3 => (),
+ | ----- matches any value
+LL | &Var2 => (),
+ | ^^^^^ unreachable pattern
+
+error: unreachable pattern
+ --> $DIR/issue-31221.rs:31:9
+ |
+LL | (c, d) => (),
+ | ------ matches any value
+LL | anything => ()
+ | ^^^^^^^^ unreachable pattern
+
+error: aborting due to 3 previous errors
+
diff --git a/tests/ui/pattern/usefulness/issue-31561.rs b/tests/ui/pattern/usefulness/issue-31561.rs
new file mode 100644
index 000000000..82414f041
--- /dev/null
+++ b/tests/ui/pattern/usefulness/issue-31561.rs
@@ -0,0 +1,11 @@
+enum Thing {
+ Foo(u8),
+ Bar,
+ Baz
+}
+
+fn main() {
+ let Thing::Foo(y) = Thing::Foo(1);
+ //~^ ERROR refutable pattern in local binding
+ //~| `Thing::Bar` and `Thing::Baz` not covered
+}
diff --git a/tests/ui/pattern/usefulness/issue-31561.stderr b/tests/ui/pattern/usefulness/issue-31561.stderr
new file mode 100644
index 000000000..5367de5e5
--- /dev/null
+++ b/tests/ui/pattern/usefulness/issue-31561.stderr
@@ -0,0 +1,27 @@
+error[E0005]: refutable pattern in local binding
+ --> $DIR/issue-31561.rs:8:9
+ |
+LL | let Thing::Foo(y) = Thing::Foo(1);
+ | ^^^^^^^^^^^^^ patterns `Thing::Bar` and `Thing::Baz` not covered
+ |
+ = note: `let` bindings require an "irrefutable pattern", like a `struct` or an `enum` with only one variant
+ = note: for more information, visit https://doc.rust-lang.org/book/ch18-02-refutability.html
+note: `Thing` defined here
+ --> $DIR/issue-31561.rs:1:6
+ |
+LL | enum Thing {
+ | ^^^^^
+LL | Foo(u8),
+LL | Bar,
+ | --- not covered
+LL | Baz
+ | --- not covered
+ = note: the matched value is of type `Thing`
+help: you might want to use `let else` to handle the variants that aren't matched
+ |
+LL | let Thing::Foo(y) = Thing::Foo(1) else { todo!() };
+ | ++++++++++++++++
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0005`.
diff --git a/tests/ui/pattern/usefulness/issue-35609.rs b/tests/ui/pattern/usefulness/issue-35609.rs
new file mode 100644
index 000000000..8ef75e351
--- /dev/null
+++ b/tests/ui/pattern/usefulness/issue-35609.rs
@@ -0,0 +1,43 @@
+enum Enum {
+ A, B, C, D, E, F
+}
+use Enum::*;
+
+struct S(Enum, ());
+struct Sd { x: Enum, y: () }
+
+fn main() {
+ match (A, ()) { //~ ERROR non-exhaustive
+ (A, _) => {}
+ }
+
+ match (A, A) { //~ ERROR non-exhaustive
+ (_, A) => {}
+ }
+
+ match ((A, ()), ()) { //~ ERROR non-exhaustive
+ ((A, ()), _) => {}
+ }
+
+ match ((A, ()), A) { //~ ERROR non-exhaustive
+ ((A, ()), _) => {}
+ }
+
+ match ((A, ()), ()) { //~ ERROR non-exhaustive
+ ((A, _), _) => {}
+ }
+
+
+ match S(A, ()) { //~ ERROR non-exhaustive
+ S(A, _) => {}
+ }
+
+ match (Sd { x: A, y: () }) { //~ ERROR non-exhaustive
+ Sd { x: A, y: _ } => {}
+ }
+
+ match Some(A) { //~ ERROR non-exhaustive
+ Some(A) => (),
+ None => ()
+ }
+}
diff --git a/tests/ui/pattern/usefulness/issue-35609.stderr b/tests/ui/pattern/usefulness/issue-35609.stderr
new file mode 100644
index 000000000..12113957d
--- /dev/null
+++ b/tests/ui/pattern/usefulness/issue-35609.stderr
@@ -0,0 +1,119 @@
+error[E0004]: non-exhaustive patterns: `(Enum::B, _)`, `(Enum::C, _)`, `(Enum::D, _)` and 2 more not covered
+ --> $DIR/issue-35609.rs:10:11
+ |
+LL | match (A, ()) {
+ | ^^^^^^^ patterns `(Enum::B, _)`, `(Enum::C, _)`, `(Enum::D, _)` and 2 more not covered
+ |
+ = note: the matched value is of type `(Enum, ())`
+help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern as shown, or multiple match arms
+ |
+LL ~ (A, _) => {}
+LL + _ => todo!()
+ |
+
+error[E0004]: non-exhaustive patterns: `(_, Enum::B)`, `(_, Enum::C)`, `(_, Enum::D)` and 2 more not covered
+ --> $DIR/issue-35609.rs:14:11
+ |
+LL | match (A, A) {
+ | ^^^^^^ patterns `(_, Enum::B)`, `(_, Enum::C)`, `(_, Enum::D)` and 2 more not covered
+ |
+ = note: the matched value is of type `(Enum, Enum)`
+help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern as shown, or multiple match arms
+ |
+LL ~ (_, A) => {}
+LL + _ => todo!()
+ |
+
+error[E0004]: non-exhaustive patterns: `((Enum::B, _), _)`, `((Enum::C, _), _)`, `((Enum::D, _), _)` and 2 more not covered
+ --> $DIR/issue-35609.rs:18:11
+ |
+LL | match ((A, ()), ()) {
+ | ^^^^^^^^^^^^^ patterns `((Enum::B, _), _)`, `((Enum::C, _), _)`, `((Enum::D, _), _)` and 2 more not covered
+ |
+ = note: the matched value is of type `((Enum, ()), ())`
+help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern as shown, or multiple match arms
+ |
+LL ~ ((A, ()), _) => {}
+LL + _ => todo!()
+ |
+
+error[E0004]: non-exhaustive patterns: `((Enum::B, _), _)`, `((Enum::C, _), _)`, `((Enum::D, _), _)` and 2 more not covered
+ --> $DIR/issue-35609.rs:22:11
+ |
+LL | match ((A, ()), A) {
+ | ^^^^^^^^^^^^ patterns `((Enum::B, _), _)`, `((Enum::C, _), _)`, `((Enum::D, _), _)` and 2 more not covered
+ |
+ = note: the matched value is of type `((Enum, ()), Enum)`
+help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern as shown, or multiple match arms
+ |
+LL ~ ((A, ()), _) => {}
+LL + _ => todo!()
+ |
+
+error[E0004]: non-exhaustive patterns: `((Enum::B, _), _)`, `((Enum::C, _), _)`, `((Enum::D, _), _)` and 2 more not covered
+ --> $DIR/issue-35609.rs:26:11
+ |
+LL | match ((A, ()), ()) {
+ | ^^^^^^^^^^^^^ patterns `((Enum::B, _), _)`, `((Enum::C, _), _)`, `((Enum::D, _), _)` and 2 more not covered
+ |
+ = note: the matched value is of type `((Enum, ()), ())`
+help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern as shown, or multiple match arms
+ |
+LL ~ ((A, _), _) => {}
+LL + _ => todo!()
+ |
+
+error[E0004]: non-exhaustive patterns: `S(Enum::B, _)`, `S(Enum::C, _)`, `S(Enum::D, _)` and 2 more not covered
+ --> $DIR/issue-35609.rs:31:11
+ |
+LL | match S(A, ()) {
+ | ^^^^^^^^ patterns `S(Enum::B, _)`, `S(Enum::C, _)`, `S(Enum::D, _)` and 2 more not covered
+ |
+note: `S` defined here
+ --> $DIR/issue-35609.rs:6:8
+ |
+LL | struct S(Enum, ());
+ | ^
+ = note: the matched value is of type `S`
+help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern as shown, or multiple match arms
+ |
+LL ~ S(A, _) => {}
+LL + _ => todo!()
+ |
+
+error[E0004]: non-exhaustive patterns: `Sd { x: Enum::B, .. }`, `Sd { x: Enum::C, .. }`, `Sd { x: Enum::D, .. }` and 2 more not covered
+ --> $DIR/issue-35609.rs:35:11
+ |
+LL | match (Sd { x: A, y: () }) {
+ | ^^^^^^^^^^^^^^^^^^^^ patterns `Sd { x: Enum::B, .. }`, `Sd { x: Enum::C, .. }`, `Sd { x: Enum::D, .. }` and 2 more not covered
+ |
+note: `Sd` defined here
+ --> $DIR/issue-35609.rs:7:8
+ |
+LL | struct Sd { x: Enum, y: () }
+ | ^^
+ = note: the matched value is of type `Sd`
+help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern as shown, or multiple match arms
+ |
+LL ~ Sd { x: A, y: _ } => {}
+LL + _ => todo!()
+ |
+
+error[E0004]: non-exhaustive patterns: `Some(Enum::B)`, `Some(Enum::C)`, `Some(Enum::D)` and 2 more not covered
+ --> $DIR/issue-35609.rs:39:11
+ |
+LL | match Some(A) {
+ | ^^^^^^^ patterns `Some(Enum::B)`, `Some(Enum::C)`, `Some(Enum::D)` and 2 more not covered
+ |
+note: `Option<Enum>` defined here
+ --> $SRC_DIR/core/src/option.rs:LL:COL
+ = note: the matched value is of type `Option<Enum>`
+help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern as shown, or multiple match arms
+ |
+LL ~ None => (),
+LL + _ => todo!()
+ |
+
+error: aborting due to 8 previous errors
+
+For more information about this error, try `rustc --explain E0004`.
diff --git a/tests/ui/pattern/usefulness/issue-3601.rs b/tests/ui/pattern/usefulness/issue-3601.rs
new file mode 100644
index 000000000..6215a2398
--- /dev/null
+++ b/tests/ui/pattern/usefulness/issue-3601.rs
@@ -0,0 +1,34 @@
+#![feature(box_patterns)]
+
+struct HTMLImageData {
+ image: Option<String>
+}
+
+struct ElementData {
+ kind: Box<ElementKind>
+}
+
+enum ElementKind {
+ HTMLImageElement(HTMLImageData)
+}
+
+enum NodeKind {
+ Element(ElementData)
+}
+
+struct NodeData {
+ kind: Box<NodeKind>,
+}
+
+fn main() {
+ let mut id = HTMLImageData { image: None };
+ let ed = ElementData { kind: Box::new(ElementKind::HTMLImageElement(id)) };
+ let n = NodeData { kind: Box::new(NodeKind::Element(ed)) };
+
+ // n.b. span could be better
+ match n.kind {
+ box NodeKind::Element(ed) => match ed.kind { //~ ERROR non-exhaustive patterns
+ box ElementKind::HTMLImageElement(ref d) if d.image.is_some() => { true }
+ },
+ };
+}
diff --git a/tests/ui/pattern/usefulness/issue-3601.stderr b/tests/ui/pattern/usefulness/issue-3601.stderr
new file mode 100644
index 000000000..59d7bcd4b
--- /dev/null
+++ b/tests/ui/pattern/usefulness/issue-3601.stderr
@@ -0,0 +1,18 @@
+error[E0004]: non-exhaustive patterns: `box _` not covered
+ --> $DIR/issue-3601.rs:30:44
+ |
+LL | box NodeKind::Element(ed) => match ed.kind {
+ | ^^^^^^^ pattern `box _` not covered
+ |
+note: `Box<ElementKind>` defined here
+ --> $SRC_DIR/alloc/src/boxed.rs:LL:COL
+ = note: the matched value is of type `Box<ElementKind>`
+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 ~ box ElementKind::HTMLImageElement(ref d) if d.image.is_some() => { true }
+LL + box _ => todo!()
+ |
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0004`.
diff --git a/tests/ui/pattern/usefulness/issue-39362.rs b/tests/ui/pattern/usefulness/issue-39362.rs
new file mode 100644
index 000000000..ea3c8f88e
--- /dev/null
+++ b/tests/ui/pattern/usefulness/issue-39362.rs
@@ -0,0 +1,18 @@
+enum Foo {
+ Bar { bar: Bar, id: usize }
+}
+
+enum Bar {
+ A, B, C, D, E, F
+}
+
+fn test(f: Foo) {
+ match f {
+ //~^ ERROR non-exhaustive patterns
+ //~| patterns
+ Foo::Bar { bar: Bar::A, .. } => (),
+ Foo::Bar { bar: Bar::B, .. } => (),
+ }
+}
+
+fn main() {}
diff --git a/tests/ui/pattern/usefulness/issue-39362.stderr b/tests/ui/pattern/usefulness/issue-39362.stderr
new file mode 100644
index 000000000..b8b17918a
--- /dev/null
+++ b/tests/ui/pattern/usefulness/issue-39362.stderr
@@ -0,0 +1,23 @@
+error[E0004]: non-exhaustive patterns: `Foo::Bar { bar: Bar::C, .. }`, `Foo::Bar { bar: Bar::D, .. }`, `Foo::Bar { bar: Bar::E, .. }` and 1 more not covered
+ --> $DIR/issue-39362.rs:10:11
+ |
+LL | match f {
+ | ^ patterns `Foo::Bar { bar: Bar::C, .. }`, `Foo::Bar { bar: Bar::D, .. }`, `Foo::Bar { bar: Bar::E, .. }` and 1 more not covered
+ |
+note: `Foo` defined here
+ --> $DIR/issue-39362.rs:2:5
+ |
+LL | enum Foo {
+ | ---
+LL | Bar { bar: Bar, id: usize }
+ | ^^^ not covered
+ = note: the matched value is of type `Foo`
+help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern as shown, or multiple match arms
+ |
+LL ~ Foo::Bar { bar: Bar::B, .. } => (),
+LL ~ _ => todo!(),
+ |
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0004`.
diff --git a/tests/ui/pattern/usefulness/issue-40221.rs b/tests/ui/pattern/usefulness/issue-40221.rs
new file mode 100644
index 000000000..e1f7e975b
--- /dev/null
+++ b/tests/ui/pattern/usefulness/issue-40221.rs
@@ -0,0 +1,16 @@
+enum P {
+ C(PC),
+}
+
+enum PC {
+ Q,
+ QA,
+}
+
+fn test(proto: P) {
+ match proto { //~ ERROR non-exhaustive patterns
+ P::C(PC::Q) => (),
+ }
+}
+
+fn main() {}
diff --git a/tests/ui/pattern/usefulness/issue-40221.stderr b/tests/ui/pattern/usefulness/issue-40221.stderr
new file mode 100644
index 000000000..4973e42b0
--- /dev/null
+++ b/tests/ui/pattern/usefulness/issue-40221.stderr
@@ -0,0 +1,23 @@
+error[E0004]: non-exhaustive patterns: `P::C(PC::QA)` not covered
+ --> $DIR/issue-40221.rs:11:11
+ |
+LL | match proto {
+ | ^^^^^ pattern `P::C(PC::QA)` not covered
+ |
+note: `P` defined here
+ --> $DIR/issue-40221.rs:2:5
+ |
+LL | enum P {
+ | -
+LL | C(PC),
+ | ^ not covered
+ = note: the matched value is of type `P`
+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 ~ P::C(PC::Q) => (),
+LL ~ P::C(PC::QA) => todo!(),
+ |
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0004`.
diff --git a/tests/ui/pattern/usefulness/issue-4321.rs b/tests/ui/pattern/usefulness/issue-4321.rs
new file mode 100644
index 000000000..9715f2eba
--- /dev/null
+++ b/tests/ui/pattern/usefulness/issue-4321.rs
@@ -0,0 +1,8 @@
+fn main() {
+ let tup = (true, true);
+ println!("foo {:}", match tup { //~ ERROR non-exhaustive patterns: `(true, false)` not covered
+ (false, false) => "foo",
+ (false, true) => "bar",
+ (true, true) => "baz"
+ });
+}
diff --git a/tests/ui/pattern/usefulness/issue-4321.stderr b/tests/ui/pattern/usefulness/issue-4321.stderr
new file mode 100644
index 000000000..293273174
--- /dev/null
+++ b/tests/ui/pattern/usefulness/issue-4321.stderr
@@ -0,0 +1,16 @@
+error[E0004]: non-exhaustive patterns: `(true, false)` not covered
+ --> $DIR/issue-4321.rs:3:31
+ |
+LL | println!("foo {:}", match tup {
+ | ^^^ pattern `(true, false)` not covered
+ |
+ = note: the matched value is of type `(bool, bool)`
+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 ~ (true, true) => "baz",
+LL + (true, false) => todo!()
+ |
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0004`.
diff --git a/tests/ui/pattern/usefulness/issue-50900.rs b/tests/ui/pattern/usefulness/issue-50900.rs
new file mode 100644
index 000000000..9cc760e9a
--- /dev/null
+++ b/tests/ui/pattern/usefulness/issue-50900.rs
@@ -0,0 +1,19 @@
+#[derive(PartialEq, Eq)]
+pub struct Tag(pub Context, pub u16);
+
+#[derive(PartialEq, Eq)]
+pub enum Context {
+ Tiff,
+ Exif,
+}
+
+impl Tag {
+ const ExifIFDPointer: Tag = Tag(Context::Tiff, 34665);
+}
+
+fn main() {
+ match Tag::ExifIFDPointer {
+ //~^ ERROR: non-exhaustive patterns: `Tag(Context::Exif, _)` not covered
+ Tag::ExifIFDPointer => {}
+ }
+}
diff --git a/tests/ui/pattern/usefulness/issue-50900.stderr b/tests/ui/pattern/usefulness/issue-50900.stderr
new file mode 100644
index 000000000..348246d28
--- /dev/null
+++ b/tests/ui/pattern/usefulness/issue-50900.stderr
@@ -0,0 +1,21 @@
+error[E0004]: non-exhaustive patterns: `Tag(Context::Exif, _)` not covered
+ --> $DIR/issue-50900.rs:15:11
+ |
+LL | match Tag::ExifIFDPointer {
+ | ^^^^^^^^^^^^^^^^^^^ pattern `Tag(Context::Exif, _)` not covered
+ |
+note: `Tag` defined here
+ --> $DIR/issue-50900.rs:2:12
+ |
+LL | pub struct Tag(pub Context, pub u16);
+ | ^^^
+ = note: the matched value is of type `Tag`
+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 ~ Tag::ExifIFDPointer => {}
+LL + Tag(Context::Exif, _) => todo!()
+ |
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0004`.
diff --git a/tests/ui/pattern/usefulness/issue-53820-slice-pattern-large-array.rs b/tests/ui/pattern/usefulness/issue-53820-slice-pattern-large-array.rs
new file mode 100644
index 000000000..5b0482de2
--- /dev/null
+++ b/tests/ui/pattern/usefulness/issue-53820-slice-pattern-large-array.rs
@@ -0,0 +1,11 @@
+// check-pass
+
+// This used to cause a stack overflow during exhaustiveness checking in the compiler.
+
+fn main() {
+ const LARGE_SIZE: usize = 1024 * 1024;
+ let [..] = [0u8; LARGE_SIZE];
+ match [0u8; LARGE_SIZE] {
+ [..] => {}
+ }
+}
diff --git a/tests/ui/pattern/usefulness/issue-56379.rs b/tests/ui/pattern/usefulness/issue-56379.rs
new file mode 100644
index 000000000..097cf98d0
--- /dev/null
+++ b/tests/ui/pattern/usefulness/issue-56379.rs
@@ -0,0 +1,14 @@
+enum Foo {
+ A(bool),
+ B(bool),
+ C(bool),
+}
+
+fn main() {
+ match Foo::A(true) {
+ //~^ ERROR non-exhaustive patterns: `Foo::A(false)`, `Foo::B(false)` and `Foo::C(false)` not covered
+ Foo::A(true) => {}
+ Foo::B(true) => {}
+ Foo::C(true) => {}
+ }
+}
diff --git a/tests/ui/pattern/usefulness/issue-56379.stderr b/tests/ui/pattern/usefulness/issue-56379.stderr
new file mode 100644
index 000000000..6eed6bfae
--- /dev/null
+++ b/tests/ui/pattern/usefulness/issue-56379.stderr
@@ -0,0 +1,27 @@
+error[E0004]: non-exhaustive patterns: `Foo::A(false)`, `Foo::B(false)` and `Foo::C(false)` not covered
+ --> $DIR/issue-56379.rs:8:11
+ |
+LL | match Foo::A(true) {
+ | ^^^^^^^^^^^^ patterns `Foo::A(false)`, `Foo::B(false)` and `Foo::C(false)` not covered
+ |
+note: `Foo` defined here
+ --> $DIR/issue-56379.rs:2:5
+ |
+LL | enum Foo {
+ | ---
+LL | A(bool),
+ | ^ not covered
+LL | B(bool),
+ | ^ not covered
+LL | C(bool),
+ | ^ not covered
+ = note: the matched value is of type `Foo`
+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 ~ Foo::C(true) => {}
+LL + Foo::A(false) | Foo::B(false) | Foo::C(false) => todo!()
+ |
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0004`.
diff --git a/tests/ui/pattern/usefulness/issue-57472.rs b/tests/ui/pattern/usefulness/issue-57472.rs
new file mode 100644
index 000000000..113100637
--- /dev/null
+++ b/tests/ui/pattern/usefulness/issue-57472.rs
@@ -0,0 +1,35 @@
+#![crate_type="lib"]
+#![deny(unreachable_patterns)]
+
+mod test_struct {
+ // Test the exact copy of the minimal example
+ // posted in the issue.
+ pub struct Punned {
+ foo: [u8; 1],
+ bar: [u8; 1],
+ }
+
+ pub fn test(punned: Punned) {
+ match punned {
+ Punned { foo: [_], .. } => println!("foo"),
+ Punned { bar: [_], .. } => println!("bar"),
+ //~^ ERROR unreachable pattern [unreachable_patterns]
+ }
+ }
+}
+
+mod test_union {
+ // Test the same thing using a union.
+ pub union Punned {
+ foo: [u8; 1],
+ bar: [u8; 1],
+ }
+
+ pub fn test(punned: Punned) {
+ match punned {
+ Punned { foo: [_] } => println!("foo"),
+ Punned { bar: [_] } => println!("bar"),
+ //~^ ERROR unreachable pattern [unreachable_patterns]
+ }
+ }
+}
diff --git a/tests/ui/pattern/usefulness/issue-57472.stderr b/tests/ui/pattern/usefulness/issue-57472.stderr
new file mode 100644
index 000000000..26efdf6db
--- /dev/null
+++ b/tests/ui/pattern/usefulness/issue-57472.stderr
@@ -0,0 +1,20 @@
+error: unreachable pattern
+ --> $DIR/issue-57472.rs:15:13
+ |
+LL | Punned { bar: [_], .. } => println!("bar"),
+ | ^^^^^^^^^^^^^^^^^^^^^^^
+ |
+note: the lint level is defined here
+ --> $DIR/issue-57472.rs:2:9
+ |
+LL | #![deny(unreachable_patterns)]
+ | ^^^^^^^^^^^^^^^^^^^^
+
+error: unreachable pattern
+ --> $DIR/issue-57472.rs:31:13
+ |
+LL | Punned { bar: [_] } => println!("bar"),
+ | ^^^^^^^^^^^^^^^^^^^
+
+error: aborting due to 2 previous errors
+
diff --git a/tests/ui/pattern/usefulness/issue-65413-constants-and-slices-exhaustiveness.rs b/tests/ui/pattern/usefulness/issue-65413-constants-and-slices-exhaustiveness.rs
new file mode 100644
index 000000000..54dfa889e
--- /dev/null
+++ b/tests/ui/pattern/usefulness/issue-65413-constants-and-slices-exhaustiveness.rs
@@ -0,0 +1,15 @@
+// check-pass
+
+#![deny(unreachable_patterns)]
+
+const C0: &'static [u8] = b"\x00";
+
+fn main() {
+ let x: &[u8] = &[0];
+ match x {
+ &[] => {}
+ &[1..=255] => {}
+ C0 => {}
+ &[_, _, ..] => {}
+ }
+}
diff --git a/tests/ui/pattern/usefulness/issue-66501.rs b/tests/ui/pattern/usefulness/issue-66501.rs
new file mode 100644
index 000000000..ffcfd4ad8
--- /dev/null
+++ b/tests/ui/pattern/usefulness/issue-66501.rs
@@ -0,0 +1,12 @@
+// check-pass
+
+#![allow(unreachable_patterns)]
+
+fn main() {
+ const CONST: &[Option<()>; 1] = &[Some(())];
+ match &[Some(())] {
+ &[None] => {}
+ CONST => {}
+ &[Some(())] => {}
+ }
+}
diff --git a/tests/ui/pattern/usefulness/issue-71930-type-of-match-scrutinee.rs b/tests/ui/pattern/usefulness/issue-71930-type-of-match-scrutinee.rs
new file mode 100644
index 000000000..e2ff9ac87
--- /dev/null
+++ b/tests/ui/pattern/usefulness/issue-71930-type-of-match-scrutinee.rs
@@ -0,0 +1,22 @@
+// check-pass
+
+// In PR 71930, it was discovered that the code to retrieve the inferred type of a match scrutinee
+// was incorrect.
+
+fn f() -> ! {
+ panic!()
+}
+
+fn g() -> usize {
+ match f() { // Should infer type `bool`
+ false => 0,
+ true => 1,
+ }
+}
+
+fn h() -> usize {
+ match f() { // Should infer type `!`
+ }
+}
+
+fn main() {}
diff --git a/tests/ui/pattern/usefulness/issue-72377.rs b/tests/ui/pattern/usefulness/issue-72377.rs
new file mode 100644
index 000000000..b5ad3075c
--- /dev/null
+++ b/tests/ui/pattern/usefulness/issue-72377.rs
@@ -0,0 +1,17 @@
+#[derive(PartialEq, Eq)]
+enum X { A, B, C, }
+
+fn main() {
+ let x = X::A;
+ let y = Some(X::A);
+
+ match (x, y) {
+ //~^ ERROR non-exhaustive patterns: `(X::A, Some(X::A))`, `(X::A, Some(X::B))`, `(X::B, Some(X::B))` and 2
+ //~| more not covered
+ (_, None) => false,
+ (v, Some(w)) if v == w => true,
+ (X::B, Some(X::C)) => false,
+ (X::B, Some(X::A)) => false,
+ (X::A, Some(X::C)) | (X::C, Some(X::A)) => false,
+ };
+}
diff --git a/tests/ui/pattern/usefulness/issue-72377.stderr b/tests/ui/pattern/usefulness/issue-72377.stderr
new file mode 100644
index 000000000..123dd051d
--- /dev/null
+++ b/tests/ui/pattern/usefulness/issue-72377.stderr
@@ -0,0 +1,16 @@
+error[E0004]: non-exhaustive patterns: `(X::A, Some(X::A))`, `(X::A, Some(X::B))`, `(X::B, Some(X::B))` and 2 more not covered
+ --> $DIR/issue-72377.rs:8:11
+ |
+LL | match (x, y) {
+ | ^^^^^^ patterns `(X::A, Some(X::A))`, `(X::A, Some(X::B))`, `(X::B, Some(X::B))` and 2 more not covered
+ |
+ = note: the matched value is of type `(X, Option<X>)`
+help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern as shown, or multiple match arms
+ |
+LL ~ (X::A, Some(X::C)) | (X::C, Some(X::A)) => false,
+LL ~ _ => todo!(),
+ |
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0004`.
diff --git a/tests/ui/pattern/usefulness/issue-72476-and-89393-associated-type.rs b/tests/ui/pattern/usefulness/issue-72476-and-89393-associated-type.rs
new file mode 100644
index 000000000..058f41967
--- /dev/null
+++ b/tests/ui/pattern/usefulness/issue-72476-and-89393-associated-type.rs
@@ -0,0 +1,56 @@
+// check-pass
+
+// From https://github.com/rust-lang/rust/issues/72476
+// and https://github.com/rust-lang/rust/issues/89393
+
+trait Trait {
+ type Projection;
+}
+
+struct A;
+impl Trait for A {
+ type Projection = bool;
+}
+
+struct B;
+impl Trait for B {
+ type Projection = (u32, u32);
+}
+
+struct Next<T: Trait>(T::Projection);
+
+fn foo1(item: Next<A>) {
+ match item {
+ Next(true) => {}
+ Next(false) => {}
+ }
+}
+
+fn foo2(x: <A as Trait>::Projection) {
+ match x {
+ true => {}
+ false => {}
+ }
+}
+
+fn foo3(x: Next<B>) {
+ let Next((_, _)) = x;
+ match x {
+ Next((_, _)) => {}
+ }
+}
+
+fn foo4(x: <B as Trait>::Projection) {
+ let (_, _) = x;
+ match x {
+ (_, _) => {}
+ }
+}
+
+fn foo5<T: Trait>(x: <T as Trait>::Projection) {
+ match x {
+ _ => {}
+ }
+}
+
+fn main() {}
diff --git a/tests/ui/pattern/usefulness/issue-78123-non-exhaustive-reference.rs b/tests/ui/pattern/usefulness/issue-78123-non-exhaustive-reference.rs
new file mode 100644
index 000000000..cbfcf0eaf
--- /dev/null
+++ b/tests/ui/pattern/usefulness/issue-78123-non-exhaustive-reference.rs
@@ -0,0 +1,12 @@
+enum A {}
+ //~^ NOTE `A` defined here
+ //~| NOTE
+
+fn f(a: &A) {
+ match a {}
+ //~^ ERROR non-exhaustive patterns: type `&A` is non-empty
+ //~| NOTE the matched value is of type `&A`
+ //~| NOTE references are always considered inhabited
+}
+
+fn main() {}
diff --git a/tests/ui/pattern/usefulness/issue-78123-non-exhaustive-reference.stderr b/tests/ui/pattern/usefulness/issue-78123-non-exhaustive-reference.stderr
new file mode 100644
index 000000000..bf05d616d
--- /dev/null
+++ b/tests/ui/pattern/usefulness/issue-78123-non-exhaustive-reference.stderr
@@ -0,0 +1,23 @@
+error[E0004]: non-exhaustive patterns: type `&A` is non-empty
+ --> $DIR/issue-78123-non-exhaustive-reference.rs:6:11
+ |
+LL | match a {}
+ | ^
+ |
+note: `A` defined here
+ --> $DIR/issue-78123-non-exhaustive-reference.rs:1:6
+ |
+LL | enum A {}
+ | ^
+ = note: the matched value is of type `&A`
+ = note: references are always considered inhabited
+help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern as shown
+ |
+LL ~ match a {
+LL + _ => todo!(),
+LL + }
+ |
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0004`.
diff --git a/tests/ui/pattern/usefulness/issue-78549-ref-pat-and-str.rs b/tests/ui/pattern/usefulness/issue-78549-ref-pat-and-str.rs
new file mode 100644
index 000000000..2879caf2c
--- /dev/null
+++ b/tests/ui/pattern/usefulness/issue-78549-ref-pat-and-str.rs
@@ -0,0 +1,25 @@
+// check-pass
+// From https://github.com/rust-lang/rust/issues/78549
+
+fn main() {
+ match "foo" {
+ "foo" => {},
+ &_ => {},
+ }
+
+ match "foo" {
+ &_ => {},
+ "foo" => {},
+ }
+
+ match ("foo", 0, "bar") {
+ (&_, 0, &_) => {},
+ ("foo", _, "bar") => {},
+ (&_, _, &_) => {},
+ }
+
+ match (&"foo", "bar") {
+ (&"foo", &_) => {},
+ (&&_, &_) => {},
+ }
+}
diff --git a/tests/ui/pattern/usefulness/issue-80501-or-pat-and-macro.rs b/tests/ui/pattern/usefulness/issue-80501-or-pat-and-macro.rs
new file mode 100644
index 000000000..aac7d7d53
--- /dev/null
+++ b/tests/ui/pattern/usefulness/issue-80501-or-pat-and-macro.rs
@@ -0,0 +1,27 @@
+// check-pass
+#![deny(unreachable_patterns)]
+pub enum TypeCtor {
+ Slice,
+ Array,
+}
+
+pub struct ApplicationTy(TypeCtor);
+
+macro_rules! ty_app {
+ ($ctor:pat) => {
+ ApplicationTy($ctor)
+ };
+}
+
+fn _foo(ty: ApplicationTy) {
+ match ty {
+ ty_app!(TypeCtor::Array) | ty_app!(TypeCtor::Slice) => {}
+ }
+
+ // same as above, with the macro expanded
+ match ty {
+ ApplicationTy(TypeCtor::Array) | ApplicationTy(TypeCtor::Slice) => {}
+ }
+}
+
+fn main() {}
diff --git a/tests/ui/pattern/usefulness/issue-82772-match-box-as-struct.rs b/tests/ui/pattern/usefulness/issue-82772-match-box-as-struct.rs
new file mode 100644
index 000000000..c1bfcc734
--- /dev/null
+++ b/tests/ui/pattern/usefulness/issue-82772-match-box-as-struct.rs
@@ -0,0 +1,6 @@
+// This used to ICE in exhaustiveness checking. Explanation here:
+// https://github.com/rust-lang/rust/issues/82772#issuecomment-905946768
+fn main() {
+ let Box { 1: _, .. }: Box<()>; //~ ERROR field `1` of
+ let Box { .. }: Box<()>;
+}
diff --git a/tests/ui/pattern/usefulness/issue-82772-match-box-as-struct.stderr b/tests/ui/pattern/usefulness/issue-82772-match-box-as-struct.stderr
new file mode 100644
index 000000000..2c8c85bb1
--- /dev/null
+++ b/tests/ui/pattern/usefulness/issue-82772-match-box-as-struct.stderr
@@ -0,0 +1,9 @@
+error[E0451]: field `1` of struct `Box` is private
+ --> $DIR/issue-82772-match-box-as-struct.rs:4:15
+ |
+LL | let Box { 1: _, .. }: Box<()>;
+ | ^^^^ private field
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0451`.
diff --git a/tests/ui/pattern/usefulness/issue-88747.rs b/tests/ui/pattern/usefulness/issue-88747.rs
new file mode 100644
index 000000000..948c99f9c
--- /dev/null
+++ b/tests/ui/pattern/usefulness/issue-88747.rs
@@ -0,0 +1,14 @@
+// check-pass: this used to be a stack overflow because of recursion in `usefulness.rs`
+
+macro_rules! long_tuple_arg {
+ ([$($t:tt)*]#$($h:tt)*) => {
+ long_tuple_arg!{[$($t)*$($t)*]$($h)*}
+ };
+ ([$([$t:tt $y:tt])*]) => {
+ pub fn _f(($($t,)*): ($($y,)*)) {}
+ }
+}
+
+long_tuple_arg!{[[_ u8]]########## ###}
+
+fn main() {}
diff --git a/tests/ui/pattern/usefulness/match-arm-statics-2.rs b/tests/ui/pattern/usefulness/match-arm-statics-2.rs
new file mode 100644
index 000000000..3c9c16561
--- /dev/null
+++ b/tests/ui/pattern/usefulness/match-arm-statics-2.rs
@@ -0,0 +1,62 @@
+use self::Direction::{North, East, South, West};
+
+#[derive(PartialEq, Eq)]
+struct NewBool(bool);
+
+#[derive(PartialEq, Eq)]
+enum Direction {
+ North,
+ East,
+ South,
+ West
+}
+
+const TRUE_TRUE: (bool, bool) = (true, true);
+
+fn nonexhaustive_1() {
+ match (true, false) {
+ //~^ ERROR non-exhaustive patterns: `(true, false)` not covered
+ TRUE_TRUE => (),
+ (false, false) => (),
+ (false, true) => ()
+ }
+}
+
+const NONE: Option<Direction> = None;
+const EAST: Direction = East;
+
+fn nonexhaustive_2() {
+ match Some(Some(North)) {
+ //~^ ERROR non-exhaustive patterns: `Some(Some(Direction::West))` not covered
+ Some(NONE) => (),
+ Some(Some(North)) => (),
+ Some(Some(EAST)) => (),
+ Some(Some(South)) => (),
+ None => ()
+ }
+}
+
+const NEW_FALSE: NewBool = NewBool(false);
+struct Foo {
+ bar: Option<Direction>,
+ baz: NewBool
+}
+
+const STATIC_FOO: Foo = Foo { bar: None, baz: NEW_FALSE };
+
+fn nonexhaustive_3() {
+ match (Foo { bar: Some(North), baz: NewBool(true) }) {
+ //~^ ERROR non-exhaustive patterns: `Foo { bar: Some(Direction::North), baz: NewBool(true) }`
+ Foo { bar: None, baz: NewBool(true) } => (),
+ Foo { bar: _, baz: NEW_FALSE } => (),
+ Foo { bar: Some(West), baz: NewBool(true) } => (),
+ Foo { bar: Some(South), .. } => (),
+ Foo { bar: Some(EAST), .. } => ()
+ }
+}
+
+fn main() {
+ nonexhaustive_1();
+ nonexhaustive_2();
+ nonexhaustive_3();
+}
diff --git a/tests/ui/pattern/usefulness/match-arm-statics-2.stderr b/tests/ui/pattern/usefulness/match-arm-statics-2.stderr
new file mode 100644
index 000000000..e4dd35a59
--- /dev/null
+++ b/tests/ui/pattern/usefulness/match-arm-statics-2.stderr
@@ -0,0 +1,54 @@
+error[E0004]: non-exhaustive patterns: `(true, false)` not covered
+ --> $DIR/match-arm-statics-2.rs:17:11
+ |
+LL | match (true, false) {
+ | ^^^^^^^^^^^^^ pattern `(true, false)` not covered
+ |
+ = note: the matched value is of type `(bool, bool)`
+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 ~ (false, true) => (),
+LL + (true, false) => todo!()
+ |
+
+error[E0004]: non-exhaustive patterns: `Some(Some(Direction::West))` not covered
+ --> $DIR/match-arm-statics-2.rs:29:11
+ |
+LL | match Some(Some(North)) {
+ | ^^^^^^^^^^^^^^^^^ pattern `Some(Some(Direction::West))` not covered
+ |
+note: `Option<Option<Direction>>` defined here
+ --> $SRC_DIR/core/src/option.rs:LL:COL
+ ::: $SRC_DIR/core/src/option.rs:LL:COL
+ |
+ = note: not covered
+ |
+ = note: not covered
+ = note: the matched value is of type `Option<Option<Direction>>`
+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 ~ None => (),
+LL + Some(Some(Direction::West)) => todo!()
+ |
+
+error[E0004]: non-exhaustive patterns: `Foo { bar: Some(Direction::North), baz: NewBool(true) }` not covered
+ --> $DIR/match-arm-statics-2.rs:48:11
+ |
+LL | match (Foo { bar: Some(North), baz: NewBool(true) }) {
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ pattern `Foo { bar: Some(Direction::North), baz: NewBool(true) }` not covered
+ |
+note: `Foo` defined here
+ --> $DIR/match-arm-statics-2.rs:40:8
+ |
+LL | struct Foo {
+ | ^^^
+ = note: the matched value is of type `Foo`
+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 ~ Foo { bar: Some(EAST), .. } => (),
+LL + Foo { bar: Some(Direction::North), baz: NewBool(true) } => todo!()
+ |
+
+error: aborting due to 3 previous errors
+
+For more information about this error, try `rustc --explain E0004`.
diff --git a/tests/ui/pattern/usefulness/match-arm-statics.rs b/tests/ui/pattern/usefulness/match-arm-statics.rs
new file mode 100644
index 000000000..91db76ebb
--- /dev/null
+++ b/tests/ui/pattern/usefulness/match-arm-statics.rs
@@ -0,0 +1,69 @@
+#![allow(dead_code)]
+#![deny(unreachable_patterns)]
+
+use self::Direction::{North, East, South, West};
+
+#[derive(PartialEq, Eq)]
+struct NewBool(bool);
+
+#[derive(PartialEq, Eq)]
+enum Direction {
+ North,
+ East,
+ South,
+ West
+}
+
+const TRUE_TRUE: (bool, bool) = (true, true);
+
+fn unreachable_1() {
+ match (true, false) {
+ TRUE_TRUE => (),
+ (false, false) => (),
+ (false, true) => (),
+ (true, false) => (),
+ (true, true) => ()
+ //~^ ERROR unreachable pattern
+ }
+}
+
+const NONE: Option<Direction> = None;
+const EAST: Direction = East;
+
+fn unreachable_2() {
+ match Some(Some(North)) {
+ Some(NONE) => (),
+ Some(Some(North)) => (),
+ Some(Some(EAST)) => (),
+ Some(Some(South)) => (),
+ Some(Some(West)) => (),
+ Some(Some(East)) => (),
+ //~^ ERROR unreachable pattern
+ None => ()
+ }
+}
+
+const NEW_FALSE: NewBool = NewBool(false);
+struct Foo {
+ bar: Option<Direction>,
+ baz: NewBool
+}
+
+fn unreachable_3() {
+ match (Foo { bar: Some(EAST), baz: NewBool(true) }) {
+ Foo { bar: None, baz: NewBool(true) } => (),
+ Foo { bar: _, baz: NEW_FALSE } => (),
+ Foo { bar: Some(West), baz: NewBool(true) } => (),
+ Foo { bar: Some(South), .. } => (),
+ Foo { bar: Some(EAST), .. } => (),
+ Foo { bar: Some(North), baz: NewBool(true) } => (),
+ Foo { bar: Some(EAST), baz: NewBool(false) } => ()
+ //~^ ERROR unreachable pattern
+ }
+}
+
+fn main() {
+ unreachable_1();
+ unreachable_2();
+ unreachable_3();
+}
diff --git a/tests/ui/pattern/usefulness/match-arm-statics.stderr b/tests/ui/pattern/usefulness/match-arm-statics.stderr
new file mode 100644
index 000000000..a5dffebf6
--- /dev/null
+++ b/tests/ui/pattern/usefulness/match-arm-statics.stderr
@@ -0,0 +1,26 @@
+error: unreachable pattern
+ --> $DIR/match-arm-statics.rs:25:9
+ |
+LL | (true, true) => ()
+ | ^^^^^^^^^^^^
+ |
+note: the lint level is defined here
+ --> $DIR/match-arm-statics.rs:2:9
+ |
+LL | #![deny(unreachable_patterns)]
+ | ^^^^^^^^^^^^^^^^^^^^
+
+error: unreachable pattern
+ --> $DIR/match-arm-statics.rs:40:9
+ |
+LL | Some(Some(East)) => (),
+ | ^^^^^^^^^^^^^^^^
+
+error: unreachable pattern
+ --> $DIR/match-arm-statics.rs:60:9
+ |
+LL | Foo { bar: Some(EAST), baz: NewBool(false) } => ()
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: aborting due to 3 previous errors
+
diff --git a/tests/ui/pattern/usefulness/match-byte-array-patterns-2.rs b/tests/ui/pattern/usefulness/match-byte-array-patterns-2.rs
new file mode 100644
index 000000000..33468d03f
--- /dev/null
+++ b/tests/ui/pattern/usefulness/match-byte-array-patterns-2.rs
@@ -0,0 +1,13 @@
+fn main() {
+ let buf = &[0, 1, 2, 3];
+
+ match buf { //~ ERROR non-exhaustive
+ b"AAAA" => {}
+ }
+
+ let buf: &[u8] = buf;
+
+ match buf { //~ ERROR non-exhaustive
+ b"AAAA" => {}
+ }
+}
diff --git a/tests/ui/pattern/usefulness/match-byte-array-patterns-2.stderr b/tests/ui/pattern/usefulness/match-byte-array-patterns-2.stderr
new file mode 100644
index 000000000..a90f32f7a
--- /dev/null
+++ b/tests/ui/pattern/usefulness/match-byte-array-patterns-2.stderr
@@ -0,0 +1,29 @@
+error[E0004]: non-exhaustive patterns: `&[0_u8..=64_u8, _, _, _]` and `&[66_u8..=u8::MAX, _, _, _]` not covered
+ --> $DIR/match-byte-array-patterns-2.rs:4:11
+ |
+LL | match buf {
+ | ^^^ patterns `&[0_u8..=64_u8, _, _, _]` and `&[66_u8..=u8::MAX, _, _, _]` not covered
+ |
+ = note: the matched value is of type `&[u8; 4]`
+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 ~ b"AAAA" => {}
+LL + &[0_u8..=64_u8, _, _, _] | &[66_u8..=u8::MAX, _, _, _] => todo!()
+ |
+
+error[E0004]: non-exhaustive patterns: `&[]`, `&[_]`, `&[_, _]` and 2 more not covered
+ --> $DIR/match-byte-array-patterns-2.rs:10:11
+ |
+LL | match buf {
+ | ^^^ patterns `&[]`, `&[_]`, `&[_, _]` and 2 more not covered
+ |
+ = note: the matched value is of type `&[u8]`
+help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern as shown, or multiple match arms
+ |
+LL ~ b"AAAA" => {}
+LL + _ => todo!()
+ |
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0004`.
diff --git a/tests/ui/pattern/usefulness/match-byte-array-patterns.rs b/tests/ui/pattern/usefulness/match-byte-array-patterns.rs
new file mode 100644
index 000000000..9b6c8bd55
--- /dev/null
+++ b/tests/ui/pattern/usefulness/match-byte-array-patterns.rs
@@ -0,0 +1,55 @@
+#![deny(unreachable_patterns)]
+
+fn main() {
+ let buf = &[0, 1, 2, 3];
+
+ match buf {
+ b"AAAA" => {},
+ &[0x41, 0x41, 0x41, 0x41] => {} //~ ERROR unreachable pattern
+ _ => {}
+ }
+
+ match buf {
+ &[0x41, 0x41, 0x41, 0x41] => {}
+ b"AAAA" => {}, //~ ERROR unreachable pattern
+ _ => {}
+ }
+
+ match buf {
+ &[_, 0x41, 0x41, 0x41] => {},
+ b"AAAA" => {}, //~ ERROR unreachable pattern
+ _ => {}
+ }
+
+ match buf {
+ &[0x41, .., 0x41] => {}
+ b"AAAA" => {}, //~ ERROR unreachable pattern
+ _ => {}
+ }
+
+ let buf: &[u8] = buf;
+
+ match buf {
+ b"AAAA" => {},
+ &[0x41, 0x41, 0x41, 0x41] => {} //~ ERROR unreachable pattern
+ _ => {}
+ }
+
+ match buf {
+ &[0x41, 0x41, 0x41, 0x41] => {}
+ b"AAAA" => {}, //~ ERROR unreachable pattern
+ _ => {}
+ }
+
+ match buf {
+ &[_, 0x41, 0x41, 0x41] => {},
+ b"AAAA" => {}, //~ ERROR unreachable pattern
+ _ => {}
+ }
+
+ match buf {
+ &[0x41, .., 0x41] => {}
+ b"AAAA" => {}, //~ ERROR unreachable pattern
+ _ => {}
+ }
+}
diff --git a/tests/ui/pattern/usefulness/match-byte-array-patterns.stderr b/tests/ui/pattern/usefulness/match-byte-array-patterns.stderr
new file mode 100644
index 000000000..0c582be8d
--- /dev/null
+++ b/tests/ui/pattern/usefulness/match-byte-array-patterns.stderr
@@ -0,0 +1,56 @@
+error: unreachable pattern
+ --> $DIR/match-byte-array-patterns.rs:8:9
+ |
+LL | &[0x41, 0x41, 0x41, 0x41] => {}
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^
+ |
+note: the lint level is defined here
+ --> $DIR/match-byte-array-patterns.rs:1:9
+ |
+LL | #![deny(unreachable_patterns)]
+ | ^^^^^^^^^^^^^^^^^^^^
+
+error: unreachable pattern
+ --> $DIR/match-byte-array-patterns.rs:14:9
+ |
+LL | b"AAAA" => {},
+ | ^^^^^^^
+
+error: unreachable pattern
+ --> $DIR/match-byte-array-patterns.rs:20:9
+ |
+LL | b"AAAA" => {},
+ | ^^^^^^^
+
+error: unreachable pattern
+ --> $DIR/match-byte-array-patterns.rs:26:9
+ |
+LL | b"AAAA" => {},
+ | ^^^^^^^
+
+error: unreachable pattern
+ --> $DIR/match-byte-array-patterns.rs:34:9
+ |
+LL | &[0x41, 0x41, 0x41, 0x41] => {}
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: unreachable pattern
+ --> $DIR/match-byte-array-patterns.rs:40:9
+ |
+LL | b"AAAA" => {},
+ | ^^^^^^^
+
+error: unreachable pattern
+ --> $DIR/match-byte-array-patterns.rs:46:9
+ |
+LL | b"AAAA" => {},
+ | ^^^^^^^
+
+error: unreachable pattern
+ --> $DIR/match-byte-array-patterns.rs:52:9
+ |
+LL | b"AAAA" => {},
+ | ^^^^^^^
+
+error: aborting due to 8 previous errors
+
diff --git a/tests/ui/pattern/usefulness/match-non-exhaustive.rs b/tests/ui/pattern/usefulness/match-non-exhaustive.rs
new file mode 100644
index 000000000..3b210a115
--- /dev/null
+++ b/tests/ui/pattern/usefulness/match-non-exhaustive.rs
@@ -0,0 +1,4 @@
+fn main() {
+ match 0 { 1 => () } //~ ERROR non-exhaustive patterns
+ match 0 { 0 if false => () } //~ ERROR non-exhaustive patterns
+}
diff --git a/tests/ui/pattern/usefulness/match-non-exhaustive.stderr b/tests/ui/pattern/usefulness/match-non-exhaustive.stderr
new file mode 100644
index 000000000..08dde523a
--- /dev/null
+++ b/tests/ui/pattern/usefulness/match-non-exhaustive.stderr
@@ -0,0 +1,27 @@
+error[E0004]: non-exhaustive patterns: `i32::MIN..=0_i32` and `2_i32..=i32::MAX` not covered
+ --> $DIR/match-non-exhaustive.rs:2:11
+ |
+LL | match 0 { 1 => () }
+ | ^ patterns `i32::MIN..=0_i32` and `2_i32..=i32::MAX` not covered
+ |
+ = note: the matched value is of type `i32`
+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 0 { 1 => (), i32::MIN..=0_i32 | 2_i32..=i32::MAX => todo!() }
+ | ++++++++++++++++++++++++++++++++++++++++++++++++
+
+error[E0004]: non-exhaustive patterns: `_` not covered
+ --> $DIR/match-non-exhaustive.rs:3:11
+ |
+LL | match 0 { 0 if false => () }
+ | ^ pattern `_` not covered
+ |
+ = note: the matched value is of type `i32`
+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 0 { 0 if false => (), _ => todo!() }
+ | ++++++++++++++
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0004`.
diff --git a/tests/ui/pattern/usefulness/match-privately-empty.rs b/tests/ui/pattern/usefulness/match-privately-empty.rs
new file mode 100644
index 000000000..315eb03d1
--- /dev/null
+++ b/tests/ui/pattern/usefulness/match-privately-empty.rs
@@ -0,0 +1,21 @@
+#![feature(never_type)]
+#![feature(exhaustive_patterns)]
+
+mod private {
+ pub struct Private {
+ _bot: !,
+ pub misc: bool,
+ }
+ pub const DATA: Option<Private> = None;
+}
+
+fn main() {
+ match private::DATA {
+ //~^ ERROR non-exhaustive patterns: `Some(Private { misc: true, .. })` not covered
+ None => {}
+ Some(private::Private {
+ misc: false,
+ ..
+ }) => {}
+ }
+}
diff --git a/tests/ui/pattern/usefulness/match-privately-empty.stderr b/tests/ui/pattern/usefulness/match-privately-empty.stderr
new file mode 100644
index 000000000..86f75d15c
--- /dev/null
+++ b/tests/ui/pattern/usefulness/match-privately-empty.stderr
@@ -0,0 +1,21 @@
+error[E0004]: non-exhaustive patterns: `Some(Private { misc: true, .. })` not covered
+ --> $DIR/match-privately-empty.rs:13:11
+ |
+LL | match private::DATA {
+ | ^^^^^^^^^^^^^ pattern `Some(Private { misc: true, .. })` not covered
+ |
+note: `Option<Private>` defined here
+ --> $SRC_DIR/core/src/option.rs:LL:COL
+ ::: $SRC_DIR/core/src/option.rs:LL:COL
+ |
+ = note: not covered
+ = note: the matched value is of type `Option<Private>`
+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 ~ }) => {}
+LL + Some(Private { misc: true, .. }) => todo!()
+ |
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0004`.
diff --git a/tests/ui/pattern/usefulness/match-ref-ice.rs b/tests/ui/pattern/usefulness/match-ref-ice.rs
new file mode 100644
index 000000000..dee110f96
--- /dev/null
+++ b/tests/ui/pattern/usefulness/match-ref-ice.rs
@@ -0,0 +1,16 @@
+#![deny(unreachable_patterns)]
+
+// The arity of `ref x` is always 1. If the pattern is compared to some non-structural type whose
+// arity is always 0, an ICE occurs.
+//
+// Related issue: #23009
+
+fn main() {
+ let homura = [1, 2, 3];
+
+ match homura {
+ [1, ref _madoka, 3] => (),
+ [1, 2, 3] => (), //~ ERROR unreachable pattern
+ [_, _, _] => (),
+ }
+}
diff --git a/tests/ui/pattern/usefulness/match-ref-ice.stderr b/tests/ui/pattern/usefulness/match-ref-ice.stderr
new file mode 100644
index 000000000..fad0940ba
--- /dev/null
+++ b/tests/ui/pattern/usefulness/match-ref-ice.stderr
@@ -0,0 +1,14 @@
+error: unreachable pattern
+ --> $DIR/match-ref-ice.rs:13:9
+ |
+LL | [1, 2, 3] => (),
+ | ^^^^^^^^^
+ |
+note: the lint level is defined here
+ --> $DIR/match-ref-ice.rs:1:9
+ |
+LL | #![deny(unreachable_patterns)]
+ | ^^^^^^^^^^^^^^^^^^^^
+
+error: aborting due to previous error
+
diff --git a/tests/ui/pattern/usefulness/match-slice-patterns.rs b/tests/ui/pattern/usefulness/match-slice-patterns.rs
new file mode 100644
index 000000000..92d74b8c2
--- /dev/null
+++ b/tests/ui/pattern/usefulness/match-slice-patterns.rs
@@ -0,0 +1,12 @@
+fn check(list: &[Option<()>]) {
+ match list {
+ //~^ ERROR `&[_, Some(_), .., None, _]` not covered
+ &[] => {},
+ &[_] => {},
+ &[_, _] => {},
+ &[_, None, ..] => {},
+ &[.., Some(_), _] => {},
+ }
+}
+
+fn main() {}
diff --git a/tests/ui/pattern/usefulness/match-slice-patterns.stderr b/tests/ui/pattern/usefulness/match-slice-patterns.stderr
new file mode 100644
index 000000000..961dd5901
--- /dev/null
+++ b/tests/ui/pattern/usefulness/match-slice-patterns.stderr
@@ -0,0 +1,16 @@
+error[E0004]: non-exhaustive patterns: `&[_, Some(_), .., None, _]` not covered
+ --> $DIR/match-slice-patterns.rs:2:11
+ |
+LL | match list {
+ | ^^^^ pattern `&[_, Some(_), .., None, _]` not covered
+ |
+ = note: the matched value is of type `&[Option<()>]`
+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 ~ &[.., Some(_), _] => {}
+LL ~ &[_, Some(_), .., None, _] => todo!(),
+ |
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0004`.
diff --git a/tests/ui/pattern/usefulness/match-vec-fixed.rs b/tests/ui/pattern/usefulness/match-vec-fixed.rs
new file mode 100644
index 000000000..e611779de
--- /dev/null
+++ b/tests/ui/pattern/usefulness/match-vec-fixed.rs
@@ -0,0 +1,18 @@
+#![deny(unreachable_patterns)]
+
+fn a() {
+ let v = [1, 2, 3];
+ match v {
+ [_, _, _] => {}
+ [_, _, _] => {} //~ ERROR unreachable pattern
+ }
+ match v {
+ [_, 1, _] => {}
+ [_, 1, _] => {} //~ ERROR unreachable pattern
+ _ => {}
+ }
+}
+
+fn main() {
+ a();
+}
diff --git a/tests/ui/pattern/usefulness/match-vec-fixed.stderr b/tests/ui/pattern/usefulness/match-vec-fixed.stderr
new file mode 100644
index 000000000..e388a06cb
--- /dev/null
+++ b/tests/ui/pattern/usefulness/match-vec-fixed.stderr
@@ -0,0 +1,20 @@
+error: unreachable pattern
+ --> $DIR/match-vec-fixed.rs:7:9
+ |
+LL | [_, _, _] => {}
+ | ^^^^^^^^^
+ |
+note: the lint level is defined here
+ --> $DIR/match-vec-fixed.rs:1:9
+ |
+LL | #![deny(unreachable_patterns)]
+ | ^^^^^^^^^^^^^^^^^^^^
+
+error: unreachable pattern
+ --> $DIR/match-vec-fixed.rs:11:9
+ |
+LL | [_, 1, _] => {}
+ | ^^^^^^^^^
+
+error: aborting due to 2 previous errors
+
diff --git a/tests/ui/pattern/usefulness/match-vec-unreachable.rs b/tests/ui/pattern/usefulness/match-vec-unreachable.rs
new file mode 100644
index 000000000..3342389be
--- /dev/null
+++ b/tests/ui/pattern/usefulness/match-vec-unreachable.rs
@@ -0,0 +1,29 @@
+#![deny(unreachable_patterns)]
+
+fn main() {
+ let x: Vec<(isize, isize)> = Vec::new();
+ let x: &[(isize, isize)] = &x;
+ match *x {
+ [a, (2, 3), _] => (),
+ [(1, 2), (2, 3), b] => (), //~ ERROR unreachable pattern
+ _ => ()
+ }
+
+ let x: Vec<String> = vec!["foo".to_string(),
+ "bar".to_string(),
+ "baz".to_string()];
+ let x: &[String] = &x;
+ match *x {
+ [ref a, _, _, ..] => { println!("{}", a); }
+ [_, _, _, _, _] => { } //~ ERROR unreachable pattern
+ _ => { }
+ }
+
+ let x: Vec<char> = vec!['a', 'b', 'c'];
+ let x: &[char] = &x;
+ match *x {
+ ['a', 'b', 'c', ref _tail @ ..] => {}
+ ['a', 'b', 'c'] => {} //~ ERROR unreachable pattern
+ _ => {}
+ }
+}
diff --git a/tests/ui/pattern/usefulness/match-vec-unreachable.stderr b/tests/ui/pattern/usefulness/match-vec-unreachable.stderr
new file mode 100644
index 000000000..672fd92fb
--- /dev/null
+++ b/tests/ui/pattern/usefulness/match-vec-unreachable.stderr
@@ -0,0 +1,26 @@
+error: unreachable pattern
+ --> $DIR/match-vec-unreachable.rs:8:9
+ |
+LL | [(1, 2), (2, 3), b] => (),
+ | ^^^^^^^^^^^^^^^^^^^
+ |
+note: the lint level is defined here
+ --> $DIR/match-vec-unreachable.rs:1:9
+ |
+LL | #![deny(unreachable_patterns)]
+ | ^^^^^^^^^^^^^^^^^^^^
+
+error: unreachable pattern
+ --> $DIR/match-vec-unreachable.rs:18:9
+ |
+LL | [_, _, _, _, _] => { }
+ | ^^^^^^^^^^^^^^^
+
+error: unreachable pattern
+ --> $DIR/match-vec-unreachable.rs:26:9
+ |
+LL | ['a', 'b', 'c'] => {}
+ | ^^^^^^^^^^^^^^^
+
+error: aborting due to 3 previous errors
+
diff --git a/tests/ui/pattern/usefulness/nested-exhaustive-match.rs b/tests/ui/pattern/usefulness/nested-exhaustive-match.rs
new file mode 100644
index 000000000..8b2294f84
--- /dev/null
+++ b/tests/ui/pattern/usefulness/nested-exhaustive-match.rs
@@ -0,0 +1,14 @@
+// run-pass
+#![allow(dead_code)]
+// pretty-expanded FIXME #23616
+
+struct Foo { foo: bool, bar: Option<isize>, baz: isize }
+
+pub fn main() {
+ match (Foo{foo: true, bar: Some(10), baz: 20}) {
+ Foo{foo: true, bar: Some(_), ..} => {}
+ Foo{foo: false, bar: None, ..} => {}
+ Foo{foo: true, bar: None, ..} => {}
+ Foo{foo: false, bar: Some(_), ..} => {}
+ }
+}
diff --git a/tests/ui/pattern/usefulness/non-exhaustive-defined-here.rs b/tests/ui/pattern/usefulness/non-exhaustive-defined-here.rs
new file mode 100644
index 000000000..5145f7690
--- /dev/null
+++ b/tests/ui/pattern/usefulness/non-exhaustive-defined-here.rs
@@ -0,0 +1,107 @@
+// Test the "defined here" and "not covered" diagnostic hints.
+// We also make sure that references are peeled off from the scrutinee type
+// so that the diagnostics work better with default binding modes.
+
+#[derive(Clone)]
+enum E {
+ //~^ NOTE
+ //~| NOTE
+ //~| NOTE
+ //~| NOTE
+ //~| NOTE
+ //~| NOTE
+ A,
+ B,
+ //~^ NOTE `E` defined here
+ //~| NOTE `E` defined here
+ //~| NOTE `E` defined here
+ //~| NOTE not covered
+ //~| NOTE not covered
+ //~| NOTE not covered
+ //~| NOTE not covered
+ //~| NOTE not covered
+ //~| NOTE not covered
+ C
+ //~^ not covered
+ //~| not covered
+ //~| not covered
+ //~| not covered
+ //~| not covered
+ //~| not covered
+}
+
+fn by_val(e: E) {
+ let e1 = e.clone();
+ match e1 { //~ ERROR non-exhaustive patterns: `E::B` and `E::C` not covered
+ //~^ NOTE patterns `E::B` and `E::C` not covered
+ //~| NOTE the matched value is of type `E`
+ E::A => {}
+ }
+
+ let E::A = e;
+ //~^ ERROR refutable pattern in local binding
+ //~| patterns `E::B` and `E::C` not covered
+ //~| NOTE `let` bindings require an "irrefutable pattern", like a `struct` or an `enum` with
+ //~| NOTE for more information, visit https://doc.rust-lang.org/book/ch18-02-refutability.html
+ //~| NOTE the matched value is of type `E`
+}
+
+fn by_ref_once(e: &E) {
+ match e {
+ //~^ ERROR non-exhaustive patterns
+ //~| patterns `&E::B` and `&E::C` not covered
+ //~| NOTE the matched value is of type `&E`
+ E::A => {}
+ }
+
+ let E::A = e;
+ //~^ ERROR refutable pattern in local binding
+ //~| patterns `&E::B` and `&E::C` not covered
+ //~| NOTE `let` bindings require an "irrefutable pattern", like a `struct` or an `enum` with
+ //~| NOTE for more information, visit https://doc.rust-lang.org/book/ch18-02-refutability.html
+ //~| NOTE the matched value is of type `&E`
+}
+
+fn by_ref_thrice(e: & &mut &E) {
+ match e {
+ //~^ ERROR non-exhaustive patterns
+ //~| patterns `&&mut &E::B` and `&&mut &E::C` not covered
+ //~| NOTE the matched value is of type `&&mut &E`
+ E::A => {}
+ }
+
+ let E::A = e;
+ //~^ ERROR refutable pattern in local binding
+ //~| patterns `&&mut &E::B` and `&&mut &E::C` not covered
+ //~| NOTE `let` bindings require an "irrefutable pattern", like a `struct` or an `enum` with
+ //~| NOTE for more information, visit https://doc.rust-lang.org/book/ch18-02-refutability.html
+ //~| NOTE the matched value is of type `&&mut &E`
+}
+
+enum Opt {
+ //~^ NOTE
+ //~| NOTE
+ Some(u8),
+ None,
+ //~^ NOTE `Opt` defined here
+ //~| NOTE not covered
+ //~| NOTE not covered
+}
+
+fn ref_pat(e: Opt) {
+ match e {
+ //~^ ERROR non-exhaustive patterns
+ //~| pattern `Opt::None` not covered
+ //~| NOTE the matched value is of type `Opt`
+ Opt::Some(ref _x) => {}
+ }
+
+ let Opt::Some(ref _x) = e;
+ //~^ ERROR refutable pattern in local binding
+ //~| NOTE the matched value is of type `Opt`
+ //~| NOTE pattern `Opt::None` not covered
+ //~| NOTE `let` bindings require an "irrefutable pattern", like a `struct` or an `enum` with
+ //~| NOTE for more information, visit https://doc.rust-lang.org/book/ch18-02-refutability.html
+}
+
+fn main() {}
diff --git a/tests/ui/pattern/usefulness/non-exhaustive-defined-here.stderr b/tests/ui/pattern/usefulness/non-exhaustive-defined-here.stderr
new file mode 100644
index 000000000..769d4070f
--- /dev/null
+++ b/tests/ui/pattern/usefulness/non-exhaustive-defined-here.stderr
@@ -0,0 +1,194 @@
+error[E0004]: non-exhaustive patterns: `E::B` and `E::C` not covered
+ --> $DIR/non-exhaustive-defined-here.rs:35:11
+ |
+LL | match e1 {
+ | ^^ patterns `E::B` and `E::C` not covered
+ |
+note: `E` defined here
+ --> $DIR/non-exhaustive-defined-here.rs:14:5
+ |
+LL | enum E {
+ | -
+...
+LL | B,
+ | ^ not covered
+...
+LL | C
+ | ^ not covered
+ = note: the matched value is of type `E`
+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 ~ E::A => {}
+LL + E::B | E::C => todo!()
+ |
+
+error[E0005]: refutable pattern in local binding
+ --> $DIR/non-exhaustive-defined-here.rs:41:9
+ |
+LL | let E::A = e;
+ | ^^^^ patterns `E::B` and `E::C` not covered
+ |
+ = note: `let` bindings require an "irrefutable pattern", like a `struct` or an `enum` with only one variant
+ = note: for more information, visit https://doc.rust-lang.org/book/ch18-02-refutability.html
+note: `E` defined here
+ --> $DIR/non-exhaustive-defined-here.rs:6:6
+ |
+LL | enum E {
+ | ^
+...
+LL | B,
+ | - not covered
+...
+LL | C
+ | - not covered
+ = note: the matched value is of type `E`
+help: you might want to use `if let` to ignore the variants that aren't matched
+ |
+LL | if let E::A = e { todo!() }
+ | ++ ~~~~~~~~~~~
+
+error[E0004]: non-exhaustive patterns: `&E::B` and `&E::C` not covered
+ --> $DIR/non-exhaustive-defined-here.rs:50:11
+ |
+LL | match e {
+ | ^ patterns `&E::B` and `&E::C` not covered
+ |
+note: `E` defined here
+ --> $DIR/non-exhaustive-defined-here.rs:14:5
+ |
+LL | enum E {
+ | -
+...
+LL | B,
+ | ^ not covered
+...
+LL | C
+ | ^ not covered
+ = note: the matched value is of type `&E`
+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 ~ E::A => {}
+LL + &E::B | &E::C => todo!()
+ |
+
+error[E0005]: refutable pattern in local binding
+ --> $DIR/non-exhaustive-defined-here.rs:57:9
+ |
+LL | let E::A = e;
+ | ^^^^ patterns `&E::B` and `&E::C` not covered
+ |
+ = note: `let` bindings require an "irrefutable pattern", like a `struct` or an `enum` with only one variant
+ = note: for more information, visit https://doc.rust-lang.org/book/ch18-02-refutability.html
+note: `E` defined here
+ --> $DIR/non-exhaustive-defined-here.rs:6:6
+ |
+LL | enum E {
+ | ^
+...
+LL | B,
+ | - not covered
+...
+LL | C
+ | - not covered
+ = note: the matched value is of type `&E`
+help: you might want to use `if let` to ignore the variants that aren't matched
+ |
+LL | if let E::A = e { todo!() }
+ | ++ ~~~~~~~~~~~
+
+error[E0004]: non-exhaustive patterns: `&&mut &E::B` and `&&mut &E::C` not covered
+ --> $DIR/non-exhaustive-defined-here.rs:66:11
+ |
+LL | match e {
+ | ^ patterns `&&mut &E::B` and `&&mut &E::C` not covered
+ |
+note: `E` defined here
+ --> $DIR/non-exhaustive-defined-here.rs:14:5
+ |
+LL | enum E {
+ | -
+...
+LL | B,
+ | ^ not covered
+...
+LL | C
+ | ^ not covered
+ = note: the matched value is of type `&&mut &E`
+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 ~ E::A => {}
+LL + &&mut &E::B | &&mut &E::C => todo!()
+ |
+
+error[E0005]: refutable pattern in local binding
+ --> $DIR/non-exhaustive-defined-here.rs:73:9
+ |
+LL | let E::A = e;
+ | ^^^^ patterns `&&mut &E::B` and `&&mut &E::C` not covered
+ |
+ = note: `let` bindings require an "irrefutable pattern", like a `struct` or an `enum` with only one variant
+ = note: for more information, visit https://doc.rust-lang.org/book/ch18-02-refutability.html
+note: `E` defined here
+ --> $DIR/non-exhaustive-defined-here.rs:6:6
+ |
+LL | enum E {
+ | ^
+...
+LL | B,
+ | - not covered
+...
+LL | C
+ | - not covered
+ = note: the matched value is of type `&&mut &E`
+help: you might want to use `if let` to ignore the variants that aren't matched
+ |
+LL | if let E::A = e { todo!() }
+ | ++ ~~~~~~~~~~~
+
+error[E0004]: non-exhaustive patterns: `Opt::None` not covered
+ --> $DIR/non-exhaustive-defined-here.rs:92:11
+ |
+LL | match e {
+ | ^ pattern `Opt::None` not covered
+ |
+note: `Opt` defined here
+ --> $DIR/non-exhaustive-defined-here.rs:85:5
+ |
+LL | enum Opt {
+ | ---
+...
+LL | None,
+ | ^^^^ not covered
+ = note: the matched value is of type `Opt`
+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 ~ Opt::Some(ref _x) => {}
+LL + Opt::None => todo!()
+ |
+
+error[E0005]: refutable pattern in local binding
+ --> $DIR/non-exhaustive-defined-here.rs:99:9
+ |
+LL | let Opt::Some(ref _x) = e;
+ | ^^^^^^^^^^^^^^^^^ pattern `Opt::None` not covered
+ |
+ = note: `let` bindings require an "irrefutable pattern", like a `struct` or an `enum` with only one variant
+ = note: for more information, visit https://doc.rust-lang.org/book/ch18-02-refutability.html
+note: `Opt` defined here
+ --> $DIR/non-exhaustive-defined-here.rs:81:6
+ |
+LL | enum Opt {
+ | ^^^
+...
+LL | None,
+ | ---- not covered
+ = note: the matched value is of type `Opt`
+help: you might want to use `let else` to handle the variant that isn't matched
+ |
+LL | let Opt::Some(ref _x) = e else { todo!() };
+ | ++++++++++++++++
+
+error: aborting due to 8 previous errors
+
+Some errors have detailed explanations: E0004, E0005.
+For more information about an error, try `rustc --explain E0004`.
diff --git a/tests/ui/pattern/usefulness/non-exhaustive-match-nested.rs b/tests/ui/pattern/usefulness/non-exhaustive-match-nested.rs
new file mode 100644
index 000000000..69c3c7658
--- /dev/null
+++ b/tests/ui/pattern/usefulness/non-exhaustive-match-nested.rs
@@ -0,0 +1,19 @@
+enum T { A(U), B }
+enum U { C, D }
+
+fn match_nested_vecs<'a, T>(l1: Option<&'a [T]>, l2: Result<&'a [T], ()>) -> &'static str {
+ match (l1, l2) { //~ ERROR non-exhaustive patterns: `(Some(&[]), Err(_))` not covered
+ (Some(&[]), Ok(&[])) => "Some(empty), Ok(empty)",
+ (Some(&[_, ..]), Ok(_)) | (Some(&[_, ..]), Err(())) => "Some(non-empty), any",
+ (None, Ok(&[])) | (None, Err(())) | (None, Ok(&[_])) => "None, Ok(less than one element)",
+ (None, Ok(&[_, _, ..])) => "None, Ok(at least two elements)"
+ }
+}
+
+fn main() {
+ let x = T::A(U::C);
+ match x { //~ ERROR non-exhaustive patterns: `T::A(U::C)` not covered
+ T::A(U::D) => { panic!("hello"); }
+ T::B => { panic!("goodbye"); }
+ }
+}
diff --git a/tests/ui/pattern/usefulness/non-exhaustive-match-nested.stderr b/tests/ui/pattern/usefulness/non-exhaustive-match-nested.stderr
new file mode 100644
index 000000000..44f327421
--- /dev/null
+++ b/tests/ui/pattern/usefulness/non-exhaustive-match-nested.stderr
@@ -0,0 +1,34 @@
+error[E0004]: non-exhaustive patterns: `(Some(&[]), Err(_))` not covered
+ --> $DIR/non-exhaustive-match-nested.rs:5:11
+ |
+LL | match (l1, l2) {
+ | ^^^^^^^^ pattern `(Some(&[]), Err(_))` not covered
+ |
+ = note: the matched value is of type `(Option<&[T]>, Result<&[T], ()>)`
+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 ~ (None, Ok(&[_, _, ..])) => "None, Ok(at least two elements)",
+LL + (Some(&[]), Err(_)) => todo!()
+ |
+
+error[E0004]: non-exhaustive patterns: `T::A(U::C)` not covered
+ --> $DIR/non-exhaustive-match-nested.rs:15:11
+ |
+LL | match x {
+ | ^ pattern `T::A(U::C)` not covered
+ |
+note: `T` defined here
+ --> $DIR/non-exhaustive-match-nested.rs:1:10
+ |
+LL | enum T { A(U), B }
+ | - ^ not covered
+ = note: the matched value is of type `T`
+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 ~ T::B => { panic!("goodbye"); }
+LL + T::A(U::C) => todo!()
+ |
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0004`.
diff --git a/tests/ui/pattern/usefulness/non-exhaustive-match.rs b/tests/ui/pattern/usefulness/non-exhaustive-match.rs
new file mode 100644
index 000000000..1cb58b8ce
--- /dev/null
+++ b/tests/ui/pattern/usefulness/non-exhaustive-match.rs
@@ -0,0 +1,63 @@
+#![allow(illegal_floating_point_literal_pattern)]
+
+enum T { A, B }
+
+fn main() {
+ let x = T::A;
+ match x { T::B => { } } //~ ERROR non-exhaustive patterns: `T::A` not covered
+ match true { //~ ERROR non-exhaustive patterns: `false` not covered
+ true => {}
+ }
+ match Some(10) { //~ ERROR non-exhaustive patterns: `Some(_)` not covered
+ None => {}
+ }
+ match (2, 3, 4) { //~ ERROR non-exhaustive patterns: `(_, _, i32::MIN..=3_i32)`
+ // and `(_, _, 5_i32..=i32::MAX)` not covered
+ (_, _, 4) => {}
+ }
+ match (T::A, T::A) { //~ ERROR non-exhaustive patterns: `(T::A, T::A)` and `(T::B, T::B)` not covered
+ (T::A, T::B) => {}
+ (T::B, T::A) => {}
+ }
+ match T::A { //~ ERROR non-exhaustive patterns: `T::B` not covered
+ T::A => {}
+ }
+ // This is exhaustive, though the algorithm got it wrong at one point
+ match (T::A, T::B) {
+ (T::A, _) => {}
+ (_, T::A) => {}
+ (T::B, T::B) => {}
+ }
+ let vec = vec![Some(42), None, Some(21)];
+ let vec: &[Option<isize>] = &vec;
+ match *vec { //~ ERROR non-exhaustive patterns: `[]` not covered
+ [Some(..), None, ref tail @ ..] => {}
+ [Some(..), Some(..), ref tail @ ..] => {}
+ [None] => {}
+ }
+ let vec = vec![1];
+ let vec: &[isize] = &vec;
+ match *vec {
+ [_, ref tail @ ..] => (),
+ [] => ()
+ }
+ let vec = vec![0.5f32];
+ let vec: &[f32] = &vec;
+ match *vec { //~ ERROR non-exhaustive patterns: `[_, _, _, _, ..]` not covered
+ [0.1, 0.2, 0.3] => (),
+ [0.1, 0.2] => (),
+ [0.1] => (),
+ [] => ()
+ }
+ let vec = vec![Some(42), None, Some(21)];
+ let vec: &[Option<isize>] = &vec;
+ match *vec {
+ [Some(..), None, ref tail @ ..] => {}
+ [Some(..), Some(..), ref tail @ ..] => {}
+ [None, None, ref tail @ ..] => {}
+ [None, Some(..), ref tail @ ..] => {}
+ [Some(_)] => {}
+ [None] => {}
+ [] => {}
+ }
+}
diff --git a/tests/ui/pattern/usefulness/non-exhaustive-match.stderr b/tests/ui/pattern/usefulness/non-exhaustive-match.stderr
new file mode 100644
index 000000000..e2260f50b
--- /dev/null
+++ b/tests/ui/pattern/usefulness/non-exhaustive-match.stderr
@@ -0,0 +1,121 @@
+error[E0004]: non-exhaustive patterns: `T::A` not covered
+ --> $DIR/non-exhaustive-match.rs:7:11
+ |
+LL | match x { T::B => { } }
+ | ^ pattern `T::A` not covered
+ |
+note: `T` defined here
+ --> $DIR/non-exhaustive-match.rs:3:10
+ |
+LL | enum T { A, B }
+ | - ^ not covered
+ = note: the matched value is of type `T`
+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 x { T::B => { }, T::A => todo!() }
+ | +++++++++++++++++
+
+error[E0004]: non-exhaustive patterns: `false` not covered
+ --> $DIR/non-exhaustive-match.rs:8:11
+ |
+LL | match true {
+ | ^^^^ pattern `false` not covered
+ |
+ = note: the matched value is of type `bool`
+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 ~ true => {}
+LL + false => todo!()
+ |
+
+error[E0004]: non-exhaustive patterns: `Some(_)` not covered
+ --> $DIR/non-exhaustive-match.rs:11:11
+ |
+LL | match Some(10) {
+ | ^^^^^^^^ pattern `Some(_)` not covered
+ |
+note: `Option<i32>` defined here
+ --> $SRC_DIR/core/src/option.rs:LL:COL
+ ::: $SRC_DIR/core/src/option.rs:LL:COL
+ |
+ = note: not covered
+ = note: the matched value is of type `Option<i32>`
+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 ~ None => {}
+LL + Some(_) => todo!()
+ |
+
+error[E0004]: non-exhaustive patterns: `(_, _, i32::MIN..=3_i32)` and `(_, _, 5_i32..=i32::MAX)` not covered
+ --> $DIR/non-exhaustive-match.rs:14:11
+ |
+LL | match (2, 3, 4) {
+ | ^^^^^^^^^ patterns `(_, _, i32::MIN..=3_i32)` and `(_, _, 5_i32..=i32::MAX)` not covered
+ |
+ = note: the matched value is of type `(i32, i32, i32)`
+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 ~ (_, _, 4) => {}
+LL + (_, _, i32::MIN..=3_i32) | (_, _, 5_i32..=i32::MAX) => todo!()
+ |
+
+error[E0004]: non-exhaustive patterns: `(T::A, T::A)` and `(T::B, T::B)` not covered
+ --> $DIR/non-exhaustive-match.rs:18:11
+ |
+LL | match (T::A, T::A) {
+ | ^^^^^^^^^^^^ patterns `(T::A, T::A)` and `(T::B, T::B)` not covered
+ |
+ = note: the matched value is of type `(T, T)`
+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 ~ (T::B, T::A) => {}
+LL + (T::A, T::A) | (T::B, T::B) => todo!()
+ |
+
+error[E0004]: non-exhaustive patterns: `T::B` not covered
+ --> $DIR/non-exhaustive-match.rs:22:11
+ |
+LL | match T::A {
+ | ^^^^ pattern `T::B` not covered
+ |
+note: `T` defined here
+ --> $DIR/non-exhaustive-match.rs:3:13
+ |
+LL | enum T { A, B }
+ | - ^ not covered
+ = note: the matched value is of type `T`
+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 ~ T::A => {}
+LL + T::B => todo!()
+ |
+
+error[E0004]: non-exhaustive patterns: `[]` not covered
+ --> $DIR/non-exhaustive-match.rs:33:11
+ |
+LL | match *vec {
+ | ^^^^ pattern `[]` not covered
+ |
+ = note: the matched value is of type `[Option<isize>]`
+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 ~ [None] => {}
+LL + [] => todo!()
+ |
+
+error[E0004]: non-exhaustive patterns: `[_, _, _, _, ..]` not covered
+ --> $DIR/non-exhaustive-match.rs:46:11
+ |
+LL | match *vec {
+ | ^^^^ pattern `[_, _, _, _, ..]` not covered
+ |
+ = note: the matched value is of type `[f32]`
+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 ~ [] => (),
+LL + [_, _, _, _, ..] => todo!()
+ |
+
+error: aborting due to 8 previous errors
+
+For more information about this error, try `rustc --explain E0004`.
diff --git a/tests/ui/pattern/usefulness/non-exhaustive-pattern-witness.rs b/tests/ui/pattern/usefulness/non-exhaustive-pattern-witness.rs
new file mode 100644
index 000000000..4bd344219
--- /dev/null
+++ b/tests/ui/pattern/usefulness/non-exhaustive-pattern-witness.rs
@@ -0,0 +1,89 @@
+struct Foo {
+ first: bool,
+ second: Option<[usize; 4]>
+}
+
+fn struct_with_a_nested_enum_and_vector() {
+ match (Foo { first: true, second: None }) {
+//~^ ERROR non-exhaustive patterns: `Foo { first: false, second: Some([_, _, _, _]) }` not covered
+ Foo { first: true, second: None } => (),
+ Foo { first: true, second: Some(_) } => (),
+ Foo { first: false, second: None } => (),
+ Foo { first: false, second: Some([1, 2, 3, 4]) } => ()
+ }
+}
+
+enum Color {
+ Red,
+ Green,
+ CustomRGBA { a: bool, r: u8, g: u8, b: u8 }
+}
+
+fn enum_with_single_missing_variant() {
+ match Color::Red {
+ //~^ ERROR non-exhaustive patterns: `Color::Red` not covered
+ Color::CustomRGBA { .. } => (),
+ Color::Green => ()
+ }
+}
+
+enum Direction {
+ North, East, South, West
+}
+
+fn enum_with_multiple_missing_variants() {
+ match Direction::North {
+ //~^ ERROR non-exhaustive patterns: `Direction::East`, `Direction::South` and `Direction::West` not covered
+ Direction::North => ()
+ }
+}
+
+enum ExcessiveEnum {
+ First, Second, Third, Fourth, Fifth, Sixth, Seventh, Eighth, Ninth, Tenth, Eleventh, Twelfth
+}
+
+fn enum_with_excessive_missing_variants() {
+ match ExcessiveEnum::First {
+ //~^ ERROR `ExcessiveEnum::Second`, `ExcessiveEnum::Third`, `ExcessiveEnum::Fourth` and 8 more not covered
+
+ ExcessiveEnum::First => ()
+ }
+}
+
+fn enum_struct_variant() {
+ match Color::Red {
+ //~^ ERROR non-exhaustive patterns: `Color::CustomRGBA { a: true, .. }` not covered
+ Color::Red => (),
+ Color::Green => (),
+ Color::CustomRGBA { a: false, r: _, g: _, b: 0 } => (),
+ Color::CustomRGBA { a: false, r: _, g: _, b: _ } => ()
+ }
+}
+
+enum Enum {
+ First,
+ Second(bool)
+}
+
+fn vectors_with_nested_enums() {
+ let x: &'static [Enum] = &[Enum::First, Enum::Second(false)];
+ match *x {
+ //~^ ERROR non-exhaustive patterns: `[Enum::Second(true), Enum::Second(false)]` not covered
+ [] => (),
+ [_] => (),
+ [Enum::First, _] => (),
+ [Enum::Second(true), Enum::First] => (),
+ [Enum::Second(true), Enum::Second(true)] => (),
+ [Enum::Second(false), _] => (),
+ [_, _, ref tail @ .., _] => ()
+ }
+}
+
+fn missing_nil() {
+ match ((), false) {
+ //~^ ERROR non-exhaustive patterns: `((), false)` not covered
+ ((), true) => ()
+ }
+}
+
+fn main() {}
diff --git a/tests/ui/pattern/usefulness/non-exhaustive-pattern-witness.stderr b/tests/ui/pattern/usefulness/non-exhaustive-pattern-witness.stderr
new file mode 100644
index 000000000..b8af566de
--- /dev/null
+++ b/tests/ui/pattern/usefulness/non-exhaustive-pattern-witness.stderr
@@ -0,0 +1,129 @@
+error[E0004]: non-exhaustive patterns: `Foo { first: false, second: Some([_, _, _, _]) }` not covered
+ --> $DIR/non-exhaustive-pattern-witness.rs:7:11
+ |
+LL | match (Foo { first: true, second: None }) {
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ pattern `Foo { first: false, second: Some([_, _, _, _]) }` not covered
+ |
+note: `Foo` defined here
+ --> $DIR/non-exhaustive-pattern-witness.rs:1:8
+ |
+LL | struct Foo {
+ | ^^^
+ = note: the matched value is of type `Foo`
+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 ~ Foo { first: false, second: Some([1, 2, 3, 4]) } => (),
+LL + Foo { first: false, second: Some([_, _, _, _]) } => todo!()
+ |
+
+error[E0004]: non-exhaustive patterns: `Color::Red` not covered
+ --> $DIR/non-exhaustive-pattern-witness.rs:23:11
+ |
+LL | match Color::Red {
+ | ^^^^^^^^^^ pattern `Color::Red` not covered
+ |
+note: `Color` defined here
+ --> $DIR/non-exhaustive-pattern-witness.rs:17:5
+ |
+LL | enum Color {
+ | -----
+LL | Red,
+ | ^^^ not covered
+ = note: the matched value is of type `Color`
+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 ~ Color::Green => (),
+LL + Color::Red => todo!()
+ |
+
+error[E0004]: non-exhaustive patterns: `Direction::East`, `Direction::South` and `Direction::West` not covered
+ --> $DIR/non-exhaustive-pattern-witness.rs:35:11
+ |
+LL | match Direction::North {
+ | ^^^^^^^^^^^^^^^^ patterns `Direction::East`, `Direction::South` and `Direction::West` not covered
+ |
+note: `Direction` defined here
+ --> $DIR/non-exhaustive-pattern-witness.rs:31:12
+ |
+LL | enum Direction {
+ | ---------
+LL | North, East, South, West
+ | ^^^^ ^^^^^ ^^^^ not covered
+ | | |
+ | | not covered
+ | not covered
+ = note: the matched value is of type `Direction`
+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 ~ Direction::North => (),
+LL + Direction::East | Direction::South | Direction::West => todo!()
+ |
+
+error[E0004]: non-exhaustive patterns: `ExcessiveEnum::Second`, `ExcessiveEnum::Third`, `ExcessiveEnum::Fourth` and 8 more not covered
+ --> $DIR/non-exhaustive-pattern-witness.rs:46:11
+ |
+LL | match ExcessiveEnum::First {
+ | ^^^^^^^^^^^^^^^^^^^^ patterns `ExcessiveEnum::Second`, `ExcessiveEnum::Third`, `ExcessiveEnum::Fourth` and 8 more not covered
+ |
+note: `ExcessiveEnum` defined here
+ --> $DIR/non-exhaustive-pattern-witness.rs:41:6
+ |
+LL | enum ExcessiveEnum {
+ | ^^^^^^^^^^^^^
+ = note: the matched value is of type `ExcessiveEnum`
+help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern as shown, or multiple match arms
+ |
+LL ~ ExcessiveEnum::First => (),
+LL + _ => todo!()
+ |
+
+error[E0004]: non-exhaustive patterns: `Color::CustomRGBA { a: true, .. }` not covered
+ --> $DIR/non-exhaustive-pattern-witness.rs:54:11
+ |
+LL | match Color::Red {
+ | ^^^^^^^^^^ pattern `Color::CustomRGBA { a: true, .. }` not covered
+ |
+note: `Color` defined here
+ --> $DIR/non-exhaustive-pattern-witness.rs:19:5
+ |
+LL | enum Color {
+ | -----
+...
+LL | CustomRGBA { a: bool, r: u8, g: u8, b: u8 }
+ | ^^^^^^^^^^ not covered
+ = note: the matched value is of type `Color`
+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 ~ Color::CustomRGBA { a: false, r: _, g: _, b: _ } => (),
+LL + Color::CustomRGBA { a: true, .. } => todo!()
+ |
+
+error[E0004]: non-exhaustive patterns: `[Enum::Second(true), Enum::Second(false)]` not covered
+ --> $DIR/non-exhaustive-pattern-witness.rs:70:11
+ |
+LL | match *x {
+ | ^^ pattern `[Enum::Second(true), Enum::Second(false)]` not covered
+ |
+ = note: the matched value is of type `[Enum]`
+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 ~ [_, _, ref tail @ .., _] => (),
+LL + [Enum::Second(true), Enum::Second(false)] => todo!()
+ |
+
+error[E0004]: non-exhaustive patterns: `((), false)` not covered
+ --> $DIR/non-exhaustive-pattern-witness.rs:83:11
+ |
+LL | match ((), false) {
+ | ^^^^^^^^^^^ pattern `((), false)` not covered
+ |
+ = note: the matched value is of type `((), bool)`
+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 ~ ((), true) => (),
+LL + ((), false) => todo!()
+ |
+
+error: aborting due to 7 previous errors
+
+For more information about this error, try `rustc --explain E0004`.
diff --git a/tests/ui/pattern/usefulness/refutable-pattern-errors.rs b/tests/ui/pattern/usefulness/refutable-pattern-errors.rs
new file mode 100644
index 000000000..7a3e991d5
--- /dev/null
+++ b/tests/ui/pattern/usefulness/refutable-pattern-errors.rs
@@ -0,0 +1,9 @@
+fn func((1, (Some(1), 2..=3)): (isize, (Option<isize>, isize))) { }
+//~^ ERROR refutable pattern in function argument
+//~| `(_, _)` not covered
+
+fn main() {
+ let (1, (Some(1), 2..=3)) = (1, (None, 2));
+ //~^ ERROR refutable pattern in local binding
+ //~| `(i32::MIN..=0_i32, _)` and `(2_i32..=i32::MAX, _)` not covered
+}
diff --git a/tests/ui/pattern/usefulness/refutable-pattern-errors.stderr b/tests/ui/pattern/usefulness/refutable-pattern-errors.stderr
new file mode 100644
index 000000000..c518de477
--- /dev/null
+++ b/tests/ui/pattern/usefulness/refutable-pattern-errors.stderr
@@ -0,0 +1,25 @@
+error[E0005]: refutable pattern in function argument
+ --> $DIR/refutable-pattern-errors.rs:1:9
+ |
+LL | fn func((1, (Some(1), 2..=3)): (isize, (Option<isize>, isize))) { }
+ | ^^^^^^^^^^^^^^^^^^^^^ pattern `(_, _)` not covered
+ |
+ = note: the matched value is of type `(isize, (Option<isize>, isize))`
+
+error[E0005]: refutable pattern in local binding
+ --> $DIR/refutable-pattern-errors.rs:6:9
+ |
+LL | let (1, (Some(1), 2..=3)) = (1, (None, 2));
+ | ^^^^^^^^^^^^^^^^^^^^^ patterns `(i32::MIN..=0_i32, _)` and `(2_i32..=i32::MAX, _)` not covered
+ |
+ = note: `let` bindings require an "irrefutable pattern", like a `struct` or an `enum` with only one variant
+ = note: for more information, visit https://doc.rust-lang.org/book/ch18-02-refutability.html
+ = note: the matched value is of type `(i32, (Option<i32>, i32))`
+help: you might want to use `if let` to ignore the variants that aren't matched
+ |
+LL | if let (1, (Some(1), 2..=3)) = (1, (None, 2)) { todo!() }
+ | ++ ~~~~~~~~~~~
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0005`.
diff --git a/tests/ui/pattern/usefulness/refutable-pattern-in-fn-arg.rs b/tests/ui/pattern/usefulness/refutable-pattern-in-fn-arg.rs
new file mode 100644
index 000000000..17dc38ab2
--- /dev/null
+++ b/tests/ui/pattern/usefulness/refutable-pattern-in-fn-arg.rs
@@ -0,0 +1,6 @@
+fn main() {
+ let f = |3: isize| println!("hello");
+ //~^ ERROR refutable pattern in function argument
+ //~| `_` not covered
+ f(4);
+}
diff --git a/tests/ui/pattern/usefulness/refutable-pattern-in-fn-arg.stderr b/tests/ui/pattern/usefulness/refutable-pattern-in-fn-arg.stderr
new file mode 100644
index 000000000..55f0b2319
--- /dev/null
+++ b/tests/ui/pattern/usefulness/refutable-pattern-in-fn-arg.stderr
@@ -0,0 +1,11 @@
+error[E0005]: refutable pattern in function argument
+ --> $DIR/refutable-pattern-in-fn-arg.rs:2:14
+ |
+LL | let f = |3: isize| println!("hello");
+ | ^ pattern `_` not covered
+ |
+ = note: the matched value is of type `isize`
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0005`.
diff --git a/tests/ui/pattern/usefulness/slice-pattern-const-2.rs b/tests/ui/pattern/usefulness/slice-pattern-const-2.rs
new file mode 100644
index 000000000..4bf8d0fd2
--- /dev/null
+++ b/tests/ui/pattern/usefulness/slice-pattern-const-2.rs
@@ -0,0 +1,31 @@
+#![deny(unreachable_patterns)]
+
+fn main() {
+ let s = &[0x00; 4][..]; //Slice of any value
+ const MAGIC_TEST: &[u32] = &[4, 5, 6, 7]; //Const slice to pattern match with
+ match s {
+ MAGIC_TEST => (),
+ [0x00, 0x00, 0x00, 0x00] => (),
+ [4, 5, 6, 7] => (), //~ ERROR unreachable pattern
+ _ => (),
+ }
+ match s {
+ [0x00, 0x00, 0x00, 0x00] => (),
+ MAGIC_TEST => (),
+ [4, 5, 6, 7] => (), //~ ERROR unreachable pattern
+ _ => (),
+ }
+ match s {
+ [0x00, 0x00, 0x00, 0x00] => (),
+ [4, 5, 6, 7] => (),
+ MAGIC_TEST => (), //~ ERROR unreachable pattern
+ _ => (),
+ }
+ const FOO: [u32; 1] = [4];
+ match [99] {
+ [0x00] => (),
+ [4] => (),
+ FOO => (), //~ ERROR unreachable pattern
+ _ => (),
+ }
+}
diff --git a/tests/ui/pattern/usefulness/slice-pattern-const-2.stderr b/tests/ui/pattern/usefulness/slice-pattern-const-2.stderr
new file mode 100644
index 000000000..dcad11a38
--- /dev/null
+++ b/tests/ui/pattern/usefulness/slice-pattern-const-2.stderr
@@ -0,0 +1,32 @@
+error: unreachable pattern
+ --> $DIR/slice-pattern-const-2.rs:9:9
+ |
+LL | [4, 5, 6, 7] => (),
+ | ^^^^^^^^^^^^
+ |
+note: the lint level is defined here
+ --> $DIR/slice-pattern-const-2.rs:1:9
+ |
+LL | #![deny(unreachable_patterns)]
+ | ^^^^^^^^^^^^^^^^^^^^
+
+error: unreachable pattern
+ --> $DIR/slice-pattern-const-2.rs:15:9
+ |
+LL | [4, 5, 6, 7] => (),
+ | ^^^^^^^^^^^^
+
+error: unreachable pattern
+ --> $DIR/slice-pattern-const-2.rs:21:9
+ |
+LL | MAGIC_TEST => (),
+ | ^^^^^^^^^^
+
+error: unreachable pattern
+ --> $DIR/slice-pattern-const-2.rs:28:9
+ |
+LL | FOO => (),
+ | ^^^
+
+error: aborting due to 4 previous errors
+
diff --git a/tests/ui/pattern/usefulness/slice-pattern-const-3.rs b/tests/ui/pattern/usefulness/slice-pattern-const-3.rs
new file mode 100644
index 000000000..2ca8323f0
--- /dev/null
+++ b/tests/ui/pattern/usefulness/slice-pattern-const-3.rs
@@ -0,0 +1,31 @@
+#![deny(unreachable_patterns)]
+
+fn main() {
+ let s = &["0x00"; 4][..]; //Slice of any value
+ const MAGIC_TEST: &[&str] = &["4", "5", "6", "7"]; //Const slice to pattern match with
+ match s {
+ MAGIC_TEST => (),
+ ["0x00", "0x00", "0x00", "0x00"] => (),
+ ["4", "5", "6", "7"] => (), //~ ERROR unreachable pattern
+ _ => (),
+ }
+ match s {
+ ["0x00", "0x00", "0x00", "0x00"] => (),
+ MAGIC_TEST => (),
+ ["4", "5", "6", "7"] => (), //~ ERROR unreachable pattern
+ _ => (),
+ }
+ match s {
+ ["0x00", "0x00", "0x00", "0x00"] => (),
+ ["4", "5", "6", "7"] => (),
+ MAGIC_TEST => (), //~ ERROR unreachable pattern
+ _ => (),
+ }
+ const FOO: [&str; 1] = ["boo"];
+ match ["baa"] {
+ ["0x00"] => (),
+ ["boo"] => (),
+ FOO => (), //~ ERROR unreachable pattern
+ _ => (),
+ }
+}
diff --git a/tests/ui/pattern/usefulness/slice-pattern-const-3.stderr b/tests/ui/pattern/usefulness/slice-pattern-const-3.stderr
new file mode 100644
index 000000000..b90b3a88a
--- /dev/null
+++ b/tests/ui/pattern/usefulness/slice-pattern-const-3.stderr
@@ -0,0 +1,32 @@
+error: unreachable pattern
+ --> $DIR/slice-pattern-const-3.rs:9:9
+ |
+LL | ["4", "5", "6", "7"] => (),
+ | ^^^^^^^^^^^^^^^^^^^^
+ |
+note: the lint level is defined here
+ --> $DIR/slice-pattern-const-3.rs:1:9
+ |
+LL | #![deny(unreachable_patterns)]
+ | ^^^^^^^^^^^^^^^^^^^^
+
+error: unreachable pattern
+ --> $DIR/slice-pattern-const-3.rs:15:9
+ |
+LL | ["4", "5", "6", "7"] => (),
+ | ^^^^^^^^^^^^^^^^^^^^
+
+error: unreachable pattern
+ --> $DIR/slice-pattern-const-3.rs:21:9
+ |
+LL | MAGIC_TEST => (),
+ | ^^^^^^^^^^
+
+error: unreachable pattern
+ --> $DIR/slice-pattern-const-3.rs:28:9
+ |
+LL | FOO => (),
+ | ^^^
+
+error: aborting due to 4 previous errors
+
diff --git a/tests/ui/pattern/usefulness/slice-pattern-const.rs b/tests/ui/pattern/usefulness/slice-pattern-const.rs
new file mode 100644
index 000000000..89195d5b1
--- /dev/null
+++ b/tests/ui/pattern/usefulness/slice-pattern-const.rs
@@ -0,0 +1,54 @@
+#![deny(unreachable_patterns)]
+
+fn main() {
+ let s = &[0x00; 4][..]; //Slice of any value
+ const MAGIC_TEST: &[u8] = b"TEST"; //Const slice to pattern match with
+ match s {
+ MAGIC_TEST => (),
+ [0x00, 0x00, 0x00, 0x00] => (),
+ [84, 69, 83, 84] => (), //~ ERROR unreachable pattern
+ _ => (),
+ }
+ match s {
+ [0x00, 0x00, 0x00, 0x00] => (),
+ MAGIC_TEST => (),
+ [84, 69, 83, 84] => (), //~ ERROR unreachable pattern
+ _ => (),
+ }
+ match s {
+ [0x00, 0x00, 0x00, 0x00] => (),
+ [84, 69, 83, 84] => (),
+ MAGIC_TEST => (), //~ ERROR unreachable pattern
+ _ => (),
+ }
+ const FOO: [u8; 1] = [4];
+ match [99] {
+ [0x00] => (),
+ [4] => (),
+ FOO => (), //~ ERROR unreachable pattern
+ _ => (),
+ }
+ const BAR: &[u8; 1] = &[4];
+ match &[99] {
+ [0x00] => (),
+ [4] => (),
+ BAR => (), //~ ERROR unreachable pattern
+ b"a" => (),
+ _ => (),
+ }
+
+ const BOO: &[u8; 0] = &[];
+ match &[] {
+ [] => (),
+ BOO => (), //~ ERROR unreachable pattern
+ b"" => (), //~ ERROR unreachable pattern
+ _ => (), //~ ERROR unreachable pattern
+ }
+
+ const CONST1: &[bool; 1] = &[true];
+ match &[false] {
+ CONST1 => {}
+ [true] => {} //~ ERROR unreachable pattern
+ [false] => {}
+ }
+}
diff --git a/tests/ui/pattern/usefulness/slice-pattern-const.stderr b/tests/ui/pattern/usefulness/slice-pattern-const.stderr
new file mode 100644
index 000000000..1fffb9fed
--- /dev/null
+++ b/tests/ui/pattern/usefulness/slice-pattern-const.stderr
@@ -0,0 +1,62 @@
+error: unreachable pattern
+ --> $DIR/slice-pattern-const.rs:9:9
+ |
+LL | [84, 69, 83, 84] => (),
+ | ^^^^^^^^^^^^^^^^
+ |
+note: the lint level is defined here
+ --> $DIR/slice-pattern-const.rs:1:9
+ |
+LL | #![deny(unreachable_patterns)]
+ | ^^^^^^^^^^^^^^^^^^^^
+
+error: unreachable pattern
+ --> $DIR/slice-pattern-const.rs:15:9
+ |
+LL | [84, 69, 83, 84] => (),
+ | ^^^^^^^^^^^^^^^^
+
+error: unreachable pattern
+ --> $DIR/slice-pattern-const.rs:21:9
+ |
+LL | MAGIC_TEST => (),
+ | ^^^^^^^^^^
+
+error: unreachable pattern
+ --> $DIR/slice-pattern-const.rs:28:9
+ |
+LL | FOO => (),
+ | ^^^
+
+error: unreachable pattern
+ --> $DIR/slice-pattern-const.rs:35:9
+ |
+LL | BAR => (),
+ | ^^^
+
+error: unreachable pattern
+ --> $DIR/slice-pattern-const.rs:43:9
+ |
+LL | BOO => (),
+ | ^^^
+
+error: unreachable pattern
+ --> $DIR/slice-pattern-const.rs:44:9
+ |
+LL | b"" => (),
+ | ^^^
+
+error: unreachable pattern
+ --> $DIR/slice-pattern-const.rs:45:9
+ |
+LL | _ => (),
+ | ^
+
+error: unreachable pattern
+ --> $DIR/slice-pattern-const.rs:51:9
+ |
+LL | [true] => {}
+ | ^^^^^^
+
+error: aborting due to 9 previous errors
+
diff --git a/tests/ui/pattern/usefulness/slice-patterns-exhaustiveness.rs b/tests/ui/pattern/usefulness/slice-patterns-exhaustiveness.rs
new file mode 100644
index 000000000..46e0da5be
--- /dev/null
+++ b/tests/ui/pattern/usefulness/slice-patterns-exhaustiveness.rs
@@ -0,0 +1,129 @@
+fn main() {
+ let s: &[bool] = &[true; 0];
+ let s1: &[bool; 1] = &[false; 1];
+ let s2: &[bool; 2] = &[false; 2];
+ let s3: &[bool; 3] = &[false; 3];
+ let s10: &[bool; 10] = &[false; 10];
+
+ match s2 {
+ //~^ ERROR `&[false, _]` not covered
+ [true, .., true] => {}
+ }
+ match s3 {
+ //~^ ERROR `&[false, ..]` not covered
+ [true, .., true] => {}
+ }
+ match s10 {
+ //~^ ERROR `&[false, ..]` not covered
+ [true, .., true] => {}
+ }
+
+ match s1 {
+ [true, ..] => {}
+ [.., false] => {}
+ }
+ match s2 {
+ //~^ ERROR `&[false, true]` not covered
+ [true, ..] => {}
+ [.., false] => {}
+ }
+ match s3 {
+ //~^ ERROR `&[false, .., true]` not covered
+ [true, ..] => {}
+ [.., false] => {}
+ }
+ match s {
+ //~^ ERROR `&[false, .., true]` not covered
+ [] => {}
+ [true, ..] => {}
+ [.., false] => {}
+ }
+
+ match s {
+ //~^ ERROR `&[_, ..]` not covered
+ [] => {}
+ }
+ match s {
+ //~^ ERROR `&[_, _, ..]` not covered
+ [] => {}
+ [_] => {}
+ }
+ match s {
+ //~^ ERROR `&[false, ..]` not covered
+ [] => {}
+ [true, ..] => {}
+ }
+ match s {
+ //~^ ERROR `&[false, _, ..]` not covered
+ [] => {}
+ [_] => {}
+ [true, ..] => {}
+ }
+ match s {
+ //~^ ERROR `&[_, .., false]` not covered
+ [] => {}
+ [_] => {}
+ [.., true] => {}
+ }
+
+ match s {
+ //~^ ERROR `&[_, _, .., true]` not covered
+ [] => {}
+ [_] => {}
+ [_, _] => {}
+ [.., false] => {}
+ }
+ match s {
+ //~^ ERROR `&[true, _, .., _]` not covered
+ [] => {}
+ [_] => {}
+ [_, _] => {}
+ [false, .., false] => {}
+ }
+
+ const CONST: &[bool] = &[true];
+ match s {
+ //~^ ERROR `&[]` and `&[_, _, ..]` not covered
+ &[true] => {}
+ }
+ match s {
+ //~^ ERROR `&[]` and `&[_, _, ..]` not covered
+ CONST => {}
+ }
+ match s {
+ //~^ ERROR `&[]` and `&[_, _, ..]` not covered
+ CONST => {}
+ &[false] => {}
+ }
+ match s {
+ //~^ ERROR `&[]` and `&[_, _, ..]` not covered
+ &[false] => {}
+ CONST => {}
+ }
+ match s {
+ //~^ ERROR `&[_, _, ..]` not covered
+ &[] => {}
+ CONST => {}
+ }
+ match s {
+ //~^ ERROR `&[false]` not covered
+ &[] => {}
+ CONST => {}
+ &[_, _, ..] => {}
+ }
+ match s {
+ [] => {}
+ [false] => {}
+ CONST => {}
+ [_, _, ..] => {}
+ }
+ const CONST1: &[bool; 1] = &[true];
+ match s1 {
+ //~^ ERROR `&[false]` not covered
+ CONST1 => {}
+ }
+ match s1 {
+ CONST1 => {}
+ [false] => {}
+ }
+}
diff --git a/tests/ui/pattern/usefulness/slice-patterns-exhaustiveness.stderr b/tests/ui/pattern/usefulness/slice-patterns-exhaustiveness.stderr
new file mode 100644
index 000000000..5d1e170ae
--- /dev/null
+++ b/tests/ui/pattern/usefulness/slice-patterns-exhaustiveness.stderr
@@ -0,0 +1,263 @@
+error[E0004]: non-exhaustive patterns: `&[false, _]` not covered
+ --> $DIR/slice-patterns-exhaustiveness.rs:8:11
+ |
+LL | match s2 {
+ | ^^ pattern `&[false, _]` not covered
+ |
+ = note: the matched value is of type `&[bool; 2]`
+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 ~ [true, .., true] => {}
+LL + &[false, _] => todo!()
+ |
+
+error[E0004]: non-exhaustive patterns: `&[false, ..]` not covered
+ --> $DIR/slice-patterns-exhaustiveness.rs:12:11
+ |
+LL | match s3 {
+ | ^^ pattern `&[false, ..]` not covered
+ |
+ = note: the matched value is of type `&[bool; 3]`
+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 ~ [true, .., true] => {}
+LL + &[false, ..] => todo!()
+ |
+
+error[E0004]: non-exhaustive patterns: `&[false, ..]` not covered
+ --> $DIR/slice-patterns-exhaustiveness.rs:16:11
+ |
+LL | match s10 {
+ | ^^^ pattern `&[false, ..]` not covered
+ |
+ = note: the matched value is of type `&[bool; 10]`
+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 ~ [true, .., true] => {}
+LL + &[false, ..] => todo!()
+ |
+
+error[E0004]: non-exhaustive patterns: `&[false, true]` not covered
+ --> $DIR/slice-patterns-exhaustiveness.rs:25:11
+ |
+LL | match s2 {
+ | ^^ pattern `&[false, true]` not covered
+ |
+ = note: the matched value is of type `&[bool; 2]`
+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 ~ [.., false] => {}
+LL + &[false, true] => todo!()
+ |
+
+error[E0004]: non-exhaustive patterns: `&[false, .., true]` not covered
+ --> $DIR/slice-patterns-exhaustiveness.rs:30:11
+ |
+LL | match s3 {
+ | ^^ pattern `&[false, .., true]` not covered
+ |
+ = note: the matched value is of type `&[bool; 3]`
+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 ~ [.., false] => {}
+LL + &[false, .., true] => todo!()
+ |
+
+error[E0004]: non-exhaustive patterns: `&[false, .., true]` not covered
+ --> $DIR/slice-patterns-exhaustiveness.rs:35:11
+ |
+LL | match s {
+ | ^ pattern `&[false, .., true]` not covered
+ |
+ = note: the matched value is of type `&[bool]`
+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 ~ [.., false] => {}
+LL + &[false, .., true] => todo!()
+ |
+
+error[E0004]: non-exhaustive patterns: `&[_, ..]` not covered
+ --> $DIR/slice-patterns-exhaustiveness.rs:42:11
+ |
+LL | match s {
+ | ^ pattern `&[_, ..]` not covered
+ |
+ = note: the matched value is of type `&[bool]`
+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 ~ [] => {}
+LL + &[_, ..] => todo!()
+ |
+
+error[E0004]: non-exhaustive patterns: `&[_, _, ..]` not covered
+ --> $DIR/slice-patterns-exhaustiveness.rs:46:11
+ |
+LL | match s {
+ | ^ pattern `&[_, _, ..]` not covered
+ |
+ = note: the matched value is of type `&[bool]`
+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 ~ [_] => {}
+LL + &[_, _, ..] => todo!()
+ |
+
+error[E0004]: non-exhaustive patterns: `&[false, ..]` not covered
+ --> $DIR/slice-patterns-exhaustiveness.rs:51:11
+ |
+LL | match s {
+ | ^ pattern `&[false, ..]` not covered
+ |
+ = note: the matched value is of type `&[bool]`
+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 ~ [true, ..] => {}
+LL + &[false, ..] => todo!()
+ |
+
+error[E0004]: non-exhaustive patterns: `&[false, _, ..]` not covered
+ --> $DIR/slice-patterns-exhaustiveness.rs:56:11
+ |
+LL | match s {
+ | ^ pattern `&[false, _, ..]` not covered
+ |
+ = note: the matched value is of type `&[bool]`
+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 ~ [true, ..] => {}
+LL + &[false, _, ..] => todo!()
+ |
+
+error[E0004]: non-exhaustive patterns: `&[_, .., false]` not covered
+ --> $DIR/slice-patterns-exhaustiveness.rs:62:11
+ |
+LL | match s {
+ | ^ pattern `&[_, .., false]` not covered
+ |
+ = note: the matched value is of type `&[bool]`
+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 ~ [.., true] => {}
+LL + &[_, .., false] => todo!()
+ |
+
+error[E0004]: non-exhaustive patterns: `&[_, _, .., true]` not covered
+ --> $DIR/slice-patterns-exhaustiveness.rs:69:11
+ |
+LL | match s {
+ | ^ pattern `&[_, _, .., true]` not covered
+ |
+ = note: the matched value is of type `&[bool]`
+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 ~ [.., false] => {}
+LL + &[_, _, .., true] => todo!()
+ |
+
+error[E0004]: non-exhaustive patterns: `&[true, _, .., _]` not covered
+ --> $DIR/slice-patterns-exhaustiveness.rs:76:11
+ |
+LL | match s {
+ | ^ pattern `&[true, _, .., _]` not covered
+ |
+ = note: the matched value is of type `&[bool]`
+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 ~ [false, .., false] => {}
+LL + &[true, _, .., _] => todo!()
+ |
+
+error[E0004]: non-exhaustive patterns: `&[]` and `&[_, _, ..]` not covered
+ --> $DIR/slice-patterns-exhaustiveness.rs:85:11
+ |
+LL | match s {
+ | ^ patterns `&[]` and `&[_, _, ..]` not covered
+ |
+ = note: the matched value is of type `&[bool]`
+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 ~ &[true] => {}
+LL + &[] | &[_, _, ..] => todo!()
+ |
+
+error[E0004]: non-exhaustive patterns: `&[]` and `&[_, _, ..]` not covered
+ --> $DIR/slice-patterns-exhaustiveness.rs:89:11
+ |
+LL | match s {
+ | ^ patterns `&[]` and `&[_, _, ..]` not covered
+ |
+ = note: the matched value is of type `&[bool]`
+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 ~ CONST => {}
+LL + &[] | &[_, _, ..] => todo!()
+ |
+
+error[E0004]: non-exhaustive patterns: `&[]` and `&[_, _, ..]` not covered
+ --> $DIR/slice-patterns-exhaustiveness.rs:93:11
+ |
+LL | match s {
+ | ^ patterns `&[]` and `&[_, _, ..]` not covered
+ |
+ = note: the matched value is of type `&[bool]`
+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 ~ &[false] => {}
+LL + &[] | &[_, _, ..] => todo!()
+ |
+
+error[E0004]: non-exhaustive patterns: `&[]` and `&[_, _, ..]` not covered
+ --> $DIR/slice-patterns-exhaustiveness.rs:98:11
+ |
+LL | match s {
+ | ^ patterns `&[]` and `&[_, _, ..]` not covered
+ |
+ = note: the matched value is of type `&[bool]`
+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 ~ CONST => {}
+LL + &[] | &[_, _, ..] => todo!()
+ |
+
+error[E0004]: non-exhaustive patterns: `&[_, _, ..]` not covered
+ --> $DIR/slice-patterns-exhaustiveness.rs:103:11
+ |
+LL | match s {
+ | ^ pattern `&[_, _, ..]` not covered
+ |
+ = note: the matched value is of type `&[bool]`
+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 ~ CONST => {}
+LL + &[_, _, ..] => todo!()
+ |
+
+error[E0004]: non-exhaustive patterns: `&[false]` not covered
+ --> $DIR/slice-patterns-exhaustiveness.rs:108:11
+ |
+LL | match s {
+ | ^ pattern `&[false]` not covered
+ |
+ = note: the matched value is of type `&[bool]`
+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 ~ &[_, _, ..] => {}
+LL + &[false] => todo!()
+ |
+
+error[E0004]: non-exhaustive patterns: `&[false]` not covered
+ --> $DIR/slice-patterns-exhaustiveness.rs:121:11
+ |
+LL | match s1 {
+ | ^^ pattern `&[false]` not covered
+ |
+ = note: the matched value is of type `&[bool; 1]`
+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 ~ CONST1 => {}
+LL + &[false] => todo!()
+ |
+
+error: aborting due to 20 previous errors
+
+For more information about this error, try `rustc --explain E0004`.
diff --git a/tests/ui/pattern/usefulness/slice-patterns-irrefutable.rs b/tests/ui/pattern/usefulness/slice-patterns-irrefutable.rs
new file mode 100644
index 000000000..cbf64e2c5
--- /dev/null
+++ b/tests/ui/pattern/usefulness/slice-patterns-irrefutable.rs
@@ -0,0 +1,26 @@
+// check-pass
+
+fn main() {
+ let s: &[bool] = &[true; 0];
+ let s0: &[bool; 0] = &[];
+ let s1: &[bool; 1] = &[false; 1];
+ let s2: &[bool; 2] = &[false; 2];
+
+ let [] = s0;
+ let [_] = s1;
+ let [_, _] = s2;
+
+ let [..] = s;
+ let [..] = s0;
+ let [..] = s1;
+ let [..] = s2;
+
+ let [_, ..] = s1;
+ let [.., _] = s1;
+ let [_, ..] = s2;
+ let [.., _] = s2;
+
+ let [_, _, ..] = s2;
+ let [_, .., _] = s2;
+ let [.., _, _] = s2;
+}
diff --git a/tests/ui/pattern/usefulness/slice-patterns-reachability.rs b/tests/ui/pattern/usefulness/slice-patterns-reachability.rs
new file mode 100644
index 000000000..7c747b5e0
--- /dev/null
+++ b/tests/ui/pattern/usefulness/slice-patterns-reachability.rs
@@ -0,0 +1,25 @@
+#![deny(unreachable_patterns)]
+
+fn main() {
+ let s: &[bool] = &[];
+
+ match s {
+ [true, ..] => {}
+ [true, ..] => {} //~ ERROR unreachable pattern
+ [true] => {} //~ ERROR unreachable pattern
+ [..] => {}
+ }
+ match s {
+ [.., true] => {}
+ [.., true] => {} //~ ERROR unreachable pattern
+ [true] => {} //~ ERROR unreachable pattern
+ [..] => {}
+ }
+ match s {
+ [false, .., true] => {}
+ [false, .., true] => {} //~ ERROR unreachable pattern
+ [false, true] => {} //~ ERROR unreachable pattern
+ [false] => {}
+ [..] => {}
+ }
+}
diff --git a/tests/ui/pattern/usefulness/slice-patterns-reachability.stderr b/tests/ui/pattern/usefulness/slice-patterns-reachability.stderr
new file mode 100644
index 000000000..607ffb765
--- /dev/null
+++ b/tests/ui/pattern/usefulness/slice-patterns-reachability.stderr
@@ -0,0 +1,44 @@
+error: unreachable pattern
+ --> $DIR/slice-patterns-reachability.rs:8:9
+ |
+LL | [true, ..] => {}
+ | ^^^^^^^^^^
+ |
+note: the lint level is defined here
+ --> $DIR/slice-patterns-reachability.rs:1:9
+ |
+LL | #![deny(unreachable_patterns)]
+ | ^^^^^^^^^^^^^^^^^^^^
+
+error: unreachable pattern
+ --> $DIR/slice-patterns-reachability.rs:9:9
+ |
+LL | [true] => {}
+ | ^^^^^^
+
+error: unreachable pattern
+ --> $DIR/slice-patterns-reachability.rs:14:9
+ |
+LL | [.., true] => {}
+ | ^^^^^^^^^^
+
+error: unreachable pattern
+ --> $DIR/slice-patterns-reachability.rs:15:9
+ |
+LL | [true] => {}
+ | ^^^^^^
+
+error: unreachable pattern
+ --> $DIR/slice-patterns-reachability.rs:20:9
+ |
+LL | [false, .., true] => {}
+ | ^^^^^^^^^^^^^^^^^
+
+error: unreachable pattern
+ --> $DIR/slice-patterns-reachability.rs:21:9
+ |
+LL | [false, true] => {}
+ | ^^^^^^^^^^^^^
+
+error: aborting due to 6 previous errors
+
diff --git a/tests/ui/pattern/usefulness/stable-gated-fields.rs b/tests/ui/pattern/usefulness/stable-gated-fields.rs
new file mode 100644
index 000000000..90f40a8d6
--- /dev/null
+++ b/tests/ui/pattern/usefulness/stable-gated-fields.rs
@@ -0,0 +1,16 @@
+// aux-build:unstable.rs
+
+extern crate unstable;
+
+use unstable::UnstableStruct;
+
+fn main() {
+ let UnstableStruct { stable } = UnstableStruct::default();
+ //~^ pattern does not mention field `stable2` and inaccessible fields
+
+ let UnstableStruct { stable, stable2 } = UnstableStruct::default();
+ //~^ pattern requires `..` due to inaccessible fields
+
+ // OK: stable field is matched
+ let UnstableStruct { stable, stable2, .. } = UnstableStruct::default();
+}
diff --git a/tests/ui/pattern/usefulness/stable-gated-fields.stderr b/tests/ui/pattern/usefulness/stable-gated-fields.stderr
new file mode 100644
index 000000000..cf98c51a2
--- /dev/null
+++ b/tests/ui/pattern/usefulness/stable-gated-fields.stderr
@@ -0,0 +1,29 @@
+error[E0027]: pattern does not mention field `stable2` and inaccessible fields
+ --> $DIR/stable-gated-fields.rs:8:9
+ |
+LL | let UnstableStruct { stable } = UnstableStruct::default();
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^ missing field `stable2` and inaccessible fields
+ |
+help: include the missing field in the pattern and ignore the inaccessible fields
+ |
+LL | let UnstableStruct { stable, stable2, .. } = UnstableStruct::default();
+ | ~~~~~~~~~~~~~~~
+help: if you don't care about this missing field, you can explicitly ignore it
+ |
+LL | let UnstableStruct { stable, .. } = UnstableStruct::default();
+ | ~~~~~~
+
+error: pattern requires `..` due to inaccessible fields
+ --> $DIR/stable-gated-fields.rs:11:9
+ |
+LL | let UnstableStruct { stable, stable2 } = UnstableStruct::default();
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+ |
+help: ignore the inaccessible and unused fields
+ |
+LL | let UnstableStruct { stable, stable2, .. } = UnstableStruct::default();
+ | ++++
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0027`.
diff --git a/tests/ui/pattern/usefulness/stable-gated-patterns.rs b/tests/ui/pattern/usefulness/stable-gated-patterns.rs
new file mode 100644
index 000000000..03db01160
--- /dev/null
+++ b/tests/ui/pattern/usefulness/stable-gated-patterns.rs
@@ -0,0 +1,18 @@
+// aux-build:unstable.rs
+
+extern crate unstable;
+
+use unstable::UnstableEnum;
+
+fn main() {
+ match UnstableEnum::Stable {
+ UnstableEnum::Stable => {}
+ }
+ //~^^^ non-exhaustive patterns: `UnstableEnum::Stable2` and `_` not covered
+
+ match UnstableEnum::Stable {
+ UnstableEnum::Stable => {}
+ UnstableEnum::Stable2 => {}
+ }
+ //~^^^^ non-exhaustive patterns: `_` not covered
+}
diff --git a/tests/ui/pattern/usefulness/stable-gated-patterns.stderr b/tests/ui/pattern/usefulness/stable-gated-patterns.stderr
new file mode 100644
index 000000000..7b8588a3c
--- /dev/null
+++ b/tests/ui/pattern/usefulness/stable-gated-patterns.stderr
@@ -0,0 +1,42 @@
+error[E0004]: non-exhaustive patterns: `UnstableEnum::Stable2` and `_` not covered
+ --> $DIR/stable-gated-patterns.rs:8:11
+ |
+LL | match UnstableEnum::Stable {
+ | ^^^^^^^^^^^^^^^^^^^^ patterns `UnstableEnum::Stable2` and `_` not covered
+ |
+note: `UnstableEnum` defined here
+ --> $DIR/auxiliary/unstable.rs:9:5
+ |
+LL | pub enum UnstableEnum {
+ | ---------------------
+...
+LL | Stable2,
+ | ^^^^^^^ not covered
+ = note: the matched value is of type `UnstableEnum`
+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 ~ UnstableEnum::Stable => {}
+LL + UnstableEnum::Stable2 | _ => todo!()
+ |
+
+error[E0004]: non-exhaustive patterns: `_` not covered
+ --> $DIR/stable-gated-patterns.rs:13:11
+ |
+LL | match UnstableEnum::Stable {
+ | ^^^^^^^^^^^^^^^^^^^^ pattern `_` not covered
+ |
+note: `UnstableEnum` defined here
+ --> $DIR/auxiliary/unstable.rs:5:1
+ |
+LL | pub enum UnstableEnum {
+ | ^^^^^^^^^^^^^^^^^^^^^
+ = note: the matched value is of type `UnstableEnum`
+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 ~ UnstableEnum::Stable2 => {}
+LL + _ => todo!()
+ |
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0004`.
diff --git a/tests/ui/pattern/usefulness/struct-like-enum-nonexhaustive.rs b/tests/ui/pattern/usefulness/struct-like-enum-nonexhaustive.rs
new file mode 100644
index 000000000..b1fc0f5ad
--- /dev/null
+++ b/tests/ui/pattern/usefulness/struct-like-enum-nonexhaustive.rs
@@ -0,0 +1,12 @@
+enum A {
+ B { x: Option<isize> },
+ C
+}
+
+fn main() {
+ let x = A::B { x: Some(3) };
+ match x { //~ ERROR non-exhaustive patterns
+ A::C => {}
+ A::B { x: None } => {}
+ }
+}
diff --git a/tests/ui/pattern/usefulness/struct-like-enum-nonexhaustive.stderr b/tests/ui/pattern/usefulness/struct-like-enum-nonexhaustive.stderr
new file mode 100644
index 000000000..85c97be29
--- /dev/null
+++ b/tests/ui/pattern/usefulness/struct-like-enum-nonexhaustive.stderr
@@ -0,0 +1,23 @@
+error[E0004]: non-exhaustive patterns: `A::B { x: Some(_) }` not covered
+ --> $DIR/struct-like-enum-nonexhaustive.rs:8:11
+ |
+LL | match x {
+ | ^ pattern `A::B { x: Some(_) }` not covered
+ |
+note: `A` defined here
+ --> $DIR/struct-like-enum-nonexhaustive.rs:2:5
+ |
+LL | enum A {
+ | -
+LL | B { x: Option<isize> },
+ | ^ not covered
+ = note: the matched value is of type `A`
+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 ~ A::B { x: None } => {}
+LL + A::B { x: Some(_) } => todo!()
+ |
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0004`.
diff --git a/tests/ui/pattern/usefulness/struct-pattern-match-useless.rs b/tests/ui/pattern/usefulness/struct-pattern-match-useless.rs
new file mode 100644
index 000000000..93f0a9317
--- /dev/null
+++ b/tests/ui/pattern/usefulness/struct-pattern-match-useless.rs
@@ -0,0 +1,15 @@
+#![deny(unreachable_patterns)]
+
+struct Foo {
+ x: isize,
+ y: isize,
+}
+
+pub fn main() {
+ let a = Foo { x: 1, y: 2 };
+ match a {
+ Foo { x: _x, y: _y } => (),
+ Foo { .. } => () //~ ERROR unreachable pattern
+ }
+
+}
diff --git a/tests/ui/pattern/usefulness/struct-pattern-match-useless.stderr b/tests/ui/pattern/usefulness/struct-pattern-match-useless.stderr
new file mode 100644
index 000000000..fbee33de6
--- /dev/null
+++ b/tests/ui/pattern/usefulness/struct-pattern-match-useless.stderr
@@ -0,0 +1,16 @@
+error: unreachable pattern
+ --> $DIR/struct-pattern-match-useless.rs:12:9
+ |
+LL | Foo { x: _x, y: _y } => (),
+ | -------------------- matches any value
+LL | Foo { .. } => ()
+ | ^^^^^^^^^^ unreachable pattern
+ |
+note: the lint level is defined here
+ --> $DIR/struct-pattern-match-useless.rs:1:9
+ |
+LL | #![deny(unreachable_patterns)]
+ | ^^^^^^^^^^^^^^^^^^^^
+
+error: aborting due to previous error
+
diff --git a/tests/ui/pattern/usefulness/top-level-alternation.rs b/tests/ui/pattern/usefulness/top-level-alternation.rs
new file mode 100644
index 000000000..e8cd12ea4
--- /dev/null
+++ b/tests/ui/pattern/usefulness/top-level-alternation.rs
@@ -0,0 +1,57 @@
+#![deny(unreachable_patterns)]
+
+fn main() {
+ while let 0..=2 | 1 = 0 {} //~ ERROR unreachable pattern
+ if let 0..=2 | 1 = 0 {} //~ ERROR unreachable pattern
+
+ match 0u8 {
+ 0
+ | 0 => {} //~ ERROR unreachable pattern
+ _ => {}
+ }
+ match Some(0u8) {
+ Some(0)
+ | Some(0) => {} //~ ERROR unreachable pattern
+ _ => {}
+ }
+ match (0u8, 0u8) {
+ (0, _) | (_, 0) => {}
+ (0, 0) => {} //~ ERROR unreachable pattern
+ (1, 1) => {}
+ _ => {}
+ }
+ match (0u8, 0u8) {
+ (0, 1) | (2, 3) => {}
+ (0, 3) => {}
+ (2, 1) => {}
+ _ => {}
+ }
+ match (0u8, 0u8) {
+ (_, 0) | (_, 1) => {}
+ _ => {}
+ }
+ match (0u8, 0u8) {
+ (0, _) | (1, _) => {}
+ _ => {}
+ }
+ match Some(0u8) {
+ None | Some(_) => {}
+ _ => {} //~ ERROR unreachable pattern
+ }
+ match Some(0u8) {
+ None | Some(_) => {}
+ Some(_) => {} //~ ERROR unreachable pattern
+ None => {} //~ ERROR unreachable pattern
+ }
+ match Some(0u8) {
+ Some(_) => {}
+ None => {}
+ None | Some(_) => {} //~ ERROR unreachable pattern
+ }
+ match 0u8 {
+ 1 | 2 => {},
+ 1..=2 => {}, //~ ERROR unreachable pattern
+ _ => {},
+ }
+ let (0 | 0) = 0 else { return }; //~ ERROR unreachable pattern
+}
diff --git a/tests/ui/pattern/usefulness/top-level-alternation.stderr b/tests/ui/pattern/usefulness/top-level-alternation.stderr
new file mode 100644
index 000000000..17fa951c5
--- /dev/null
+++ b/tests/ui/pattern/usefulness/top-level-alternation.stderr
@@ -0,0 +1,74 @@
+error: unreachable pattern
+ --> $DIR/top-level-alternation.rs:4:23
+ |
+LL | while let 0..=2 | 1 = 0 {}
+ | ^
+ |
+note: the lint level is defined here
+ --> $DIR/top-level-alternation.rs:1:9
+ |
+LL | #![deny(unreachable_patterns)]
+ | ^^^^^^^^^^^^^^^^^^^^
+
+error: unreachable pattern
+ --> $DIR/top-level-alternation.rs:5:20
+ |
+LL | if let 0..=2 | 1 = 0 {}
+ | ^
+
+error: unreachable pattern
+ --> $DIR/top-level-alternation.rs:9:15
+ |
+LL | | 0 => {}
+ | ^
+
+error: unreachable pattern
+ --> $DIR/top-level-alternation.rs:14:15
+ |
+LL | | Some(0) => {}
+ | ^^^^^^^
+
+error: unreachable pattern
+ --> $DIR/top-level-alternation.rs:19:9
+ |
+LL | (0, 0) => {}
+ | ^^^^^^
+
+error: unreachable pattern
+ --> $DIR/top-level-alternation.rs:39:9
+ |
+LL | _ => {}
+ | ^
+
+error: unreachable pattern
+ --> $DIR/top-level-alternation.rs:43:9
+ |
+LL | Some(_) => {}
+ | ^^^^^^^
+
+error: unreachable pattern
+ --> $DIR/top-level-alternation.rs:44:9
+ |
+LL | None => {}
+ | ^^^^
+
+error: unreachable pattern
+ --> $DIR/top-level-alternation.rs:49:9
+ |
+LL | None | Some(_) => {}
+ | ^^^^^^^^^^^^^^
+
+error: unreachable pattern
+ --> $DIR/top-level-alternation.rs:53:9
+ |
+LL | 1..=2 => {},
+ | ^^^^^
+
+error: unreachable pattern
+ --> $DIR/top-level-alternation.rs:56:14
+ |
+LL | let (0 | 0) = 0 else { return };
+ | ^
+
+error: aborting due to 11 previous errors
+
diff --git a/tests/ui/pattern/usefulness/tuple-struct-nonexhaustive.rs b/tests/ui/pattern/usefulness/tuple-struct-nonexhaustive.rs
new file mode 100644
index 000000000..76bcf3fbd
--- /dev/null
+++ b/tests/ui/pattern/usefulness/tuple-struct-nonexhaustive.rs
@@ -0,0 +1,9 @@
+struct Foo(isize, isize);
+
+fn main() {
+ let x = Foo(1, 2);
+ match x { //~ ERROR non-exhaustive
+ Foo(1, b) => println!("{}", b),
+ Foo(2, b) => println!("{}", b)
+ }
+}
diff --git a/tests/ui/pattern/usefulness/tuple-struct-nonexhaustive.stderr b/tests/ui/pattern/usefulness/tuple-struct-nonexhaustive.stderr
new file mode 100644
index 000000000..e2a65ff85
--- /dev/null
+++ b/tests/ui/pattern/usefulness/tuple-struct-nonexhaustive.stderr
@@ -0,0 +1,21 @@
+error[E0004]: non-exhaustive patterns: `Foo(_, _)` not covered
+ --> $DIR/tuple-struct-nonexhaustive.rs:5:11
+ |
+LL | match x {
+ | ^ pattern `Foo(_, _)` not covered
+ |
+note: `Foo` defined here
+ --> $DIR/tuple-struct-nonexhaustive.rs:1:8
+ |
+LL | struct Foo(isize, isize);
+ | ^^^
+ = note: the matched value is of type `Foo`
+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 ~ Foo(2, b) => println!("{}", b),
+LL + Foo(_, _) => todo!()
+ |
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0004`.
diff --git a/tests/ui/pattern/usefulness/type_polymorphic_byte_str_literals.rs b/tests/ui/pattern/usefulness/type_polymorphic_byte_str_literals.rs
new file mode 100644
index 000000000..cb44c1da7
--- /dev/null
+++ b/tests/ui/pattern/usefulness/type_polymorphic_byte_str_literals.rs
@@ -0,0 +1,36 @@
+#[deny(unreachable_patterns)]
+
+fn parse_data1(data: &[u8]) -> u32 {
+ match data {
+ b"" => 1,
+ _ => 2,
+ }
+}
+
+fn parse_data2(data: &[u8]) -> u32 {
+ match data { //~ ERROR non-exhaustive patterns: `&[_, ..]` not covered
+ b"" => 1,
+ }
+}
+
+fn parse_data3(data: &[u8; 0]) -> u8 {
+ match data {
+ b"" => 1,
+ }
+}
+
+fn parse_data4(data: &[u8]) -> u8 {
+ match data { //~ ERROR non-exhaustive patterns
+ b"aaa" => 0,
+ [_, _, _] => 1,
+ }
+}
+
+fn parse_data5(data: &[u8; 3]) -> u8 {
+ match data {
+ b"aaa" => 0,
+ [_, _, _] => 1,
+ }
+}
+
+fn main() {}
diff --git a/tests/ui/pattern/usefulness/type_polymorphic_byte_str_literals.stderr b/tests/ui/pattern/usefulness/type_polymorphic_byte_str_literals.stderr
new file mode 100644
index 000000000..acae605da
--- /dev/null
+++ b/tests/ui/pattern/usefulness/type_polymorphic_byte_str_literals.stderr
@@ -0,0 +1,29 @@
+error[E0004]: non-exhaustive patterns: `&[_, ..]` not covered
+ --> $DIR/type_polymorphic_byte_str_literals.rs:11:11
+ |
+LL | match data {
+ | ^^^^ pattern `&[_, ..]` not covered
+ |
+ = note: the matched value is of type `&[u8]`
+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 ~ b"" => 1,
+LL ~ &[_, ..] => todo!(),
+ |
+
+error[E0004]: non-exhaustive patterns: `&[]`, `&[_]`, `&[_, _]` and 1 more not covered
+ --> $DIR/type_polymorphic_byte_str_literals.rs:23:11
+ |
+LL | match data {
+ | ^^^^ patterns `&[]`, `&[_]`, `&[_, _]` and 1 more not covered
+ |
+ = note: the matched value is of type `&[u8]`
+help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern as shown, or multiple match arms
+ |
+LL ~ [_, _, _] => 1,
+LL ~ _ => todo!(),
+ |
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0004`.
diff --git a/tests/ui/pattern/usefulness/uninhabited.rs b/tests/ui/pattern/usefulness/uninhabited.rs
new file mode 100644
index 000000000..5622808d4
--- /dev/null
+++ b/tests/ui/pattern/usefulness/uninhabited.rs
@@ -0,0 +1,143 @@
+// check-pass
+// aux-build:empty.rs
+//
+// This tests plays with matching and uninhabited types. This also serves as a test for the
+// `Ty::is_inhabited_from` function.
+#![feature(never_type)]
+#![feature(never_type_fallback)]
+#![feature(exhaustive_patterns)]
+#![deny(unreachable_patterns)]
+
+macro_rules! assert_empty {
+ ($ty:ty) => {
+ const _: () = {
+ fn assert_empty(x: $ty) {
+ match x {}
+ match Some(x) {
+ None => {}
+ }
+ }
+ };
+ };
+}
+macro_rules! assert_non_empty {
+ ($ty:ty) => {
+ const _: () = {
+ fn assert_non_empty(x: $ty) {
+ match x {
+ _ => {}
+ }
+ match Some(x) {
+ None => {}
+ Some(_) => {}
+ }
+ }
+ };
+ };
+}
+
+extern crate empty;
+assert_empty!(empty::EmptyForeignEnum);
+assert_empty!(empty::VisiblyUninhabitedForeignStruct);
+assert_non_empty!(empty::SecretlyUninhabitedForeignStruct);
+
+enum Void {}
+assert_empty!(Void);
+
+enum Enum2 {
+ Foo(Void),
+ Bar(!),
+}
+assert_empty!(Enum2);
+
+enum Enum3 {
+ Foo(Void),
+ Bar {
+ x: u64,
+ y: !,
+ },
+}
+assert_empty!(Enum3);
+
+enum Enum4 {
+ Foo(u64),
+ Bar(!),
+}
+assert_non_empty!(Enum4);
+
+struct Struct1(empty::EmptyForeignEnum);
+assert_empty!(Struct1);
+
+struct Struct2 {
+ x: u64,
+ y: !,
+}
+assert_empty!(Struct2);
+
+union Union {
+ foo: !,
+}
+assert_non_empty!(Union);
+
+assert_empty!((!, String));
+
+assert_non_empty!(&'static !);
+assert_non_empty!(&'static Struct1);
+assert_non_empty!(&'static &'static &'static !);
+
+assert_empty!([!; 1]);
+assert_empty!([Void; 2]);
+assert_non_empty!([!; 0]);
+assert_non_empty!(&'static [!]);
+
+mod visibility {
+ /// This struct can only be seen to be inhabited in modules `b`, `c` or `d`, because otherwise
+ /// the uninhabitedness of both `SecretlyUninhabited` structs is hidden.
+ struct SometimesEmptyStruct {
+ x: a::b::SecretlyUninhabited,
+ y: c::AlsoSecretlyUninhabited,
+ }
+
+ /// This enum can only be seen to be inhabited in module `d`.
+ enum SometimesEmptyEnum {
+ X(c::AlsoSecretlyUninhabited),
+ Y(c::d::VerySecretlyUninhabited),
+ }
+
+ mod a {
+ use super::*;
+ pub mod b {
+ use super::*;
+ pub struct SecretlyUninhabited {
+ _priv: !,
+ }
+ assert_empty!(SometimesEmptyStruct);
+ }
+
+ assert_non_empty!(SometimesEmptyStruct);
+ assert_non_empty!(SometimesEmptyEnum);
+ }
+
+ mod c {
+ use super::*;
+ pub struct AlsoSecretlyUninhabited {
+ _priv: ::Struct1,
+ }
+ assert_empty!(SometimesEmptyStruct);
+ assert_non_empty!(SometimesEmptyEnum);
+
+ pub mod d {
+ use super::*;
+ pub struct VerySecretlyUninhabited {
+ _priv: !,
+ }
+ assert_empty!(SometimesEmptyStruct);
+ assert_empty!(SometimesEmptyEnum);
+ }
+ }
+
+ assert_non_empty!(SometimesEmptyStruct);
+ assert_non_empty!(SometimesEmptyEnum);
+}
+
+fn main() {}
diff --git a/tests/ui/pattern/usefulness/unstable-gated-fields.rs b/tests/ui/pattern/usefulness/unstable-gated-fields.rs
new file mode 100644
index 000000000..2b473ae98
--- /dev/null
+++ b/tests/ui/pattern/usefulness/unstable-gated-fields.rs
@@ -0,0 +1,18 @@
+#![feature(unstable_test_feature)]
+
+// aux-build:unstable.rs
+
+extern crate unstable;
+
+use unstable::UnstableStruct;
+
+fn main() {
+ let UnstableStruct { stable, stable2, } = UnstableStruct::default();
+ //~^ pattern does not mention field `unstable`
+
+ let UnstableStruct { stable, unstable, } = UnstableStruct::default();
+ //~^ pattern does not mention field `stable2`
+
+ // OK: stable field is matched
+ let UnstableStruct { stable, stable2, unstable } = UnstableStruct::default();
+}
diff --git a/tests/ui/pattern/usefulness/unstable-gated-fields.stderr b/tests/ui/pattern/usefulness/unstable-gated-fields.stderr
new file mode 100644
index 000000000..e4f5fa06b
--- /dev/null
+++ b/tests/ui/pattern/usefulness/unstable-gated-fields.stderr
@@ -0,0 +1,33 @@
+error[E0027]: pattern does not mention field `unstable`
+ --> $DIR/unstable-gated-fields.rs:10:9
+ |
+LL | let UnstableStruct { stable, stable2, } = UnstableStruct::default();
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ missing field `unstable`
+ |
+help: include the missing field in the pattern
+ |
+LL | let UnstableStruct { stable, stable2, unstable } = UnstableStruct::default();
+ | ~~~~~~~~~~~~
+help: if you don't care about this missing field, you can explicitly ignore it
+ |
+LL | let UnstableStruct { stable, stable2, .. } = UnstableStruct::default();
+ | ~~~~~~
+
+error[E0027]: pattern does not mention field `stable2`
+ --> $DIR/unstable-gated-fields.rs:13:9
+ |
+LL | let UnstableStruct { stable, unstable, } = UnstableStruct::default();
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ missing field `stable2`
+ |
+help: include the missing field in the pattern
+ |
+LL | let UnstableStruct { stable, unstable, stable2 } = UnstableStruct::default();
+ | ~~~~~~~~~~~
+help: if you don't care about this missing field, you can explicitly ignore it
+ |
+LL | let UnstableStruct { stable, unstable, .. } = UnstableStruct::default();
+ | ~~~~~~
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0027`.
diff --git a/tests/ui/pattern/usefulness/unstable-gated-patterns.rs b/tests/ui/pattern/usefulness/unstable-gated-patterns.rs
new file mode 100644
index 000000000..7046555e0
--- /dev/null
+++ b/tests/ui/pattern/usefulness/unstable-gated-patterns.rs
@@ -0,0 +1,22 @@
+#![feature(unstable_test_feature)]
+
+// aux-build:unstable.rs
+
+extern crate unstable;
+
+use unstable::UnstableEnum;
+
+fn main() {
+ match UnstableEnum::Stable {
+ UnstableEnum::Stable => {}
+ UnstableEnum::Stable2 => {}
+ }
+ //~^^^^ non-exhaustive patterns: `UnstableEnum::Unstable` not covered
+
+ // Ok: all variants are explicitly matched
+ match UnstableEnum::Stable {
+ UnstableEnum::Stable => {}
+ UnstableEnum::Stable2 => {}
+ UnstableEnum::Unstable => {}
+ }
+}
diff --git a/tests/ui/pattern/usefulness/unstable-gated-patterns.stderr b/tests/ui/pattern/usefulness/unstable-gated-patterns.stderr
new file mode 100644
index 000000000..6dc9a4058
--- /dev/null
+++ b/tests/ui/pattern/usefulness/unstable-gated-patterns.stderr
@@ -0,0 +1,24 @@
+error[E0004]: non-exhaustive patterns: `UnstableEnum::Unstable` not covered
+ --> $DIR/unstable-gated-patterns.rs:10:11
+ |
+LL | match UnstableEnum::Stable {
+ | ^^^^^^^^^^^^^^^^^^^^ pattern `UnstableEnum::Unstable` not covered
+ |
+note: `UnstableEnum` defined here
+ --> $DIR/auxiliary/unstable.rs:11:5
+ |
+LL | pub enum UnstableEnum {
+ | ---------------------
+...
+LL | Unstable,
+ | ^^^^^^^^ not covered
+ = note: the matched value is of type `UnstableEnum`
+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 ~ UnstableEnum::Stable2 => {}
+LL + UnstableEnum::Unstable => todo!()
+ |
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0004`.