about summary refs log tree commit diff
path: root/src/test/ui/pattern
diff options
context:
space:
mode:
authorNadrieril <nadrieril@gmail.com>2019-09-28 16:05:38 +0200
committerNadrieril <nadrieril@gmail.com>2019-10-27 21:20:26 +0000
commit09f9947ebc68a8199c3dff8607a41571c48cc377 (patch)
treefb81c258de9902ea813c24c5ca08bcce9817a4bb /src/test/ui/pattern
parent0f677c65e867d93a47ccbaeaf6e6725cde8c5ff6 (diff)
downloadrust-09f9947ebc68a8199c3dff8607a41571c48cc377.tar.gz
rust-09f9947ebc68a8199c3dff8607a41571c48cc377.zip
Gather together usefulness tests
I took most tests that were testing only for match exhaustiveness,
pattern refutability or match arm reachability, and put them in
the same test folder.
Diffstat (limited to 'src/test/ui/pattern')
-rw-r--r--src/test/ui/pattern/usefulness/always-inhabited-union-ref.rs32
-rw-r--r--src/test/ui/pattern/usefulness/always-inhabited-union-ref.stderr19
-rw-r--r--src/test/ui/pattern/usefulness/exhaustive_integer_patterns.rs157
-rw-r--r--src/test/ui/pattern/usefulness/exhaustive_integer_patterns.stderr123
-rw-r--r--src/test/ui/pattern/usefulness/guards-not-exhaustive.rs18
-rw-r--r--src/test/ui/pattern/usefulness/irrefutable-exhaustive-integer-binding.rs (renamed from src/test/ui/pattern/irrefutable-exhaustive-integer-binding.rs)0
-rw-r--r--src/test/ui/pattern/usefulness/irrefutable-unit.rs6
-rw-r--r--src/test/ui/pattern/usefulness/issue-35609.rs43
-rw-r--r--src/test/ui/pattern/usefulness/issue-35609.stderr73
-rw-r--r--src/test/ui/pattern/usefulness/issue-43253.rs47
-rw-r--r--src/test/ui/pattern/usefulness/issue-43253.stderr50
-rw-r--r--src/test/ui/pattern/usefulness/match-arm-statics-2.rs62
-rw-r--r--src/test/ui/pattern/usefulness/match-arm-statics-2.stderr33
-rw-r--r--src/test/ui/pattern/usefulness/match-arm-statics.rs69
-rw-r--r--src/test/ui/pattern/usefulness/match-arm-statics.stderr26
-rw-r--r--src/test/ui/pattern/usefulness/match-byte-array-patterns-2.rs13
-rw-r--r--src/test/ui/pattern/usefulness/match-byte-array-patterns-2.stderr19
-rw-r--r--src/test/ui/pattern/usefulness/match-byte-array-patterns.rs56
-rw-r--r--src/test/ui/pattern/usefulness/match-byte-array-patterns.stderr56
-rw-r--r--src/test/ui/pattern/usefulness/match-non-exhaustive.rs4
-rw-r--r--src/test/ui/pattern/usefulness/match-non-exhaustive.stderr19
-rw-r--r--src/test/ui/pattern/usefulness/match-privately-empty.rs21
-rw-r--r--src/test/ui/pattern/usefulness/match-privately-empty.stderr11
-rw-r--r--src/test/ui/pattern/usefulness/match-range-fail-dominate.rs45
-rw-r--r--src/test/ui/pattern/usefulness/match-range-fail-dominate.stderr75
-rw-r--r--src/test/ui/pattern/usefulness/match-ref-ice.rs16
-rw-r--r--src/test/ui/pattern/usefulness/match-ref-ice.stderr14
-rw-r--r--src/test/ui/pattern/usefulness/match-slice-patterns.rs14
-rw-r--r--src/test/ui/pattern/usefulness/match-slice-patterns.stderr11
-rw-r--r--src/test/ui/pattern/usefulness/match-vec-fixed.rs18
-rw-r--r--src/test/ui/pattern/usefulness/match-vec-fixed.stderr20
-rw-r--r--src/test/ui/pattern/usefulness/match-vec-unreachable.rs30
-rw-r--r--src/test/ui/pattern/usefulness/match-vec-unreachable.stderr26
-rw-r--r--src/test/ui/pattern/usefulness/nested-exhaustive-match.rs14
-rw-r--r--src/test/ui/pattern/usefulness/non-exhaustive-defined-here.rs72
-rw-r--r--src/test/ui/pattern/usefulness/non-exhaustive-defined-here.stderr198
-rw-r--r--src/test/ui/pattern/usefulness/non-exhaustive-float-range-match.rs13
-rw-r--r--src/test/ui/pattern/usefulness/non-exhaustive-float-range-match.stderr11
-rw-r--r--src/test/ui/pattern/usefulness/non-exhaustive-match-nested.rs21
-rw-r--r--src/test/ui/pattern/usefulness/non-exhaustive-match-nested.stderr25
-rw-r--r--src/test/ui/pattern/usefulness/non-exhaustive-match.rs64
-rw-r--r--src/test/ui/pattern/usefulness/non-exhaustive-match.stderr79
-rw-r--r--src/test/ui/pattern/usefulness/non-exhaustive-pattern-witness.rs91
-rw-r--r--src/test/ui/pattern/usefulness/non-exhaustive-pattern-witness.stderr95
-rw-r--r--src/test/ui/pattern/usefulness/refutable-pattern-errors.rs9
-rw-r--r--src/test/ui/pattern/usefulness/refutable-pattern-errors.stderr22
-rw-r--r--src/test/ui/pattern/usefulness/refutable-pattern-in-fn-arg.rs5
-rw-r--r--src/test/ui/pattern/usefulness/refutable-pattern-in-fn-arg.stderr9
-rw-r--r--src/test/ui/pattern/usefulness/struct-like-enum-nonexhaustive.rs12
-rw-r--r--src/test/ui/pattern/usefulness/struct-like-enum-nonexhaustive.stderr18
-rw-r--r--src/test/ui/pattern/usefulness/struct-pattern-match-useless.rs15
-rw-r--r--src/test/ui/pattern/usefulness/struct-pattern-match-useless.stderr14
-rw-r--r--src/test/ui/pattern/usefulness/tuple-struct-nonexhaustive.rs9
-rw-r--r--src/test/ui/pattern/usefulness/tuple-struct-nonexhaustive.stderr14
54 files changed, 2036 insertions, 0 deletions
diff --git a/src/test/ui/pattern/usefulness/always-inhabited-union-ref.rs b/src/test/ui/pattern/usefulness/always-inhabited-union-ref.rs
new file mode 100644
index 00000000000..11eae2af9c9
--- /dev/null
+++ b/src/test/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 `&'static !` is non-empty
+    }
+
+    match uninhab_union() {
+        //~^ ERROR non-exhaustive patterns: type `Foo` is non-empty
+    }
+}
+
+fn main() {}
diff --git a/src/test/ui/pattern/usefulness/always-inhabited-union-ref.stderr b/src/test/ui/pattern/usefulness/always-inhabited-union-ref.stderr
new file mode 100644
index 00000000000..792ab6f59a4
--- /dev/null
+++ b/src/test/ui/pattern/usefulness/always-inhabited-union-ref.stderr
@@ -0,0 +1,19 @@
+error[E0004]: non-exhaustive patterns: type `&'static !` is non-empty
+  --> $DIR/always-inhabited-union-ref.rs:23:11
+   |
+LL |     match uninhab_ref() {
+   |           ^^^^^^^^^^^^^
+   |
+   = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
+
+error[E0004]: non-exhaustive patterns: type `Foo` is non-empty
+  --> $DIR/always-inhabited-union-ref.rs:27:11
+   |
+LL |     match uninhab_union() {
+   |           ^^^^^^^^^^^^^^^
+   |
+   = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0004`.
diff --git a/src/test/ui/pattern/usefulness/exhaustive_integer_patterns.rs b/src/test/ui/pattern/usefulness/exhaustive_integer_patterns.rs
new file mode 100644
index 00000000000..59f74919897
--- /dev/null
+++ b/src/test/ui/pattern/usefulness/exhaustive_integer_patterns.rs
@@ -0,0 +1,157 @@
+#![feature(precise_pointer_size_matching)]
+#![feature(exclusive_range_pattern)]
+#![deny(unreachable_patterns)]
+#![deny(overlapping_patterns)]
+
+use std::{char, u8, u16, u32, u64, u128, i8, i16, i32, i64, i128};
+
+fn main() {
+    let x: u8 = 0;
+
+    // A single range covering the entire domain.
+    match x {
+        0 ..= 255 => {} // ok
+    }
+
+    // A combination of ranges and values.
+    // These are currently allowed to be overlapping.
+    match x {
+        0 ..= 32 => {}
+        33 => {}
+        34 .. 128 => {}
+        100 ..= 200 => {}
+        200 => {} //~ ERROR unreachable pattern
+        201 ..= 255 => {}
+    }
+
+    // An incomplete set of values.
+    match x { //~ ERROR non-exhaustive patterns
+        0 .. 128 => {}
+    }
+
+    // A more incomplete set of values.
+    match x { //~ ERROR non-exhaustive patterns
+        0 ..= 10 => {}
+        20 ..= 30 => {}
+        35 => {}
+        70 .. 255 => {}
+    }
+
+    let x: i8 = 0;
+    match x { //~ ERROR non-exhaustive patterns
+        -7 => {}
+        -5..=120 => {}
+        -2..=20 => {}
+        //~^ ERROR unreachable pattern
+        125 => {}
+    }
+
+    // Let's test other types too!
+    let c: char = '\u{0}';
+    match c {
+        '\u{0}' ..= char::MAX => {} // ok
+    }
+
+    // We can actually get away with just covering the
+    // following two ranges, which correspond to all
+    // valid Unicode Scalar Values.
+    match c {
+        '\u{0000}' ..= '\u{D7FF}' => {}
+        '\u{E000}' ..= '\u{10_FFFF}' => {}
+    }
+
+    match 0u16 {
+        0 ..= u16::MAX => {} // ok
+    }
+
+    match 0u32 {
+        0 ..= u32::MAX => {} // ok
+    }
+
+    match 0u64 {
+        0 ..= u64::MAX => {} // ok
+    }
+
+    match 0u128 {
+        0 ..= u128::MAX => {} // ok
+    }
+
+    match 0i8 {
+        -128 ..= 127 => {} // ok
+    }
+
+    match 0i8 { //~ ERROR non-exhaustive patterns
+        -127 ..= 127 => {}
+    }
+
+    match 0i16 {
+        i16::MIN ..= i16::MAX => {} // ok
+    }
+
+    match 0i16 { //~ ERROR non-exhaustive patterns
+        i16::MIN ..= -1 => {}
+        1 ..= i16::MAX => {}
+    }
+
+    match 0i32 {
+        i32::MIN ..= i32::MAX => {} // ok
+    }
+
+    match 0i64 {
+        i64::MIN ..= i64::MAX => {} // ok
+    }
+
+    match 0i128 {
+        i128::MIN ..= i128::MAX => {} // ok
+    }
+
+    // Make sure that guards don't factor into the exhaustiveness checks.
+    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
+    }
+
+    // Now things start getting a bit more interesting. Testing products!
+    match (0u8, Some(())) { //~ ERROR non-exhaustive patterns
+        (1, _) => {}
+        (_, None) => {}
+    }
+
+    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 0u8 {
+        0 .. 2 => {}
+        1 ..= 2 => {} //~ ERROR multiple patterns covering the same range
+        _ => {}
+    }
+
+    const LIM: u128 = u128::MAX - 1;
+    match 0u128 { //~ ERROR non-exhaustive patterns
+        0 ..= LIM => {}
+    }
+
+    match 0u128 { //~ ERROR non-exhaustive patterns
+        0 ..= 4 => {}
+    }
+
+    match 0u128 { //~ ERROR non-exhaustive patterns
+        4 ..= u128::MAX => {}
+    }
+}
diff --git a/src/test/ui/pattern/usefulness/exhaustive_integer_patterns.stderr b/src/test/ui/pattern/usefulness/exhaustive_integer_patterns.stderr
new file mode 100644
index 00000000000..7a3a36a820c
--- /dev/null
+++ b/src/test/ui/pattern/usefulness/exhaustive_integer_patterns.stderr
@@ -0,0 +1,123 @@
+error: unreachable pattern
+  --> $DIR/exhaustive_integer_patterns.rs:23:9
+   |
+LL |         200 => {}
+   |         ^^^
+   |
+note: lint level defined here
+  --> $DIR/exhaustive_integer_patterns.rs:3:9
+   |
+LL | #![deny(unreachable_patterns)]
+   |         ^^^^^^^^^^^^^^^^^^^^
+
+error[E0004]: non-exhaustive patterns: `128u8..=std::u8::MAX` not covered
+  --> $DIR/exhaustive_integer_patterns.rs:28:11
+   |
+LL |     match x {
+   |           ^ pattern `128u8..=std::u8::MAX` not covered
+   |
+   = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
+
+error[E0004]: non-exhaustive patterns: `11u8..=19u8`, `31u8..=34u8`, `36u8..=69u8` and 1 more not covered
+  --> $DIR/exhaustive_integer_patterns.rs:33:11
+   |
+LL |     match x {
+   |           ^ patterns `11u8..=19u8`, `31u8..=34u8`, `36u8..=69u8` and 1 more not covered
+   |
+   = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
+
+error: unreachable pattern
+  --> $DIR/exhaustive_integer_patterns.rs:44:9
+   |
+LL |         -2..=20 => {}
+   |         ^^^^^^^
+
+error[E0004]: non-exhaustive patterns: `std::i8::MIN..=-8i8`, `-6i8`, `121i8..=124i8` and 1 more not covered
+  --> $DIR/exhaustive_integer_patterns.rs:41:11
+   |
+LL |     match x {
+   |           ^ patterns `std::i8::MIN..=-8i8`, `-6i8`, `121i8..=124i8` and 1 more not covered
+   |
+   = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
+
+error[E0004]: non-exhaustive patterns: `std::i8::MIN` not covered
+  --> $DIR/exhaustive_integer_patterns.rs:83:11
+   |
+LL |     match 0i8 {
+   |           ^^^ pattern `std::i8::MIN` not covered
+   |
+   = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
+
+error[E0004]: non-exhaustive patterns: `0i16` not covered
+  --> $DIR/exhaustive_integer_patterns.rs:91:11
+   |
+LL |     match 0i16 {
+   |           ^^^^ pattern `0i16` not covered
+   |
+   = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
+
+error[E0004]: non-exhaustive patterns: `128u8..=std::u8::MAX` not covered
+  --> $DIR/exhaustive_integer_patterns.rs:109:11
+   |
+LL |     match 0u8 {
+   |           ^^^ pattern `128u8..=std::u8::MAX` not covered
+   |
+   = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
+
+error[E0004]: non-exhaustive patterns: `(0u8, Some(_))` and `(2u8..=std::u8::MAX, Some(_))` not covered
+  --> $DIR/exhaustive_integer_patterns.rs:121:11
+   |
+LL |     match (0u8, Some(())) {
+   |           ^^^^^^^^^^^^^^^ patterns `(0u8, Some(_))` and `(2u8..=std::u8::MAX, Some(_))` not covered
+   |
+   = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
+
+error[E0004]: non-exhaustive patterns: `(126u8..=127u8, false)` not covered
+  --> $DIR/exhaustive_integer_patterns.rs:126:11
+   |
+LL |     match (0u8, true) {
+   |           ^^^^^^^^^^^ pattern `(126u8..=127u8, false)` not covered
+   |
+   = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
+
+error: multiple patterns covering the same range
+  --> $DIR/exhaustive_integer_patterns.rs:141:9
+   |
+LL |         0 .. 2 => {}
+   |         ------ this range overlaps on `1u8`
+LL |         1 ..= 2 => {}
+   |         ^^^^^^^ overlapping patterns
+   |
+note: lint level defined here
+  --> $DIR/exhaustive_integer_patterns.rs:4:9
+   |
+LL | #![deny(overlapping_patterns)]
+   |         ^^^^^^^^^^^^^^^^^^^^
+
+error[E0004]: non-exhaustive patterns: `std::u128::MAX` not covered
+  --> $DIR/exhaustive_integer_patterns.rs:146:11
+   |
+LL |     match 0u128 {
+   |           ^^^^^ pattern `std::u128::MAX` not covered
+   |
+   = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
+
+error[E0004]: non-exhaustive patterns: `5u128..=std::u128::MAX` not covered
+  --> $DIR/exhaustive_integer_patterns.rs:150:11
+   |
+LL |     match 0u128 {
+   |           ^^^^^ pattern `5u128..=std::u128::MAX` not covered
+   |
+   = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
+
+error[E0004]: non-exhaustive patterns: `0u128..=3u128` not covered
+  --> $DIR/exhaustive_integer_patterns.rs:154:11
+   |
+LL |     match 0u128 {
+   |           ^^^^^ pattern `0u128..=3u128` not covered
+   |
+   = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
+
+error: aborting due to 14 previous errors
+
+For more information about this error, try `rustc --explain E0004`.
diff --git a/src/test/ui/pattern/usefulness/guards-not-exhaustive.rs b/src/test/ui/pattern/usefulness/guards-not-exhaustive.rs
new file mode 100644
index 00000000000..b74f162c0c6
--- /dev/null
+++ b/src/test/ui/pattern/usefulness/guards-not-exhaustive.rs
@@ -0,0 +1,18 @@
+// run-pass
+
+#![allow(non_snake_case)]
+
+#[derive(Copy, Clone)]
+enum Q { R(Option<usize>) }
+
+fn xyzzy(q: Q) -> usize {
+    match q {
+        Q::R(S) if S.is_some() => { 0 }
+        _ => 1
+    }
+}
+
+
+pub fn main() {
+    assert_eq!(xyzzy(Q::R(Some(5))), 0);
+}
diff --git a/src/test/ui/pattern/irrefutable-exhaustive-integer-binding.rs b/src/test/ui/pattern/usefulness/irrefutable-exhaustive-integer-binding.rs
index ff065882d96..ff065882d96 100644
--- a/src/test/ui/pattern/irrefutable-exhaustive-integer-binding.rs
+++ b/src/test/ui/pattern/usefulness/irrefutable-exhaustive-integer-binding.rs
diff --git a/src/test/ui/pattern/usefulness/irrefutable-unit.rs b/src/test/ui/pattern/usefulness/irrefutable-unit.rs
new file mode 100644
index 00000000000..dd8f03b6dbd
--- /dev/null
+++ b/src/test/ui/pattern/usefulness/irrefutable-unit.rs
@@ -0,0 +1,6 @@
+// run-pass
+// pretty-expanded FIXME #23616
+
+pub fn main() {
+    let ((),()) = ((),());
+}
diff --git a/src/test/ui/pattern/usefulness/issue-35609.rs b/src/test/ui/pattern/usefulness/issue-35609.rs
new file mode 100644
index 00000000000..8ef75e3511e
--- /dev/null
+++ b/src/test/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/src/test/ui/pattern/usefulness/issue-35609.stderr b/src/test/ui/pattern/usefulness/issue-35609.stderr
new file mode 100644
index 00000000000..af22535c55e
--- /dev/null
+++ b/src/test/ui/pattern/usefulness/issue-35609.stderr
@@ -0,0 +1,73 @@
+error[E0004]: non-exhaustive patterns: `(B, _)`, `(C, _)`, `(D, _)` and 2 more not covered
+  --> $DIR/issue-35609.rs:10:11
+   |
+LL |     match (A, ()) {
+   |           ^^^^^^^ patterns `(B, _)`, `(C, _)`, `(D, _)` and 2 more not covered
+   |
+   = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
+
+error[E0004]: non-exhaustive patterns: `(_, B)`, `(_, C)`, `(_, D)` and 2 more not covered
+  --> $DIR/issue-35609.rs:14:11
+   |
+LL |     match (A, A) {
+   |           ^^^^^^ patterns `(_, B)`, `(_, C)`, `(_, D)` and 2 more not covered
+   |
+   = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
+
+error[E0004]: non-exhaustive patterns: `((B, _), _)`, `((C, _), _)`, `((D, _), _)` and 2 more not covered
+  --> $DIR/issue-35609.rs:18:11
+   |
+LL |     match ((A, ()), ()) {
+   |           ^^^^^^^^^^^^^ patterns `((B, _), _)`, `((C, _), _)`, `((D, _), _)` and 2 more not covered
+   |
+   = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
+
+error[E0004]: non-exhaustive patterns: `((B, _), _)`, `((C, _), _)`, `((D, _), _)` and 2 more not covered
+  --> $DIR/issue-35609.rs:22:11
+   |
+LL |     match ((A, ()), A) {
+   |           ^^^^^^^^^^^^ patterns `((B, _), _)`, `((C, _), _)`, `((D, _), _)` and 2 more not covered
+   |
+   = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
+
+error[E0004]: non-exhaustive patterns: `((B, _), _)`, `((C, _), _)`, `((D, _), _)` and 2 more not covered
+  --> $DIR/issue-35609.rs:26:11
+   |
+LL |     match ((A, ()), ()) {
+   |           ^^^^^^^^^^^^^ patterns `((B, _), _)`, `((C, _), _)`, `((D, _), _)` and 2 more not covered
+   |
+   = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
+
+error[E0004]: non-exhaustive patterns: `S(B, _)`, `S(C, _)`, `S(D, _)` and 2 more not covered
+  --> $DIR/issue-35609.rs:31:11
+   |
+LL | struct S(Enum, ());
+   | ------------------- `S` defined here
+...
+LL |     match S(A, ()) {
+   |           ^^^^^^^^ patterns `S(B, _)`, `S(C, _)`, `S(D, _)` and 2 more not covered
+   |
+   = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
+
+error[E0004]: non-exhaustive patterns: `Sd { x: B, .. }`, `Sd { x: C, .. }`, `Sd { x: D, .. }` and 2 more not covered
+  --> $DIR/issue-35609.rs:35:11
+   |
+LL | struct Sd { x: Enum, y: () }
+   | ---------------------------- `Sd` defined here
+...
+LL |     match (Sd { x: A, y: () }) {
+   |           ^^^^^^^^^^^^^^^^^^^^ patterns `Sd { x: B, .. }`, `Sd { x: C, .. }`, `Sd { x: D, .. }` and 2 more not covered
+   |
+   = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
+
+error[E0004]: non-exhaustive patterns: `Some(B)`, `Some(C)`, `Some(D)` and 2 more not covered
+  --> $DIR/issue-35609.rs:39:11
+   |
+LL |     match Some(A) {
+   |           ^^^^^^^ patterns `Some(B)`, `Some(C)`, `Some(D)` and 2 more not covered
+   |
+   = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
+
+error: aborting due to 8 previous errors
+
+For more information about this error, try `rustc --explain E0004`.
diff --git a/src/test/ui/pattern/usefulness/issue-43253.rs b/src/test/ui/pattern/usefulness/issue-43253.rs
new file mode 100644
index 00000000000..5c6834459f0
--- /dev/null
+++ b/src/test/ui/pattern/usefulness/issue-43253.rs
@@ -0,0 +1,47 @@
+// check-pass
+#![feature(exclusive_range_pattern)]
+#![warn(unreachable_patterns)]
+#![warn(overlapping_patterns)]
+
+fn main() {
+    // These cases should generate no warning.
+    match 10 {
+        1..10 => {},
+        10 => {},
+        _ => {},
+    }
+
+    match 10 {
+        1..10 => {},
+        9..=10 => {}, //~ WARNING multiple patterns covering the same range
+        _ => {},
+    }
+
+    match 10 {
+        1..10 => {},
+        10..=10 => {},
+        _ => {},
+    }
+
+    // These cases should generate "unreachable pattern" warnings.
+    match 10 {
+        1..10 => {},
+        9 => {}, //~ WARNING unreachable pattern
+        _ => {},
+    }
+
+    match 10 {
+        1..10 => {},
+        8..=9 => {}, //~ WARNING multiple patterns covering the same range
+        _ => {},
+    }
+
+    match 10 {
+        5..7 => {},
+        6 => {}, //~ WARNING unreachable pattern
+        1..10 => {}, //~ WARNING multiple patterns covering the same range
+        9..=9 => {}, //~ WARNING unreachable pattern
+        6 => {}, //~ WARNING unreachable pattern
+        _ => {},
+    }
+}
diff --git a/src/test/ui/pattern/usefulness/issue-43253.stderr b/src/test/ui/pattern/usefulness/issue-43253.stderr
new file mode 100644
index 00000000000..cb4a0486eef
--- /dev/null
+++ b/src/test/ui/pattern/usefulness/issue-43253.stderr
@@ -0,0 +1,50 @@
+warning: multiple patterns covering the same range
+  --> $DIR/issue-43253.rs:16:9
+   |
+LL |         1..10 => {},
+   |         ----- this range overlaps on `9i32`
+LL |         9..=10 => {},
+   |         ^^^^^^ overlapping patterns
+   |
+note: lint level defined here
+  --> $DIR/issue-43253.rs:4:9
+   |
+LL | #![warn(overlapping_patterns)]
+   |         ^^^^^^^^^^^^^^^^^^^^
+
+warning: unreachable pattern
+  --> $DIR/issue-43253.rs:29:9
+   |
+LL |         9 => {},
+   |         ^
+   |
+note: lint level defined here
+  --> $DIR/issue-43253.rs:3:9
+   |
+LL | #![warn(unreachable_patterns)]
+   |         ^^^^^^^^^^^^^^^^^^^^
+
+warning: unreachable pattern
+  --> $DIR/issue-43253.rs:35:9
+   |
+LL |         8..=9 => {},
+   |         ^^^^^
+
+warning: unreachable pattern
+  --> $DIR/issue-43253.rs:41:9
+   |
+LL |         6 => {},
+   |         ^
+
+warning: unreachable pattern
+  --> $DIR/issue-43253.rs:43:9
+   |
+LL |         9..=9 => {},
+   |         ^^^^^
+
+warning: unreachable pattern
+  --> $DIR/issue-43253.rs:44:9
+   |
+LL |         6 => {},
+   |         ^
+
diff --git a/src/test/ui/pattern/usefulness/match-arm-statics-2.rs b/src/test/ui/pattern/usefulness/match-arm-statics-2.rs
new file mode 100644
index 00000000000..4c5f2d35649
--- /dev/null
+++ b/src/test/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(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(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/src/test/ui/pattern/usefulness/match-arm-statics-2.stderr b/src/test/ui/pattern/usefulness/match-arm-statics-2.stderr
new file mode 100644
index 00000000000..8521e37d3fd
--- /dev/null
+++ b/src/test/ui/pattern/usefulness/match-arm-statics-2.stderr
@@ -0,0 +1,33 @@
+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
+   |
+   = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
+
+error[E0004]: non-exhaustive patterns: `Some(Some(West))` not covered
+  --> $DIR/match-arm-statics-2.rs:29:11
+   |
+LL |     match Some(Some(North)) {
+   |           ^^^^^^^^^^^^^^^^^ pattern `Some(Some(West))` not covered
+   |
+   = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
+
+error[E0004]: non-exhaustive patterns: `Foo { bar: Some(North), baz: NewBool(true) }` not covered
+  --> $DIR/match-arm-statics-2.rs:48:11
+   |
+LL | / struct Foo {
+LL | |     bar: Option<Direction>,
+LL | |     baz: NewBool
+LL | | }
+   | |_- `Foo` defined here
+...
+LL |       match (Foo { bar: Some(North), baz: NewBool(true) }) {
+   |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ pattern `Foo { bar: Some(North), baz: NewBool(true) }` not covered
+   |
+   = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
+
+error: aborting due to 3 previous errors
+
+For more information about this error, try `rustc --explain E0004`.
diff --git a/src/test/ui/pattern/usefulness/match-arm-statics.rs b/src/test/ui/pattern/usefulness/match-arm-statics.rs
new file mode 100644
index 00000000000..91db76ebb9f
--- /dev/null
+++ b/src/test/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/src/test/ui/pattern/usefulness/match-arm-statics.stderr b/src/test/ui/pattern/usefulness/match-arm-statics.stderr
new file mode 100644
index 00000000000..3d9e900a4e9
--- /dev/null
+++ b/src/test/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: lint level 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/src/test/ui/pattern/usefulness/match-byte-array-patterns-2.rs b/src/test/ui/pattern/usefulness/match-byte-array-patterns-2.rs
new file mode 100644
index 00000000000..33468d03fae
--- /dev/null
+++ b/src/test/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/src/test/ui/pattern/usefulness/match-byte-array-patterns-2.stderr b/src/test/ui/pattern/usefulness/match-byte-array-patterns-2.stderr
new file mode 100644
index 00000000000..d53e2e25b3d
--- /dev/null
+++ b/src/test/ui/pattern/usefulness/match-byte-array-patterns-2.stderr
@@ -0,0 +1,19 @@
+error[E0004]: non-exhaustive patterns: `&[_, _, _, _]` not covered
+  --> $DIR/match-byte-array-patterns-2.rs:4:11
+   |
+LL |     match buf {
+   |           ^^^ pattern `&[_, _, _, _]` not covered
+   |
+   = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
+
+error[E0004]: non-exhaustive patterns: `&[]`, `&[_]`, `&[_, _]` and 3 more not covered
+  --> $DIR/match-byte-array-patterns-2.rs:10:11
+   |
+LL |     match buf {
+   |           ^^^ patterns `&[]`, `&[_]`, `&[_, _]` and 3 more not covered
+   |
+   = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0004`.
diff --git a/src/test/ui/pattern/usefulness/match-byte-array-patterns.rs b/src/test/ui/pattern/usefulness/match-byte-array-patterns.rs
new file mode 100644
index 00000000000..7541ea3e2e2
--- /dev/null
+++ b/src/test/ui/pattern/usefulness/match-byte-array-patterns.rs
@@ -0,0 +1,56 @@
+#![feature(slice_patterns)]
+#![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/src/test/ui/pattern/usefulness/match-byte-array-patterns.stderr b/src/test/ui/pattern/usefulness/match-byte-array-patterns.stderr
new file mode 100644
index 00000000000..b28646b50cf
--- /dev/null
+++ b/src/test/ui/pattern/usefulness/match-byte-array-patterns.stderr
@@ -0,0 +1,56 @@
+error: unreachable pattern
+  --> $DIR/match-byte-array-patterns.rs:9:9
+   |
+LL |         &[0x41, 0x41, 0x41, 0x41] => {}
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+note: lint level defined here
+  --> $DIR/match-byte-array-patterns.rs:2:9
+   |
+LL | #![deny(unreachable_patterns)]
+   |         ^^^^^^^^^^^^^^^^^^^^
+
+error: unreachable pattern
+  --> $DIR/match-byte-array-patterns.rs:15:9
+   |
+LL |         b"AAAA" => {},
+   |         ^^^^^^^
+
+error: unreachable pattern
+  --> $DIR/match-byte-array-patterns.rs:21:9
+   |
+LL |         b"AAAA" => {},
+   |         ^^^^^^^
+
+error: unreachable pattern
+  --> $DIR/match-byte-array-patterns.rs:27:9
+   |
+LL |         b"AAAA" => {},
+   |         ^^^^^^^
+
+error: unreachable pattern
+  --> $DIR/match-byte-array-patterns.rs:35:9
+   |
+LL |         &[0x41, 0x41, 0x41, 0x41] => {}
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: unreachable pattern
+  --> $DIR/match-byte-array-patterns.rs:41:9
+   |
+LL |         b"AAAA" => {},
+   |         ^^^^^^^
+
+error: unreachable pattern
+  --> $DIR/match-byte-array-patterns.rs:47:9
+   |
+LL |         b"AAAA" => {},
+   |         ^^^^^^^
+
+error: unreachable pattern
+  --> $DIR/match-byte-array-patterns.rs:53:9
+   |
+LL |         b"AAAA" => {},
+   |         ^^^^^^^
+
+error: aborting due to 8 previous errors
+
diff --git a/src/test/ui/pattern/usefulness/match-non-exhaustive.rs b/src/test/ui/pattern/usefulness/match-non-exhaustive.rs
new file mode 100644
index 00000000000..3b210a115d2
--- /dev/null
+++ b/src/test/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/src/test/ui/pattern/usefulness/match-non-exhaustive.stderr b/src/test/ui/pattern/usefulness/match-non-exhaustive.stderr
new file mode 100644
index 00000000000..211f333882b
--- /dev/null
+++ b/src/test/ui/pattern/usefulness/match-non-exhaustive.stderr
@@ -0,0 +1,19 @@
+error[E0004]: non-exhaustive patterns: `std::i32::MIN..=0i32` and `2i32..=std::i32::MAX` not covered
+  --> $DIR/match-non-exhaustive.rs:2:11
+   |
+LL |     match 0 { 1 => () }
+   |           ^ patterns `std::i32::MIN..=0i32` and `2i32..=std::i32::MAX` not covered
+   |
+   = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
+
+error[E0004]: non-exhaustive patterns: `_` not covered
+  --> $DIR/match-non-exhaustive.rs:3:11
+   |
+LL |     match 0 { 0 if false => () }
+   |           ^ pattern `_` not covered
+   |
+   = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0004`.
diff --git a/src/test/ui/pattern/usefulness/match-privately-empty.rs b/src/test/ui/pattern/usefulness/match-privately-empty.rs
new file mode 100644
index 00000000000..315eb03d165
--- /dev/null
+++ b/src/test/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/src/test/ui/pattern/usefulness/match-privately-empty.stderr b/src/test/ui/pattern/usefulness/match-privately-empty.stderr
new file mode 100644
index 00000000000..f79d180a1b8
--- /dev/null
+++ b/src/test/ui/pattern/usefulness/match-privately-empty.stderr
@@ -0,0 +1,11 @@
+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
+   |
+   = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0004`.
diff --git a/src/test/ui/pattern/usefulness/match-range-fail-dominate.rs b/src/test/ui/pattern/usefulness/match-range-fail-dominate.rs
new file mode 100644
index 00000000000..7de7b7e79be
--- /dev/null
+++ b/src/test/ui/pattern/usefulness/match-range-fail-dominate.rs
@@ -0,0 +1,45 @@
+#![deny(unreachable_patterns, overlapping_patterns)]
+
+fn main() {
+    match 5 {
+      1 ..= 10 => { }
+      5 ..= 6 => { }
+      //~^ ERROR unreachable pattern
+      _ => {}
+    };
+
+    match 5 {
+      3 ..= 6 => { }
+      4 ..= 6 => { }
+      //~^ ERROR unreachable pattern
+      _ => {}
+    };
+
+    match 5 {
+      4 ..= 6 => { }
+      4 ..= 6 => { }
+      //~^ ERROR unreachable pattern
+      _ => {}
+    };
+
+    match 'c' {
+      'A' ..= 'z' => {}
+      'a' ..= 'z' => {}
+      //~^ ERROR unreachable pattern
+      _ => {}
+    };
+
+    match 1.0f64 {
+      0.01f64 ..= 6.5f64 => {}
+      //~^ WARNING floating-point types cannot be used in patterns
+      //~| WARNING floating-point types cannot be used in patterns
+      //~| WARNING floating-point types cannot be used in patterns
+      //~| WARNING this was previously accepted by the compiler
+      //~| WARNING this was previously accepted by the compiler
+      //~| WARNING this was previously accepted by the compiler
+      0.02f64 => {} //~ ERROR unreachable pattern
+      //~^ WARNING floating-point types cannot be used in patterns
+      //~| WARNING this was previously accepted by the compiler
+      _ => {}
+    };
+}
diff --git a/src/test/ui/pattern/usefulness/match-range-fail-dominate.stderr b/src/test/ui/pattern/usefulness/match-range-fail-dominate.stderr
new file mode 100644
index 00000000000..c15186d2558
--- /dev/null
+++ b/src/test/ui/pattern/usefulness/match-range-fail-dominate.stderr
@@ -0,0 +1,75 @@
+error: unreachable pattern
+  --> $DIR/match-range-fail-dominate.rs:6:7
+   |
+LL |       5 ..= 6 => { }
+   |       ^^^^^^^
+   |
+note: lint level defined here
+  --> $DIR/match-range-fail-dominate.rs:1:9
+   |
+LL | #![deny(unreachable_patterns, overlapping_patterns)]
+   |         ^^^^^^^^^^^^^^^^^^^^
+
+error: unreachable pattern
+  --> $DIR/match-range-fail-dominate.rs:13:7
+   |
+LL |       4 ..= 6 => { }
+   |       ^^^^^^^
+
+error: unreachable pattern
+  --> $DIR/match-range-fail-dominate.rs:20:7
+   |
+LL |       4 ..= 6 => { }
+   |       ^^^^^^^
+
+error: unreachable pattern
+  --> $DIR/match-range-fail-dominate.rs:27:7
+   |
+LL |       'a' ..= 'z' => {}
+   |       ^^^^^^^^^^^
+
+warning: floating-point types cannot be used in patterns
+  --> $DIR/match-range-fail-dominate.rs:33:7
+   |
+LL |       0.01f64 ..= 6.5f64 => {}
+   |       ^^^^^^^
+   |
+   = note: `#[warn(illegal_floating_point_literal_pattern)]` on by default
+   = 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 #41620 <https://github.com/rust-lang/rust/issues/41620>
+
+warning: floating-point types cannot be used in patterns
+  --> $DIR/match-range-fail-dominate.rs:33:19
+   |
+LL |       0.01f64 ..= 6.5f64 => {}
+   |                   ^^^^^^
+   |
+   = 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 #41620 <https://github.com/rust-lang/rust/issues/41620>
+
+warning: floating-point types cannot be used in patterns
+  --> $DIR/match-range-fail-dominate.rs:40:7
+   |
+LL |       0.02f64 => {}
+   |       ^^^^^^^
+   |
+   = 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 #41620 <https://github.com/rust-lang/rust/issues/41620>
+
+error: unreachable pattern
+  --> $DIR/match-range-fail-dominate.rs:40:7
+   |
+LL |       0.02f64 => {}
+   |       ^^^^^^^
+
+warning: floating-point types cannot be used in patterns
+  --> $DIR/match-range-fail-dominate.rs:33:7
+   |
+LL |       0.01f64 ..= 6.5f64 => {}
+   |       ^^^^^^^
+   |
+   = 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 #41620 <https://github.com/rust-lang/rust/issues/41620>
+
+error: aborting due to 5 previous errors
+
diff --git a/src/test/ui/pattern/usefulness/match-ref-ice.rs b/src/test/ui/pattern/usefulness/match-ref-ice.rs
new file mode 100644
index 00000000000..dee110f96cd
--- /dev/null
+++ b/src/test/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/src/test/ui/pattern/usefulness/match-ref-ice.stderr b/src/test/ui/pattern/usefulness/match-ref-ice.stderr
new file mode 100644
index 00000000000..c4bfa0afcc2
--- /dev/null
+++ b/src/test/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: lint level defined here
+  --> $DIR/match-ref-ice.rs:1:9
+   |
+LL | #![deny(unreachable_patterns)]
+   |         ^^^^^^^^^^^^^^^^^^^^
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/pattern/usefulness/match-slice-patterns.rs b/src/test/ui/pattern/usefulness/match-slice-patterns.rs
new file mode 100644
index 00000000000..afbeb61e441
--- /dev/null
+++ b/src/test/ui/pattern/usefulness/match-slice-patterns.rs
@@ -0,0 +1,14 @@
+#![feature(slice_patterns)]
+
+fn check(list: &[Option<()>]) {
+    match list {
+    //~^ ERROR `&[_, Some(_), None, _]` not covered
+        &[] => {},
+        &[_] => {},
+        &[_, _] => {},
+        &[_, None, ..] => {},
+        &[.., Some(_), _] => {},
+    }
+}
+
+fn main() {}
diff --git a/src/test/ui/pattern/usefulness/match-slice-patterns.stderr b/src/test/ui/pattern/usefulness/match-slice-patterns.stderr
new file mode 100644
index 00000000000..24769db34c9
--- /dev/null
+++ b/src/test/ui/pattern/usefulness/match-slice-patterns.stderr
@@ -0,0 +1,11 @@
+error[E0004]: non-exhaustive patterns: `&[_, Some(_), None, _]` not covered
+  --> $DIR/match-slice-patterns.rs:4:11
+   |
+LL |     match list {
+   |           ^^^^ pattern `&[_, Some(_), None, _]` not covered
+   |
+   = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0004`.
diff --git a/src/test/ui/pattern/usefulness/match-vec-fixed.rs b/src/test/ui/pattern/usefulness/match-vec-fixed.rs
new file mode 100644
index 00000000000..e611779dec2
--- /dev/null
+++ b/src/test/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/src/test/ui/pattern/usefulness/match-vec-fixed.stderr b/src/test/ui/pattern/usefulness/match-vec-fixed.stderr
new file mode 100644
index 00000000000..ae2dd87b695
--- /dev/null
+++ b/src/test/ui/pattern/usefulness/match-vec-fixed.stderr
@@ -0,0 +1,20 @@
+error: unreachable pattern
+  --> $DIR/match-vec-fixed.rs:7:9
+   |
+LL |         [_, _, _] => {}
+   |         ^^^^^^^^^
+   |
+note: lint level 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/src/test/ui/pattern/usefulness/match-vec-unreachable.rs b/src/test/ui/pattern/usefulness/match-vec-unreachable.rs
new file mode 100644
index 00000000000..78810525bad
--- /dev/null
+++ b/src/test/ui/pattern/usefulness/match-vec-unreachable.rs
@@ -0,0 +1,30 @@
+#![feature(slice_patterns)]
+#![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/src/test/ui/pattern/usefulness/match-vec-unreachable.stderr b/src/test/ui/pattern/usefulness/match-vec-unreachable.stderr
new file mode 100644
index 00000000000..415c24ae77e
--- /dev/null
+++ b/src/test/ui/pattern/usefulness/match-vec-unreachable.stderr
@@ -0,0 +1,26 @@
+error: unreachable pattern
+  --> $DIR/match-vec-unreachable.rs:9:9
+   |
+LL |         [(1, 2), (2, 3), b] => (),
+   |         ^^^^^^^^^^^^^^^^^^^
+   |
+note: lint level defined here
+  --> $DIR/match-vec-unreachable.rs:2:9
+   |
+LL | #![deny(unreachable_patterns)]
+   |         ^^^^^^^^^^^^^^^^^^^^
+
+error: unreachable pattern
+  --> $DIR/match-vec-unreachable.rs:19:9
+   |
+LL |         [_, _, _, _, _] => { }
+   |         ^^^^^^^^^^^^^^^
+
+error: unreachable pattern
+  --> $DIR/match-vec-unreachable.rs:27:9
+   |
+LL |         ['a', 'b', 'c'] => {}
+   |         ^^^^^^^^^^^^^^^
+
+error: aborting due to 3 previous errors
+
diff --git a/src/test/ui/pattern/usefulness/nested-exhaustive-match.rs b/src/test/ui/pattern/usefulness/nested-exhaustive-match.rs
new file mode 100644
index 00000000000..8b2294f8432
--- /dev/null
+++ b/src/test/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/src/test/ui/pattern/usefulness/non-exhaustive-defined-here.rs b/src/test/ui/pattern/usefulness/non-exhaustive-defined-here.rs
new file mode 100644
index 00000000000..6f009acbdfe
--- /dev/null
+++ b/src/test/ui/pattern/usefulness/non-exhaustive-defined-here.rs
@@ -0,0 +1,72 @@
+// 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 {
+//~^ `E` defined here
+//~| `E` defined here
+//~| `E` defined here
+//~| `E` defined here
+//~| `E` defined here
+//~| `E` defined here
+    A,
+    B,
+    //~^ not covered
+    //~| not covered
+    //~| not covered
+    //~| not covered
+    //~| not covered
+    //~| 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: `B` and `C` not covered
+        E::A => {}
+    }
+
+    let E::A = e; //~ ERROR refutable pattern in local binding: `B` and `C` not covered
+}
+
+fn by_ref_once(e: &E) {
+    match e { //~ ERROR non-exhaustive patterns: `&B` and `&C` not covered
+        E::A => {}
+    }
+
+    let E::A = e; //~ ERROR refutable pattern in local binding: `&B` and `&C` not covered
+}
+
+fn by_ref_thrice(e: & &mut &E) {
+    match e { //~ ERROR non-exhaustive patterns: `&&mut &B` and `&&mut &C` not covered
+        E::A => {}
+    }
+
+    let E::A = e;
+    //~^ ERROR refutable pattern in local binding: `&&mut &B` and `&&mut &C` not covered
+}
+
+enum Opt {
+//~^ `Opt` defined here
+//~| `Opt` defined here
+    Some(u8),
+    None,
+    //~^ not covered
+}
+
+fn ref_pat(e: Opt) {
+    match e {//~ ERROR non-exhaustive patterns: `None` not covered
+        Opt::Some(ref _x) => {}
+    }
+
+    let Opt::Some(ref _x) = e; //~ ERROR refutable pattern in local binding: `None` not covered
+}
+
+fn main() {}
diff --git a/src/test/ui/pattern/usefulness/non-exhaustive-defined-here.stderr b/src/test/ui/pattern/usefulness/non-exhaustive-defined-here.stderr
new file mode 100644
index 00000000000..e5f01174ac1
--- /dev/null
+++ b/src/test/ui/pattern/usefulness/non-exhaustive-defined-here.stderr
@@ -0,0 +1,198 @@
+error[E0004]: non-exhaustive patterns: `B` and `C` not covered
+  --> $DIR/non-exhaustive-defined-here.rs:32:11
+   |
+LL | / enum E {
+LL | |
+LL | |
+LL | |
+...  |
+LL | |     B,
+   | |     - not covered
+...  |
+LL | |     C
+   | |     - not covered
+...  |
+LL | |
+LL | | }
+   | |_- `E` defined here
+...
+LL |       match e1 {
+   |             ^^ patterns `B` and `C` not covered
+   |
+   = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
+
+error[E0005]: refutable pattern in local binding: `B` and `C` not covered
+  --> $DIR/non-exhaustive-defined-here.rs:36:9
+   |
+LL | / enum E {
+LL | |
+LL | |
+LL | |
+...  |
+LL | |     B,
+   | |     - not covered
+...  |
+LL | |     C
+   | |     - not covered
+...  |
+LL | |
+LL | | }
+   | |_- `E` defined here
+...
+LL |       let E::A = e;
+   |           ^^^^ patterns `B` and `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
+help: you might want to use `if let` to ignore the variant that isn't matched
+   |
+LL |     if let E::A = e { /* */ }
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error[E0004]: non-exhaustive patterns: `&B` and `&C` not covered
+  --> $DIR/non-exhaustive-defined-here.rs:40:11
+   |
+LL | / enum E {
+LL | |
+LL | |
+LL | |
+...  |
+LL | |     B,
+   | |     - not covered
+...  |
+LL | |     C
+   | |     - not covered
+...  |
+LL | |
+LL | | }
+   | |_- `E` defined here
+...
+LL |       match e {
+   |             ^ patterns `&B` and `&C` not covered
+   |
+   = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
+
+error[E0005]: refutable pattern in local binding: `&B` and `&C` not covered
+  --> $DIR/non-exhaustive-defined-here.rs:44:9
+   |
+LL | / enum E {
+LL | |
+LL | |
+LL | |
+...  |
+LL | |     B,
+   | |     - not covered
+...  |
+LL | |     C
+   | |     - not covered
+...  |
+LL | |
+LL | | }
+   | |_- `E` defined here
+...
+LL |       let E::A = e;
+   |           ^^^^ patterns `&B` and `&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
+help: you might want to use `if let` to ignore the variant that isn't matched
+   |
+LL |     if let E::A = e { /* */ }
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error[E0004]: non-exhaustive patterns: `&&mut &B` and `&&mut &C` not covered
+  --> $DIR/non-exhaustive-defined-here.rs:48:11
+   |
+LL | / enum E {
+LL | |
+LL | |
+LL | |
+...  |
+LL | |     B,
+   | |     - not covered
+...  |
+LL | |     C
+   | |     - not covered
+...  |
+LL | |
+LL | | }
+   | |_- `E` defined here
+...
+LL |       match e {
+   |             ^ patterns `&&mut &B` and `&&mut &C` not covered
+   |
+   = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
+
+error[E0005]: refutable pattern in local binding: `&&mut &B` and `&&mut &C` not covered
+  --> $DIR/non-exhaustive-defined-here.rs:52:9
+   |
+LL | / enum E {
+LL | |
+LL | |
+LL | |
+...  |
+LL | |     B,
+   | |     - not covered
+...  |
+LL | |     C
+   | |     - not covered
+...  |
+LL | |
+LL | | }
+   | |_- `E` defined here
+...
+LL |       let E::A = e;
+   |           ^^^^ patterns `&&mut &B` and `&&mut &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
+help: you might want to use `if let` to ignore the variant that isn't matched
+   |
+LL |     if let E::A = e { /* */ }
+   |
+
+error[E0004]: non-exhaustive patterns: `None` not covered
+  --> $DIR/non-exhaustive-defined-here.rs:65:11
+   |
+LL | / enum Opt {
+LL | |
+LL | |
+LL | |     Some(u8),
+LL | |     None,
+   | |     ---- not covered
+LL | |
+LL | | }
+   | |_- `Opt` defined here
+...
+LL |       match e {
+   |             ^ pattern `None` not covered
+   |
+   = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
+
+error[E0005]: refutable pattern in local binding: `None` not covered
+  --> $DIR/non-exhaustive-defined-here.rs:69:9
+   |
+LL | / enum Opt {
+LL | |
+LL | |
+LL | |     Some(u8),
+LL | |     None,
+   | |     ---- not covered
+LL | |
+LL | | }
+   | |_- `Opt` defined here
+...
+LL |       let Opt::Some(ref _x) = e;
+   |           ^^^^^^^^^^^^^^^^^ pattern `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
+help: you might want to use `if let` to ignore the variant that isn't matched
+   |
+LL |     if let Opt::Some(ref _x) = e { /* */ }
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+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/src/test/ui/pattern/usefulness/non-exhaustive-float-range-match.rs b/src/test/ui/pattern/usefulness/non-exhaustive-float-range-match.rs
new file mode 100644
index 00000000000..588fecbf10d
--- /dev/null
+++ b/src/test/ui/pattern/usefulness/non-exhaustive-float-range-match.rs
@@ -0,0 +1,13 @@
+#![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 => {}
+    }
+}
diff --git a/src/test/ui/pattern/usefulness/non-exhaustive-float-range-match.stderr b/src/test/ui/pattern/usefulness/non-exhaustive-float-range-match.stderr
new file mode 100644
index 00000000000..6de615c3de4
--- /dev/null
+++ b/src/test/ui/pattern/usefulness/non-exhaustive-float-range-match.stderr
@@ -0,0 +1,11 @@
+error[E0004]: non-exhaustive patterns: `_` not covered
+  --> $DIR/non-exhaustive-float-range-match.rs:10:11
+   |
+LL |     match 0.0 {
+   |           ^^^ pattern `_` not covered
+   |
+   = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0004`.
diff --git a/src/test/ui/pattern/usefulness/non-exhaustive-match-nested.rs b/src/test/ui/pattern/usefulness/non-exhaustive-match-nested.rs
new file mode 100644
index 00000000000..9423a2891a6
--- /dev/null
+++ b/src/test/ui/pattern/usefulness/non-exhaustive-match-nested.rs
@@ -0,0 +1,21 @@
+#![feature(slice_patterns)]
+
+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: `A(C)` not covered
+        T::A(U::D) => { panic!("hello"); }
+        T::B => { panic!("goodbye"); }
+    }
+}
diff --git a/src/test/ui/pattern/usefulness/non-exhaustive-match-nested.stderr b/src/test/ui/pattern/usefulness/non-exhaustive-match-nested.stderr
new file mode 100644
index 00000000000..67c818e19cb
--- /dev/null
+++ b/src/test/ui/pattern/usefulness/non-exhaustive-match-nested.stderr
@@ -0,0 +1,25 @@
+error[E0004]: non-exhaustive patterns: `(Some(&[]), Err(_))` not covered
+  --> $DIR/non-exhaustive-match-nested.rs:7:11
+   |
+LL |     match (l1, l2) {
+   |           ^^^^^^^^ pattern `(Some(&[]), Err(_))` not covered
+   |
+   = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
+
+error[E0004]: non-exhaustive patterns: `A(C)` not covered
+  --> $DIR/non-exhaustive-match-nested.rs:17:11
+   |
+LL | enum T { A(U), B }
+   | ------------------
+   | |        |
+   | |        not covered
+   | `T` defined here
+...
+LL |     match x {
+   |           ^ pattern `A(C)` not covered
+   |
+   = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0004`.
diff --git a/src/test/ui/pattern/usefulness/non-exhaustive-match.rs b/src/test/ui/pattern/usefulness/non-exhaustive-match.rs
new file mode 100644
index 00000000000..0e5a9203c5f
--- /dev/null
+++ b/src/test/ui/pattern/usefulness/non-exhaustive-match.rs
@@ -0,0 +1,64 @@
+#![feature(slice_patterns)]
+#![allow(illegal_floating_point_literal_pattern)]
+
+enum T { A, B }
+
+fn main() {
+    let x = T::A;
+    match x { T::B => { } } //~ ERROR non-exhaustive patterns: `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: `(_, _, std::i32::MIN..=3i32)`
+                      //  and `(_, _, 5i32..=std::i32::MAX)` not covered
+      (_, _, 4) => {}
+    }
+    match (T::A, T::A) { //~ ERROR non-exhaustive patterns: `(A, A)` not covered
+      (T::A, T::B) => {}
+      (T::B, T::A) => {}
+    }
+    match T::A { //~ ERROR non-exhaustive patterns: `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/src/test/ui/pattern/usefulness/non-exhaustive-match.stderr b/src/test/ui/pattern/usefulness/non-exhaustive-match.stderr
new file mode 100644
index 00000000000..5dba05e1642
--- /dev/null
+++ b/src/test/ui/pattern/usefulness/non-exhaustive-match.stderr
@@ -0,0 +1,79 @@
+error[E0004]: non-exhaustive patterns: `A` not covered
+  --> $DIR/non-exhaustive-match.rs:8:11
+   |
+LL | enum T { A, B }
+   | ---------------
+   | |        |
+   | |        not covered
+   | `T` defined here
+...
+LL |     match x { T::B => { } }
+   |           ^ pattern `A` not covered
+   |
+   = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
+
+error[E0004]: non-exhaustive patterns: `false` not covered
+  --> $DIR/non-exhaustive-match.rs:9:11
+   |
+LL |     match true {
+   |           ^^^^ pattern `false` not covered
+   |
+   = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
+
+error[E0004]: non-exhaustive patterns: `Some(_)` not covered
+  --> $DIR/non-exhaustive-match.rs:12:11
+   |
+LL |     match Some(10) {
+   |           ^^^^^^^^ pattern `Some(_)` not covered
+   |
+   = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
+
+error[E0004]: non-exhaustive patterns: `(_, _, std::i32::MIN..=3i32)` and `(_, _, 5i32..=std::i32::MAX)` not covered
+  --> $DIR/non-exhaustive-match.rs:15:11
+   |
+LL |     match (2, 3, 4) {
+   |           ^^^^^^^^^ patterns `(_, _, std::i32::MIN..=3i32)` and `(_, _, 5i32..=std::i32::MAX)` not covered
+   |
+   = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
+
+error[E0004]: non-exhaustive patterns: `(A, A)` not covered
+  --> $DIR/non-exhaustive-match.rs:19:11
+   |
+LL |     match (T::A, T::A) {
+   |           ^^^^^^^^^^^^ pattern `(A, A)` not covered
+   |
+   = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
+
+error[E0004]: non-exhaustive patterns: `B` not covered
+  --> $DIR/non-exhaustive-match.rs:23:11
+   |
+LL | enum T { A, B }
+   | ---------------
+   | |           |
+   | |           not covered
+   | `T` defined here
+...
+LL |     match T::A {
+   |           ^^^^ pattern `B` not covered
+   |
+   = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
+
+error[E0004]: non-exhaustive patterns: `[]` not covered
+  --> $DIR/non-exhaustive-match.rs:34:11
+   |
+LL |     match *vec {
+   |           ^^^^ pattern `[]` not covered
+   |
+   = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
+
+error[E0004]: non-exhaustive patterns: `[_, _, _, _]` not covered
+  --> $DIR/non-exhaustive-match.rs:47:11
+   |
+LL |     match *vec {
+   |           ^^^^ pattern `[_, _, _, _]` not covered
+   |
+   = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
+
+error: aborting due to 8 previous errors
+
+For more information about this error, try `rustc --explain E0004`.
diff --git a/src/test/ui/pattern/usefulness/non-exhaustive-pattern-witness.rs b/src/test/ui/pattern/usefulness/non-exhaustive-pattern-witness.rs
new file mode 100644
index 00000000000..4ca1cbcebcc
--- /dev/null
+++ b/src/test/ui/pattern/usefulness/non-exhaustive-pattern-witness.rs
@@ -0,0 +1,91 @@
+#![feature(slice_patterns)]
+
+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: `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: `East`, `South` and `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 `Second`, `Third`, `Fourth` and 8 more not covered
+
+        ExcessiveEnum::First => ()
+    }
+}
+
+fn enum_struct_variant() {
+    match Color::Red {
+    //~^ ERROR non-exhaustive patterns: `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: `[Second(true), 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/src/test/ui/pattern/usefulness/non-exhaustive-pattern-witness.stderr b/src/test/ui/pattern/usefulness/non-exhaustive-pattern-witness.stderr
new file mode 100644
index 00000000000..a0b497dd4c0
--- /dev/null
+++ b/src/test/ui/pattern/usefulness/non-exhaustive-pattern-witness.stderr
@@ -0,0 +1,95 @@
+error[E0004]: non-exhaustive patterns: `Foo { first: false, second: Some([_, _, _, _]) }` not covered
+  --> $DIR/non-exhaustive-pattern-witness.rs:9:11
+   |
+LL | / struct Foo {
+LL | |     first: bool,
+LL | |     second: Option<[usize; 4]>
+LL | | }
+   | |_- `Foo` defined here
+...
+LL |       match (Foo { first: true, second: None }) {
+   |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ pattern `Foo { first: false, second: Some([_, _, _, _]) }` not covered
+   |
+   = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
+
+error[E0004]: non-exhaustive patterns: `Red` not covered
+  --> $DIR/non-exhaustive-pattern-witness.rs:25:11
+   |
+LL | / enum Color {
+LL | |     Red,
+   | |     --- not covered
+LL | |     Green,
+LL | |     CustomRGBA { a: bool, r: u8, g: u8, b: u8 }
+LL | | }
+   | |_- `Color` defined here
+...
+LL |       match Color::Red {
+   |             ^^^^^^^^^^ pattern `Red` not covered
+   |
+   = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
+
+error[E0004]: non-exhaustive patterns: `East`, `South` and `West` not covered
+  --> $DIR/non-exhaustive-pattern-witness.rs:37:11
+   |
+LL | / enum Direction {
+LL | |     North, East, South, West
+   | |            ----  -----  ---- not covered
+   | |            |     |
+   | |            |     not covered
+   | |            not covered
+LL | | }
+   | |_- `Direction` defined here
+...
+LL |       match Direction::North {
+   |             ^^^^^^^^^^^^^^^^ patterns `East`, `South` and `West` not covered
+   |
+   = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
+
+error[E0004]: non-exhaustive patterns: `Second`, `Third`, `Fourth` and 8 more not covered
+  --> $DIR/non-exhaustive-pattern-witness.rs:48:11
+   |
+LL | / enum ExcessiveEnum {
+LL | |     First, Second, Third, Fourth, Fifth, Sixth, Seventh, Eighth, Ninth, Tenth, Eleventh, Twelfth
+LL | | }
+   | |_- `ExcessiveEnum` defined here
+...
+LL |       match ExcessiveEnum::First {
+   |             ^^^^^^^^^^^^^^^^^^^^ patterns `Second`, `Third`, `Fourth` and 8 more not covered
+   |
+   = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
+
+error[E0004]: non-exhaustive patterns: `CustomRGBA { a: true, .. }` not covered
+  --> $DIR/non-exhaustive-pattern-witness.rs:56:11
+   |
+LL | / enum Color {
+LL | |     Red,
+LL | |     Green,
+LL | |     CustomRGBA { a: bool, r: u8, g: u8, b: u8 }
+   | |     ---------- not covered
+LL | | }
+   | |_- `Color` defined here
+...
+LL |       match Color::Red {
+   |             ^^^^^^^^^^ pattern `CustomRGBA { a: true, .. }` not covered
+   |
+   = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
+
+error[E0004]: non-exhaustive patterns: `[Second(true), Second(false)]` not covered
+  --> $DIR/non-exhaustive-pattern-witness.rs:72:11
+   |
+LL |     match *x {
+   |           ^^ pattern `[Second(true), Second(false)]` not covered
+   |
+   = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
+
+error[E0004]: non-exhaustive patterns: `((), false)` not covered
+  --> $DIR/non-exhaustive-pattern-witness.rs:85:11
+   |
+LL |     match ((), false) {
+   |           ^^^^^^^^^^^ pattern `((), false)` not covered
+   |
+   = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
+
+error: aborting due to 7 previous errors
+
+For more information about this error, try `rustc --explain E0004`.
diff --git a/src/test/ui/pattern/usefulness/refutable-pattern-errors.rs b/src/test/ui/pattern/usefulness/refutable-pattern-errors.rs
new file mode 100644
index 00000000000..d4afe17ca74
--- /dev/null
+++ b/src/test/ui/pattern/usefulness/refutable-pattern-errors.rs
@@ -0,0 +1,9 @@
+// ignore-tidy-linelength
+
+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: `(std::i32::MIN..=0i32, _)` and `(2i32..=std::i32::MAX, _)` not covered
+}
diff --git a/src/test/ui/pattern/usefulness/refutable-pattern-errors.stderr b/src/test/ui/pattern/usefulness/refutable-pattern-errors.stderr
new file mode 100644
index 00000000000..0cf5d9cd5f1
--- /dev/null
+++ b/src/test/ui/pattern/usefulness/refutable-pattern-errors.stderr
@@ -0,0 +1,22 @@
+error[E0005]: refutable pattern in function argument: `(_, _)` not covered
+  --> $DIR/refutable-pattern-errors.rs:3:9
+   |
+LL | fn func((1, (Some(1), 2..=3)): (isize, (Option<isize>, isize))) { }
+   |         ^^^^^^^^^^^^^^^^^^^^^ pattern `(_, _)` not covered
+
+error[E0005]: refutable pattern in local binding: `(std::i32::MIN..=0i32, _)` and `(2i32..=std::i32::MAX, _)` not covered
+  --> $DIR/refutable-pattern-errors.rs:7:9
+   |
+LL |     let (1, (Some(1), 2..=3)) = (1, (None, 2));
+   |         ^^^^^^^^^^^^^^^^^^^^^ patterns `(std::i32::MIN..=0i32, _)` and `(2i32..=std::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
+help: you might want to use `if let` to ignore the variant that isn't matched
+   |
+LL |     if let (1, (Some(1), 2..=3)) = (1, (None, 2)) { /* */ }
+   |
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0005`.
diff --git a/src/test/ui/pattern/usefulness/refutable-pattern-in-fn-arg.rs b/src/test/ui/pattern/usefulness/refutable-pattern-in-fn-arg.rs
new file mode 100644
index 00000000000..a2d9e1935de
--- /dev/null
+++ b/src/test/ui/pattern/usefulness/refutable-pattern-in-fn-arg.rs
@@ -0,0 +1,5 @@
+fn main() {
+    let f = |3: isize| println!("hello");
+    //~^ ERROR refutable pattern in function argument: `_` not covered
+    f(4);
+}
diff --git a/src/test/ui/pattern/usefulness/refutable-pattern-in-fn-arg.stderr b/src/test/ui/pattern/usefulness/refutable-pattern-in-fn-arg.stderr
new file mode 100644
index 00000000000..8666e6bb73e
--- /dev/null
+++ b/src/test/ui/pattern/usefulness/refutable-pattern-in-fn-arg.stderr
@@ -0,0 +1,9 @@
+error[E0005]: refutable pattern in function argument: `_` not covered
+  --> $DIR/refutable-pattern-in-fn-arg.rs:2:14
+   |
+LL |     let f = |3: isize| println!("hello");
+   |              ^ pattern `_` not covered
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0005`.
diff --git a/src/test/ui/pattern/usefulness/struct-like-enum-nonexhaustive.rs b/src/test/ui/pattern/usefulness/struct-like-enum-nonexhaustive.rs
new file mode 100644
index 00000000000..b1fc0f5ad3e
--- /dev/null
+++ b/src/test/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/src/test/ui/pattern/usefulness/struct-like-enum-nonexhaustive.stderr b/src/test/ui/pattern/usefulness/struct-like-enum-nonexhaustive.stderr
new file mode 100644
index 00000000000..d6b5af17964
--- /dev/null
+++ b/src/test/ui/pattern/usefulness/struct-like-enum-nonexhaustive.stderr
@@ -0,0 +1,18 @@
+error[E0004]: non-exhaustive patterns: `B { x: Some(_) }` not covered
+  --> $DIR/struct-like-enum-nonexhaustive.rs:8:11
+   |
+LL | / enum A {
+LL | |     B { x: Option<isize> },
+   | |     - not covered
+LL | |     C
+LL | | }
+   | |_- `A` defined here
+...
+LL |       match x {
+   |             ^ pattern `B { x: Some(_) }` not covered
+   |
+   = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0004`.
diff --git a/src/test/ui/pattern/usefulness/struct-pattern-match-useless.rs b/src/test/ui/pattern/usefulness/struct-pattern-match-useless.rs
new file mode 100644
index 00000000000..93f0a931761
--- /dev/null
+++ b/src/test/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/src/test/ui/pattern/usefulness/struct-pattern-match-useless.stderr b/src/test/ui/pattern/usefulness/struct-pattern-match-useless.stderr
new file mode 100644
index 00000000000..5b0c9305448
--- /dev/null
+++ b/src/test/ui/pattern/usefulness/struct-pattern-match-useless.stderr
@@ -0,0 +1,14 @@
+error: unreachable pattern
+  --> $DIR/struct-pattern-match-useless.rs:12:9
+   |
+LL |         Foo { .. } => ()
+   |         ^^^^^^^^^^
+   |
+note: lint level defined here
+  --> $DIR/struct-pattern-match-useless.rs:1:9
+   |
+LL | #![deny(unreachable_patterns)]
+   |         ^^^^^^^^^^^^^^^^^^^^
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/pattern/usefulness/tuple-struct-nonexhaustive.rs b/src/test/ui/pattern/usefulness/tuple-struct-nonexhaustive.rs
new file mode 100644
index 00000000000..76bcf3fbd4d
--- /dev/null
+++ b/src/test/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/src/test/ui/pattern/usefulness/tuple-struct-nonexhaustive.stderr b/src/test/ui/pattern/usefulness/tuple-struct-nonexhaustive.stderr
new file mode 100644
index 00000000000..bbdf9ceed23
--- /dev/null
+++ b/src/test/ui/pattern/usefulness/tuple-struct-nonexhaustive.stderr
@@ -0,0 +1,14 @@
+error[E0004]: non-exhaustive patterns: `Foo(_, _)` not covered
+  --> $DIR/tuple-struct-nonexhaustive.rs:5:11
+   |
+LL | struct Foo(isize, isize);
+   | ------------------------- `Foo` defined here
+...
+LL |     match x {
+   |           ^ pattern `Foo(_, _)` not covered
+   |
+   = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0004`.