diff --git a/compiler/rustc_mir_build/src/thir/pattern/_match.rs b/compiler/rustc_mir_build/src/thir/pattern/_match.rs
index 6bea2381862e9..79a74e387435c 100644
--- a/compiler/rustc_mir_build/src/thir/pattern/_match.rs
+++ b/compiler/rustc_mir_build/src/thir/pattern/_match.rs
@@ -3,6 +3,7 @@
 //!     - ui/or-patterns
 //!     - ui/consts/const_in_pattern
 //!     - ui/rfc-2008-non-exhaustive
+//!     - ui/half-open-range-patterns
 //!     - probably many others
 //! I (Nadrieril) prefer to put new tests in `ui/pattern/usefulness` unless there's a specific
 //! reason not to, for example if they depend on a particular feature like or_patterns.
diff --git a/src/test/ui/feature-gates/feature-gate-precise_pointer_size_matching.rs b/src/test/ui/feature-gates/feature-gate-precise_pointer_size_matching.rs
index 1208552d25637..d42fbf22938c0 100644
--- a/src/test/ui/feature-gates/feature-gate-precise_pointer_size_matching.rs
+++ b/src/test/ui/feature-gates/feature-gate-precise_pointer_size_matching.rs
@@ -1,14 +1,19 @@
-#![feature(exclusive_range_pattern)]
-
-use std::usize::MAX;
+use std::{isize, usize};
 
 fn main() {
-    match 0usize { //~ERROR non-exhaustive patterns: `_` not covered
-        0..=MAX => {}
+    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
-        1..=20 => {}
-        -5..3 => {}
+    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/src/test/ui/feature-gates/feature-gate-precise_pointer_size_matching.stderr b/src/test/ui/feature-gates/feature-gate-precise_pointer_size_matching.stderr
index c7a63e5d50252..da308c292dfab 100644
--- a/src/test/ui/feature-gates/feature-gate-precise_pointer_size_matching.stderr
+++ b/src/test/ui/feature-gates/feature-gate-precise_pointer_size_matching.stderr
@@ -1,5 +1,5 @@
 error[E0004]: non-exhaustive patterns: `_` not covered
-  --> $DIR/feature-gate-precise_pointer_size_matching.rs:6:11
+  --> $DIR/feature-gate-precise_pointer_size_matching.rs:4:11
    |
 LL |     match 0usize {
    |           ^^^^^^ pattern `_` not covered
@@ -10,7 +10,7 @@ LL |     match 0usize {
    = help: add `#![feature(precise_pointer_size_matching)]` to the crate attributes to enable precise `usize` matching
 
 error[E0004]: non-exhaustive patterns: `_` not covered
-  --> $DIR/feature-gate-precise_pointer_size_matching.rs:10:11
+  --> $DIR/feature-gate-precise_pointer_size_matching.rs:12:11
    |
 LL |     match 0isize {
    |           ^^^^^^ pattern `_` not covered
diff --git a/src/test/ui/pattern/usefulness/irrefutable-exhaustive-integer-binding.rs b/src/test/ui/pattern/integer-range-binding.rs
similarity index 100%
rename from src/test/ui/pattern/usefulness/irrefutable-exhaustive-integer-binding.rs
rename to src/test/ui/pattern/integer-range-binding.rs
diff --git a/src/test/ui/pattern/const-pat-ice.rs b/src/test/ui/pattern/usefulness/const-pat-ice.rs
similarity index 100%
rename from src/test/ui/pattern/const-pat-ice.rs
rename to src/test/ui/pattern/usefulness/const-pat-ice.rs
diff --git a/src/test/ui/pattern/deny-irrefutable-let-patterns.rs b/src/test/ui/pattern/usefulness/deny-irrefutable-let-patterns.rs
similarity index 100%
rename from src/test/ui/pattern/deny-irrefutable-let-patterns.rs
rename to src/test/ui/pattern/usefulness/deny-irrefutable-let-patterns.rs
diff --git a/src/test/ui/pattern/deny-irrefutable-let-patterns.stderr b/src/test/ui/pattern/usefulness/deny-irrefutable-let-patterns.stderr
similarity index 100%
rename from src/test/ui/pattern/deny-irrefutable-let-patterns.stderr
rename to src/test/ui/pattern/usefulness/deny-irrefutable-let-patterns.stderr
diff --git a/src/test/ui/pattern/usefulness/exhaustive_integer_patterns.rs b/src/test/ui/pattern/usefulness/exhaustive_integer_patterns.rs
deleted file mode 100644
index 78cc0d28fb037..0000000000000
--- a/src/test/ui/pattern/usefulness/exhaustive_integer_patterns.rs
+++ /dev/null
@@ -1,172 +0,0 @@
-#![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 => {}
-    }
-
-    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/src/test/ui/pattern/usefulness/exhaustive_integer_patterns.stderr b/src/test/ui/pattern/usefulness/exhaustive_integer_patterns.stderr
deleted file mode 100644
index 9f076c50a8f09..0000000000000
--- a/src/test/ui/pattern/usefulness/exhaustive_integer_patterns.stderr
+++ /dev/null
@@ -1,146 +0,0 @@
-error: unreachable pattern
-  --> $DIR/exhaustive_integer_patterns.rs:23:9
-   |
-LL |         200 => {}
-   |         ^^^
-   |
-note: the lint level is defined here
-  --> $DIR/exhaustive_integer_patterns.rs:3:9
-   |
-LL | #![deny(unreachable_patterns)]
-   |         ^^^^^^^^^^^^^^^^^^^^
-
-error[E0004]: non-exhaustive patterns: `128_u8..=u8::MAX` not covered
-  --> $DIR/exhaustive_integer_patterns.rs:28:11
-   |
-LL |     match x {
-   |           ^ pattern `128_u8..=u8::MAX` not covered
-   |
-   = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
-   = note: the matched value is of type `u8`
-
-error[E0004]: non-exhaustive patterns: `11_u8..=19_u8`, `31_u8..=34_u8`, `36_u8..=69_u8` and 1 more not covered
-  --> $DIR/exhaustive_integer_patterns.rs:33:11
-   |
-LL |     match x {
-   |           ^ patterns `11_u8..=19_u8`, `31_u8..=34_u8`, `36_u8..=69_u8` and 1 more not covered
-   |
-   = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
-   = note: the matched value is of type `u8`
-
-error: unreachable pattern
-  --> $DIR/exhaustive_integer_patterns.rs:44:9
-   |
-LL |         -2..=20 => {}
-   |         ^^^^^^^
-
-error[E0004]: non-exhaustive patterns: `i8::MIN..=-8_i8`, `-6_i8`, `121_i8..=124_i8` and 1 more not covered
-  --> $DIR/exhaustive_integer_patterns.rs:41:11
-   |
-LL |     match x {
-   |           ^ patterns `i8::MIN..=-8_i8`, `-6_i8`, `121_i8..=124_i8` and 1 more not covered
-   |
-   = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
-   = note: the matched value is of type `i8`
-
-error[E0004]: non-exhaustive patterns: `i8::MIN` not covered
-  --> $DIR/exhaustive_integer_patterns.rs:83:11
-   |
-LL |     match 0i8 {
-   |           ^^^ pattern `i8::MIN` not covered
-   |
-   = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
-   = note: the matched value is of type `i8`
-
-error[E0004]: non-exhaustive patterns: `0_i16` not covered
-  --> $DIR/exhaustive_integer_patterns.rs:91:11
-   |
-LL |     match 0i16 {
-   |           ^^^^ pattern `0_i16` not covered
-   |
-   = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
-   = note: the matched value is of type `i16`
-
-error[E0004]: non-exhaustive patterns: `128_u8..=u8::MAX` not covered
-  --> $DIR/exhaustive_integer_patterns.rs:109:11
-   |
-LL |     match 0u8 {
-   |           ^^^ pattern `128_u8..=u8::MAX` not covered
-   |
-   = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
-   = note: the matched value is of type `u8`
-
-error[E0004]: non-exhaustive patterns: `(0_u8, Some(_))` and `(2_u8..=u8::MAX, Some(_))` not covered
-  --> $DIR/exhaustive_integer_patterns.rs:121:11
-   |
-LL |     match (0u8, Some(())) {
-   |           ^^^^^^^^^^^^^^^ patterns `(0_u8, Some(_))` and `(2_u8..=u8::MAX, Some(_))` not covered
-   |
-   = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
-   = note: the matched value is of type `(u8, Option<()>)`
-
-error[E0004]: non-exhaustive patterns: `(126_u8..=127_u8, false)` not covered
-  --> $DIR/exhaustive_integer_patterns.rs:126:11
-   |
-LL |     match (0u8, true) {
-   |           ^^^^^^^^^^^ pattern `(126_u8..=127_u8, false)` not covered
-   |
-   = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
-   = note: the matched value is of type `(u8, bool)`
-
-error: multiple patterns covering the same range
-  --> $DIR/exhaustive_integer_patterns.rs:141:9
-   |
-LL |         0 .. 2 => {}
-   |         ------ this range overlaps on `1_u8`
-LL |         1 ..= 2 => {}
-   |         ^^^^^^^ overlapping patterns
-   |
-note: the lint level is defined here
-  --> $DIR/exhaustive_integer_patterns.rs:4:9
-   |
-LL | #![deny(overlapping_patterns)]
-   |         ^^^^^^^^^^^^^^^^^^^^
-
-error[E0004]: non-exhaustive patterns: `u128::MAX` not covered
-  --> $DIR/exhaustive_integer_patterns.rs:146:11
-   |
-LL |     match 0u128 {
-   |           ^^^^^ pattern `u128::MAX` not covered
-   |
-   = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
-   = note: the matched value is of type `u128`
-
-error[E0004]: non-exhaustive patterns: `5_u128..=u128::MAX` not covered
-  --> $DIR/exhaustive_integer_patterns.rs:150:11
-   |
-LL |     match 0u128 {
-   |           ^^^^^ pattern `5_u128..=u128::MAX` not covered
-   |
-   = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
-   = note: the matched value is of type `u128`
-
-error[E0004]: non-exhaustive patterns: `0_u128..=3_u128` not covered
-  --> $DIR/exhaustive_integer_patterns.rs:154:11
-   |
-LL |     match 0u128 {
-   |           ^^^^^ pattern `0_u128..=3_u128` not covered
-   |
-   = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
-   = note: the matched value is of type `u128`
-
-error: unreachable pattern
-  --> $DIR/exhaustive_integer_patterns.rs:162:9
-   |
-LL |         &FOO => {}
-   |         ^^^^
-
-error: unreachable pattern
-  --> $DIR/exhaustive_integer_patterns.rs:163:9
-   |
-LL |         BAR => {}
-   |         ^^^
-
-error: aborting due to 16 previous errors
-
-For more information about this 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/floats.rs
similarity index 66%
rename from src/test/ui/pattern/usefulness/non-exhaustive-float-range-match.rs
rename to src/test/ui/pattern/usefulness/floats.rs
index 588fecbf10dd5..095f5ac9a8970 100644
--- a/src/test/ui/pattern/usefulness/non-exhaustive-float-range-match.rs
+++ b/src/test/ui/pattern/usefulness/floats.rs
@@ -10,4 +10,10 @@ fn main() {
     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/src/test/ui/pattern/usefulness/non-exhaustive-float-range-match.stderr b/src/test/ui/pattern/usefulness/floats.stderr
similarity index 53%
rename from src/test/ui/pattern/usefulness/non-exhaustive-float-range-match.stderr
rename to src/test/ui/pattern/usefulness/floats.stderr
index 4835fa86cc0ee..464bfbdb2c3b2 100644
--- a/src/test/ui/pattern/usefulness/non-exhaustive-float-range-match.stderr
+++ b/src/test/ui/pattern/usefulness/floats.stderr
@@ -1,5 +1,5 @@
 error[E0004]: non-exhaustive patterns: `_` not covered
-  --> $DIR/non-exhaustive-float-range-match.rs:10:11
+  --> $DIR/floats.rs:10:11
    |
 LL |     match 0.0 {
    |           ^^^ pattern `_` not covered
@@ -7,6 +7,18 @@ LL |     match 0.0 {
    = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
    = note: the matched value is of type `f64`
 
-error: aborting due to previous error
+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/src/test/ui/pattern/usefulness/guards-not-exhaustive.rs b/src/test/ui/pattern/usefulness/guards-not-exhaustive.rs
deleted file mode 100644
index b74f162c0c622..0000000000000
--- a/src/test/ui/pattern/usefulness/guards-not-exhaustive.rs
+++ /dev/null
@@ -1,18 +0,0 @@
-// 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/usefulness/guards.rs b/src/test/ui/pattern/usefulness/guards.rs
new file mode 100644
index 0000000000000..b15440cf608bd
--- /dev/null
+++ b/src/test/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/src/test/ui/pattern/usefulness/guards.stderr b/src/test/ui/pattern/usefulness/guards.stderr
new file mode 100644
index 0000000000000..61f7facb330da
--- /dev/null
+++ b/src/test/ui/pattern/usefulness/guards.stderr
@@ -0,0 +1,12 @@
+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
+   |
+   = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
+   = note: the matched value is of type `u8`
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0004`.
diff --git a/src/test/ui/pattern/usefulness/integer-ranges/exhaustiveness.rs b/src/test/ui/pattern/usefulness/integer-ranges/exhaustiveness.rs
new file mode 100644
index 0000000000000..5a44dfc28bb45
--- /dev/null
+++ b/src/test/ui/pattern/usefulness/integer-ranges/exhaustiveness.rs
@@ -0,0 +1,101 @@
+#![feature(exclusive_range_pattern)]
+#![feature(assoc_char_consts)]
+#![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/src/test/ui/pattern/usefulness/integer-ranges/exhaustiveness.stderr b/src/test/ui/pattern/usefulness/integer-ranges/exhaustiveness.stderr
new file mode 100644
index 0000000000000..2e0023348e4d8
--- /dev/null
+++ b/src/test/ui/pattern/usefulness/integer-ranges/exhaustiveness.stderr
@@ -0,0 +1,111 @@
+error[E0004]: non-exhaustive patterns: `u8::MAX` not covered
+  --> $DIR/exhaustiveness.rs:47:8
+   |
+LL |     m!(0u8, 0..255);
+   |        ^^^ pattern `u8::MAX` not covered
+   |
+   = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
+   = note: the matched value is of type `u8`
+
+error[E0004]: non-exhaustive patterns: `u8::MAX` not covered
+  --> $DIR/exhaustiveness.rs:48:8
+   |
+LL |     m!(0u8, 0..=254);
+   |        ^^^ pattern `u8::MAX` not covered
+   |
+   = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
+   = note: the matched value is of type `u8`
+
+error[E0004]: non-exhaustive patterns: `0_u8` not covered
+  --> $DIR/exhaustiveness.rs:49:8
+   |
+LL |     m!(0u8, 1..=255);
+   |        ^^^ pattern `0_u8` not covered
+   |
+   = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
+   = note: the matched value is of type `u8`
+
+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
+   |
+   = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
+   = note: the matched value is of type `u8`
+
+error[E0004]: non-exhaustive patterns: `i8::MAX` not covered
+  --> $DIR/exhaustiveness.rs:51:8
+   |
+LL |     m!(0i8, -128..127);
+   |        ^^^ pattern `i8::MAX` not covered
+   |
+   = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
+   = note: the matched value is of type `i8`
+
+error[E0004]: non-exhaustive patterns: `i8::MAX` not covered
+  --> $DIR/exhaustiveness.rs:52:8
+   |
+LL |     m!(0i8, -128..=126);
+   |        ^^^ pattern `i8::MAX` not covered
+   |
+   = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
+   = note: the matched value is of type `i8`
+
+error[E0004]: non-exhaustive patterns: `i8::MIN` not covered
+  --> $DIR/exhaustiveness.rs:53:8
+   |
+LL |     m!(0i8, -127..=127);
+   |        ^^^ pattern `i8::MIN` not covered
+   |
+   = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
+   = note: the matched value is of type `i8`
+
+error[E0004]: non-exhaustive patterns: `0_i8` not covered
+  --> $DIR/exhaustiveness.rs:54:11
+   |
+LL |     match 0i8 {
+   |           ^^^ pattern `0_i8` not covered
+   |
+   = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
+   = note: the matched value is of type `i8`
+
+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
+   |
+   = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
+   = note: the matched value is of type `u128`
+
+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
+   |
+   = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
+   = note: the matched value is of type `u128`
+
+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
+   |
+   = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
+   = note: the matched value is of type `u128`
+
+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
+   |
+   = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
+   = note: the matched value is of type `(u8, bool)`
+
+error: aborting due to 12 previous errors
+
+For more information about this error, try `rustc --explain E0004`.
diff --git a/src/test/ui/pattern/usefulness/integer-ranges/overlapping_range_endpoints.rs b/src/test/ui/pattern/usefulness/integer-ranges/overlapping_range_endpoints.rs
new file mode 100644
index 0000000000000..af720a0569322
--- /dev/null
+++ b/src/test/ui/pattern/usefulness/integer-ranges/overlapping_range_endpoints.rs
@@ -0,0 +1,53 @@
+#![feature(exclusive_range_pattern)]
+#![deny(overlapping_patterns)]
+
+macro_rules! m {
+    ($s:expr, $t1:pat, $t2:pat) => {
+        match $s {
+            $t1 => {}
+            $t2 => {}
+            _ => {}
+        }
+    }
+}
+
+fn main() {
+    m!(0u8, 20..=30, 30..=40); //~ ERROR multiple patterns covering the same range
+    m!(0u8, 30..=40, 20..=30); //~ ERROR multiple patterns covering the same range
+    m!(0u8, 20..=30, 31..=40);
+    m!(0u8, 20..=30, 29..=40);
+    m!(0u8, 20.. 30, 29..=40); //~ ERROR multiple patterns covering the same range
+    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 covering the same range
+    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 covering the same range
+    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); //~ ERROR multiple patterns covering the same range
+    m!(0u8, 25, 20..=30);
+    m!(0u8, 30, 20..=30); //~ ERROR multiple patterns covering the same range
+
+    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 covering the same range
+        (false, 10..20) => {}
+        _ => {}
+    }
+    match Some(0u8) {
+        Some(0..=10) => {}
+        Some(10..20) => {} //~ ERROR multiple patterns covering the same range
+        _ => {}
+    }
+}
diff --git a/src/test/ui/pattern/usefulness/integer-ranges/overlapping_range_endpoints.stderr b/src/test/ui/pattern/usefulness/integer-ranges/overlapping_range_endpoints.stderr
new file mode 100644
index 0000000000000..7bb747cdf6fc1
--- /dev/null
+++ b/src/test/ui/pattern/usefulness/integer-ranges/overlapping_range_endpoints.stderr
@@ -0,0 +1,80 @@
+error: multiple patterns covering the same range
+  --> $DIR/overlapping_range_endpoints.rs:15:22
+   |
+LL |     m!(0u8, 20..=30, 30..=40);
+   |             -------  ^^^^^^^ overlapping patterns
+   |             |
+   |             this range overlaps on `30_u8`
+   |
+note: the lint level is defined here
+  --> $DIR/overlapping_range_endpoints.rs:2:9
+   |
+LL | #![deny(overlapping_patterns)]
+   |         ^^^^^^^^^^^^^^^^^^^^
+
+error: multiple patterns covering the same range
+  --> $DIR/overlapping_range_endpoints.rs:16:22
+   |
+LL |     m!(0u8, 30..=40, 20..=30);
+   |             -------  ^^^^^^^ overlapping patterns
+   |             |
+   |             this range overlaps on `30_u8`
+
+error: multiple patterns covering the same range
+  --> $DIR/overlapping_range_endpoints.rs:19:22
+   |
+LL |     m!(0u8, 20.. 30, 29..=40);
+   |             -------  ^^^^^^^ overlapping patterns
+   |             |
+   |             this range overlaps on `29_u8`
+
+error: multiple patterns covering the same range
+  --> $DIR/overlapping_range_endpoints.rs:23:22
+   |
+LL |     m!(0u8, 20..=30, 30..=31);
+   |             -------  ^^^^^^^ overlapping patterns
+   |             |
+   |             this range overlaps on `30_u8`
+
+error: multiple patterns covering the same range
+  --> $DIR/overlapping_range_endpoints.rs:27:22
+   |
+LL |     m!(0u8, 20..=30, 19..=20);
+   |             -------  ^^^^^^^ overlapping patterns
+   |             |
+   |             this range overlaps on `20_u8`
+
+error: multiple patterns covering the same range
+  --> $DIR/overlapping_range_endpoints.rs:32:17
+   |
+LL |     m!(0u8, 20, 20..=30);
+   |             --  ^^^^^^^ overlapping patterns
+   |             |
+   |             this range overlaps on `20_u8`
+
+error: multiple patterns covering the same range
+  --> $DIR/overlapping_range_endpoints.rs:34:17
+   |
+LL |     m!(0u8, 30, 20..=30);
+   |             --  ^^^^^^^ overlapping patterns
+   |             |
+   |             this range overlaps on `30_u8`
+
+error: multiple patterns covering the same range
+  --> $DIR/overlapping_range_endpoints.rs:44:16
+   |
+LL |         (true, 0..=10) => {}
+   |                ------ this range overlaps on `10_u8`
+LL |         (true, 10..20) => {}
+   |                ^^^^^^ overlapping patterns
+
+error: multiple patterns covering the same range
+  --> $DIR/overlapping_range_endpoints.rs:50:14
+   |
+LL |         Some(0..=10) => {}
+   |              ------ this range overlaps on `10_u8`
+LL |         Some(10..20) => {}
+   |              ^^^^^^ overlapping patterns
+
+error: aborting due to 9 previous errors
+
diff --git a/src/test/ui/pattern/usefulness/integer-ranges/pointer-sized-int-allow.rs b/src/test/ui/pattern/usefulness/integer-ranges/pointer-sized-int-allow.rs
new file mode 100644
index 0000000000000..6173053cc4f3c
--- /dev/null
+++ b/src/test/ui/pattern/usefulness/integer-ranges/pointer-sized-int-allow.rs
@@ -0,0 +1,38 @@
+#![feature(precise_pointer_size_matching)]
+#![feature(exclusive_range_pattern)]
+
+macro_rules! m {
+    ($s:expr, $($t:tt)+) => {
+        match $s { $($t)+ => {} }
+    }
+}
+
+fn main() {
+    match 0usize {
+        0 ..= usize::MAX => {}
+    }
+
+    match 0isize {
+        isize::MIN ..= isize::MAX => {}
+    }
+
+    m!(0usize, 0..=usize::MAX);
+    m!(0usize, 0..5 | 5..=usize::MAX);
+    m!(0usize, 0..usize::MAX | usize::MAX);
+    m!((0usize, true), (0..5, true) | (5..=usize::MAX, true) | (0..=usize::MAX, false));
+
+    m!(0isize, isize::MIN..=isize::MAX);
+    m!(0isize, isize::MIN..5 | 5..=isize::MAX);
+    m!(0isize, isize::MIN..isize::MAX | isize::MAX);
+    m!((0isize, true), (isize::MIN..5, true)
+        | (5..=isize::MAX, true) | (isize::MIN..=isize::MAX, false));
+
+    match 0isize {
+        isize::MIN ..= -1 => {}
+        0 => {}
+        1 ..= isize::MAX => {}
+    }
+
+    match 7usize {}
+    //~^ ERROR non-exhaustive patterns
+}
diff --git a/src/test/ui/pattern/usefulness/integer-ranges/pointer-sized-int-allow.stderr b/src/test/ui/pattern/usefulness/integer-ranges/pointer-sized-int-allow.stderr
new file mode 100644
index 0000000000000..0b3c65166ee18
--- /dev/null
+++ b/src/test/ui/pattern/usefulness/integer-ranges/pointer-sized-int-allow.stderr
@@ -0,0 +1,12 @@
+error[E0004]: non-exhaustive patterns: type `usize` is non-empty
+  --> $DIR/pointer-sized-int-allow.rs:36:11
+   |
+LL |     match 7usize {}
+   |           ^^^^^^
+   |
+   = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
+   = note: the matched value is of type `usize`
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0004`.
diff --git a/src/test/ui/pattern/usefulness/integer-ranges/pointer-sized-int-deny.rs b/src/test/ui/pattern/usefulness/integer-ranges/pointer-sized-int-deny.rs
new file mode 100644
index 0000000000000..9292f22e09e05
--- /dev/null
+++ b/src/test/ui/pattern/usefulness/integer-ranges/pointer-sized-int-deny.rs
@@ -0,0 +1,48 @@
+#![feature(exclusive_range_pattern)]
+
+macro_rules! m {
+    ($s:expr, $($t:tt)+) => {
+        match $s { $($t)+ => {} }
+    }
+}
+
+fn main() {
+    match 0usize {
+        //~^ ERROR non-exhaustive patterns
+        0 ..= usize::MAX => {}
+    }
+
+    match 0isize {
+        //~^ ERROR non-exhaustive patterns
+        isize::MIN ..= isize::MAX => {}
+    }
+
+    m!(0usize, 0..=usize::MAX);
+    //~^ ERROR non-exhaustive patterns
+    m!(0usize, 0..5 | 5..=usize::MAX);
+    //~^ ERROR non-exhaustive patterns
+    m!(0usize, 0..usize::MAX | usize::MAX);
+    //~^ ERROR non-exhaustive patterns
+    m!((0usize, true), (0..5, true) | (5..=usize::MAX, true) | (0..=usize::MAX, false));
+    //~^ ERROR non-exhaustive patterns
+
+    m!(0isize, isize::MIN..=isize::MAX);
+    //~^ ERROR non-exhaustive patterns
+    m!(0isize, isize::MIN..5 | 5..=isize::MAX);
+    //~^ ERROR non-exhaustive patterns
+    m!(0isize, isize::MIN..isize::MAX | isize::MAX);
+    //~^ ERROR non-exhaustive patterns
+    m!((0isize, true), (isize::MIN..5, true)
+        | (5..=isize::MAX, true) | (isize::MIN..=isize::MAX, false));
+    //~^^ ERROR non-exhaustive patterns
+
+    match 0isize {
+        //~^ ERROR non-exhaustive patterns
+        isize::MIN ..= -1 => {}
+        0 => {}
+        1 ..= isize::MAX => {}
+    }
+
+    match 7usize {}
+    //~^ ERROR non-exhaustive patterns
+}
diff --git a/src/test/ui/pattern/usefulness/integer-ranges/pointer-sized-int-deny.stderr b/src/test/ui/pattern/usefulness/integer-ranges/pointer-sized-int-deny.stderr
new file mode 100644
index 0000000000000..9d566b0e7751f
--- /dev/null
+++ b/src/test/ui/pattern/usefulness/integer-ranges/pointer-sized-int-deny.stderr
@@ -0,0 +1,129 @@
+error[E0004]: non-exhaustive patterns: `_` not covered
+  --> $DIR/pointer-sized-int-deny.rs:10:11
+   |
+LL |     match 0usize {
+   |           ^^^^^^ pattern `_` not covered
+   |
+   = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
+   = 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
+
+error[E0004]: non-exhaustive patterns: `_` not covered
+  --> $DIR/pointer-sized-int-deny.rs:15:11
+   |
+LL |     match 0isize {
+   |           ^^^^^^ pattern `_` not covered
+   |
+   = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
+   = 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
+
+error[E0004]: non-exhaustive patterns: `_` not covered
+  --> $DIR/pointer-sized-int-deny.rs:20:8
+   |
+LL |     m!(0usize, 0..=usize::MAX);
+   |        ^^^^^^ pattern `_` not covered
+   |
+   = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
+   = 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
+
+error[E0004]: non-exhaustive patterns: `_` not covered
+  --> $DIR/pointer-sized-int-deny.rs:22:8
+   |
+LL |     m!(0usize, 0..5 | 5..=usize::MAX);
+   |        ^^^^^^ pattern `_` not covered
+   |
+   = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
+   = 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
+
+error[E0004]: non-exhaustive patterns: `_` not covered
+  --> $DIR/pointer-sized-int-deny.rs:24:8
+   |
+LL |     m!(0usize, 0..usize::MAX | usize::MAX);
+   |        ^^^^^^ pattern `_` not covered
+   |
+   = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
+   = 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
+
+error[E0004]: non-exhaustive patterns: `(_, _)` not covered
+  --> $DIR/pointer-sized-int-deny.rs:26:8
+   |
+LL |     m!((0usize, true), (0..5, true) | (5..=usize::MAX, true) | (0..=usize::MAX, false));
+   |        ^^^^^^^^^^^^^^ pattern `(_, _)` not covered
+   |
+   = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
+   = note: the matched value is of type `(usize, bool)`
+
+error[E0004]: non-exhaustive patterns: `_` not covered
+  --> $DIR/pointer-sized-int-deny.rs:29:8
+   |
+LL |     m!(0isize, isize::MIN..=isize::MAX);
+   |        ^^^^^^ pattern `_` not covered
+   |
+   = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
+   = 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
+
+error[E0004]: non-exhaustive patterns: `_` not covered
+  --> $DIR/pointer-sized-int-deny.rs:31:8
+   |
+LL |     m!(0isize, isize::MIN..5 | 5..=isize::MAX);
+   |        ^^^^^^ pattern `_` not covered
+   |
+   = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
+   = 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
+
+error[E0004]: non-exhaustive patterns: `_` not covered
+  --> $DIR/pointer-sized-int-deny.rs:33:8
+   |
+LL |     m!(0isize, isize::MIN..isize::MAX | isize::MAX);
+   |        ^^^^^^ pattern `_` not covered
+   |
+   = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
+   = 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
+
+error[E0004]: non-exhaustive patterns: `(_, _)` not covered
+  --> $DIR/pointer-sized-int-deny.rs:35:8
+   |
+LL |     m!((0isize, true), (isize::MIN..5, true)
+   |        ^^^^^^^^^^^^^^ pattern `(_, _)` not covered
+   |
+   = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
+   = note: the matched value is of type `(isize, bool)`
+
+error[E0004]: non-exhaustive patterns: `_` not covered
+  --> $DIR/pointer-sized-int-deny.rs:39:11
+   |
+LL |     match 0isize {
+   |           ^^^^^^ pattern `_` not covered
+   |
+   = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
+   = 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
+
+error[E0004]: non-exhaustive patterns: type `usize` is non-empty
+  --> $DIR/pointer-sized-int-deny.rs:46:11
+   |
+LL |     match 7usize {}
+   |           ^^^^^^
+   |
+   = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
+   = note: the matched value is of type `usize`
+
+error: aborting due to 12 previous errors
+
+For more information about this error, try `rustc --explain E0004`.
diff --git a/src/test/ui/pattern/usefulness/non-exhaustive-pattern-pointer-size-int.rs b/src/test/ui/pattern/usefulness/integer-ranges/precise_pointer_matching-message.rs
similarity index 56%
rename from src/test/ui/pattern/usefulness/non-exhaustive-pattern-pointer-size-int.rs
rename to src/test/ui/pattern/usefulness/integer-ranges/precise_pointer_matching-message.rs
index 0c52876e21f95..a2aa655ca5413 100644
--- a/src/test/ui/pattern/usefulness/non-exhaustive-pattern-pointer-size-int.rs
+++ b/src/test/ui/pattern/usefulness/integer-ranges/precise_pointer_matching-message.rs
@@ -1,23 +1,18 @@
-use std::{usize, isize};
-
+// This tests that the lint message explains the reason for the error.
 fn main() {
     match 0usize {
-        //~^ ERROR non-exhaustive patterns
+        //~^ 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 => {}
+        0..=usize::MAX => {}
     }
 
     match 0isize {
-        //~^ ERROR non-exhaustive patterns
+        //~^ 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 => {}
+        isize::MIN..=isize::MAX => {}
     }
-
-    match 7usize {}
-    //~^ ERROR non-exhaustive patterns
-    //~| NOTE the matched value is of type `usize`
 }
diff --git a/src/test/ui/pattern/usefulness/non-exhaustive-pattern-pointer-size-int.stderr b/src/test/ui/pattern/usefulness/integer-ranges/precise_pointer_matching-message.stderr
similarity index 68%
rename from src/test/ui/pattern/usefulness/non-exhaustive-pattern-pointer-size-int.stderr
rename to src/test/ui/pattern/usefulness/integer-ranges/precise_pointer_matching-message.stderr
index d0aa452fd3861..37e73a68f22bb 100644
--- a/src/test/ui/pattern/usefulness/non-exhaustive-pattern-pointer-size-int.stderr
+++ b/src/test/ui/pattern/usefulness/integer-ranges/precise_pointer_matching-message.stderr
@@ -1,5 +1,5 @@
 error[E0004]: non-exhaustive patterns: `_` not covered
-  --> $DIR/non-exhaustive-pattern-pointer-size-int.rs:4:11
+  --> $DIR/precise_pointer_matching-message.rs:3:11
    |
 LL |     match 0usize {
    |           ^^^^^^ pattern `_` not covered
@@ -10,7 +10,7 @@ LL |     match 0usize {
    = help: add `#![feature(precise_pointer_size_matching)]` to the crate attributes to enable precise `usize` matching
 
 error[E0004]: non-exhaustive patterns: `_` not covered
-  --> $DIR/non-exhaustive-pattern-pointer-size-int.rs:12:11
+  --> $DIR/precise_pointer_matching-message.rs:11:11
    |
 LL |     match 0isize {
    |           ^^^^^^ pattern `_` not covered
@@ -20,15 +20,6 @@ LL |     match 0isize {
    = 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
 
-error[E0004]: non-exhaustive patterns: type `usize` is non-empty
-  --> $DIR/non-exhaustive-pattern-pointer-size-int.rs:20:11
-   |
-LL |     match 7usize {}
-   |           ^^^^^^
-   |
-   = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
-   = note: the matched value is of type `usize`
-
-error: aborting due to 3 previous errors
+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/integer-ranges/reachability.rs b/src/test/ui/pattern/usefulness/integer-ranges/reachability.rs
new file mode 100644
index 0000000000000..9078e65f66781
--- /dev/null
+++ b/src/test/ui/pattern/usefulness/integer-ranges/reachability.rs
@@ -0,0 +1,112 @@
+#![feature(exclusive_range_pattern)]
+#![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 => {}, // FIXME: should be unreachable
+        _ => {},
+    }
+    // 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/src/test/ui/pattern/usefulness/integer-ranges/reachability.stderr b/src/test/ui/pattern/usefulness/integer-ranges/reachability.stderr
new file mode 100644
index 0000000000000..8baf0d50c889b
--- /dev/null
+++ b/src/test/ui/pattern/usefulness/integer-ranges/reachability.stderr
@@ -0,0 +1,146 @@
+error: unreachable pattern
+  --> $DIR/reachability.rs:16:17
+   |
+LL |     m!(0u8, 42, 42);
+   |                 ^^
+   |
+note: the lint level is defined here
+  --> $DIR/reachability.rs:2:9
+   |
+LL | #![deny(unreachable_patterns)]
+   |         ^^^^^^^^^^^^^^^^^^^^
+
+error: unreachable pattern
+  --> $DIR/reachability.rs:20:22
+   |
+LL |     m!(0u8, 20..=30, 20);
+   |                      ^^
+
+error: unreachable pattern
+  --> $DIR/reachability.rs:21:22
+   |
+LL |     m!(0u8, 20..=30, 21);
+   |                      ^^
+
+error: unreachable pattern
+  --> $DIR/reachability.rs:22:22
+   |
+LL |     m!(0u8, 20..=30, 25);
+   |                      ^^
+
+error: unreachable pattern
+  --> $DIR/reachability.rs:23:22
+   |
+LL |     m!(0u8, 20..=30, 29);
+   |                      ^^
+
+error: unreachable pattern
+  --> $DIR/reachability.rs:24:22
+   |
+LL |     m!(0u8, 20..=30, 30);
+   |                      ^^
+
+error: unreachable pattern
+  --> $DIR/reachability.rs:27:21
+   |
+LL |     m!(0u8, 20..30, 20);
+   |                     ^^
+
+error: unreachable pattern
+  --> $DIR/reachability.rs:28:21
+   |
+LL |     m!(0u8, 20..30, 21);
+   |                     ^^
+
+error: unreachable pattern
+  --> $DIR/reachability.rs:29:21
+   |
+LL |     m!(0u8, 20..30, 25);
+   |                     ^^
+
+error: unreachable pattern
+  --> $DIR/reachability.rs:30:21
+   |
+LL |     m!(0u8, 20..30, 29);
+   |                     ^^
+
+error: unreachable pattern
+  --> $DIR/reachability.rs:34:22
+   |
+LL |     m!(0u8, 20..=30, 20..=30);
+   |                      ^^^^^^^
+
+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:38:22
+   |
+LL |     m!(0u8, 20..=30, 21..=30);
+   |                      ^^^^^^^
+
+error: unreachable pattern
+  --> $DIR/reachability.rs:39:22
+   |
+LL |     m!(0u8, 20..=30, 20..=29);
+   |                      ^^^^^^^
+
+error: unreachable pattern
+  --> $DIR/reachability.rs:41:24
+   |
+LL |     m!('a', 'A'..='z', 'a'..='z');
+   |                        ^^^^^^^^^
+
+error: unreachable pattern
+  --> $DIR/reachability.rs:48:9
+   |
+LL |         5..=8 => {},
+   |         ^^^^^
+
+error: unreachable pattern
+  --> $DIR/reachability.rs:54:9
+   |
+LL |         5..15 => {},
+   |         ^^^^^
+
+error: unreachable pattern
+  --> $DIR/reachability.rs:61:9
+   |
+LL |         5..25 => {},
+   |         ^^^^^
+
+error: unreachable pattern
+  --> $DIR/reachability.rs:69:9
+   |
+LL |         5..25 => {},
+   |         ^^^^^
+
+error: unreachable pattern
+  --> $DIR/reachability.rs:82:9
+   |
+LL |         '\u{D7FF}'..='\u{E000}' => {},
+   |         ^^^^^^^^^^^^^^^^^^^^^^^
+
+error: unreachable pattern
+  --> $DIR/reachability.rs:103:9
+   |
+LL |         &FOO => {}
+   |         ^^^^
+
+error: unreachable pattern
+  --> $DIR/reachability.rs:104:9
+   |
+LL |         BAR => {}
+   |         ^^^
+
+error: aborting due to 23 previous errors
+
diff --git a/src/test/ui/pattern/irrefutable-let-patterns.rs b/src/test/ui/pattern/usefulness/irrefutable-let-patterns.rs
similarity index 100%
rename from src/test/ui/pattern/irrefutable-let-patterns.rs
rename to src/test/ui/pattern/usefulness/irrefutable-let-patterns.rs
diff --git a/src/test/ui/issues/issue-12116.rs b/src/test/ui/pattern/usefulness/issue-12116.rs
similarity index 100%
rename from src/test/ui/issues/issue-12116.rs
rename to src/test/ui/pattern/usefulness/issue-12116.rs
diff --git a/src/test/ui/issues/issue-12116.stderr b/src/test/ui/pattern/usefulness/issue-12116.stderr
similarity index 100%
rename from src/test/ui/issues/issue-12116.stderr
rename to src/test/ui/pattern/usefulness/issue-12116.stderr
diff --git a/src/test/ui/issues/issue-12369.rs b/src/test/ui/pattern/usefulness/issue-12369.rs
similarity index 100%
rename from src/test/ui/issues/issue-12369.rs
rename to src/test/ui/pattern/usefulness/issue-12369.rs
diff --git a/src/test/ui/issues/issue-12369.stderr b/src/test/ui/pattern/usefulness/issue-12369.stderr
similarity index 100%
rename from src/test/ui/issues/issue-12369.stderr
rename to src/test/ui/pattern/usefulness/issue-12369.stderr
diff --git a/src/test/ui/issues/issue-13727.rs b/src/test/ui/pattern/usefulness/issue-13727.rs
similarity index 100%
rename from src/test/ui/issues/issue-13727.rs
rename to src/test/ui/pattern/usefulness/issue-13727.rs
diff --git a/src/test/ui/issues/issue-13727.stderr b/src/test/ui/pattern/usefulness/issue-13727.stderr
similarity index 100%
rename from src/test/ui/issues/issue-13727.stderr
rename to src/test/ui/pattern/usefulness/issue-13727.stderr
diff --git a/src/test/ui/issues/issue-15129.rs b/src/test/ui/pattern/usefulness/issue-15129.rs
similarity index 100%
rename from src/test/ui/issues/issue-15129.rs
rename to src/test/ui/pattern/usefulness/issue-15129.rs
diff --git a/src/test/ui/issues/issue-15129.stderr b/src/test/ui/pattern/usefulness/issue-15129.stderr
similarity index 100%
rename from src/test/ui/issues/issue-15129.stderr
rename to src/test/ui/pattern/usefulness/issue-15129.stderr
diff --git a/src/test/ui/issues/issue-2111.rs b/src/test/ui/pattern/usefulness/issue-2111.rs
similarity index 100%
rename from src/test/ui/issues/issue-2111.rs
rename to src/test/ui/pattern/usefulness/issue-2111.rs
diff --git a/src/test/ui/issues/issue-2111.stderr b/src/test/ui/pattern/usefulness/issue-2111.stderr
similarity index 100%
rename from src/test/ui/issues/issue-2111.stderr
rename to src/test/ui/pattern/usefulness/issue-2111.stderr
diff --git a/src/test/ui/issues/issue-30240-b.rs b/src/test/ui/pattern/usefulness/issue-30240-b.rs
similarity index 100%
rename from src/test/ui/issues/issue-30240-b.rs
rename to src/test/ui/pattern/usefulness/issue-30240-b.rs
diff --git a/src/test/ui/issues/issue-30240-b.stderr b/src/test/ui/pattern/usefulness/issue-30240-b.stderr
similarity index 100%
rename from src/test/ui/issues/issue-30240-b.stderr
rename to src/test/ui/pattern/usefulness/issue-30240-b.stderr
diff --git a/src/test/ui/issues/issue-30240-rpass.rs b/src/test/ui/pattern/usefulness/issue-30240-rpass.rs
similarity index 100%
rename from src/test/ui/issues/issue-30240-rpass.rs
rename to src/test/ui/pattern/usefulness/issue-30240-rpass.rs
diff --git a/src/test/ui/issues/issue-30240.rs b/src/test/ui/pattern/usefulness/issue-30240.rs
similarity index 100%
rename from src/test/ui/issues/issue-30240.rs
rename to src/test/ui/pattern/usefulness/issue-30240.rs
diff --git a/src/test/ui/issues/issue-30240.stderr b/src/test/ui/pattern/usefulness/issue-30240.stderr
similarity index 100%
rename from src/test/ui/issues/issue-30240.stderr
rename to src/test/ui/pattern/usefulness/issue-30240.stderr
diff --git a/src/test/ui/issues/issue-3096-1.rs b/src/test/ui/pattern/usefulness/issue-3096-1.rs
similarity index 100%
rename from src/test/ui/issues/issue-3096-1.rs
rename to src/test/ui/pattern/usefulness/issue-3096-1.rs
diff --git a/src/test/ui/issues/issue-3096-1.stderr b/src/test/ui/pattern/usefulness/issue-3096-1.stderr
similarity index 100%
rename from src/test/ui/issues/issue-3096-1.stderr
rename to src/test/ui/pattern/usefulness/issue-3096-1.stderr
diff --git a/src/test/ui/issues/issue-3096-2.rs b/src/test/ui/pattern/usefulness/issue-3096-2.rs
similarity index 100%
rename from src/test/ui/issues/issue-3096-2.rs
rename to src/test/ui/pattern/usefulness/issue-3096-2.rs
diff --git a/src/test/ui/issues/issue-3096-2.stderr b/src/test/ui/pattern/usefulness/issue-3096-2.stderr
similarity index 100%
rename from src/test/ui/issues/issue-3096-2.stderr
rename to src/test/ui/pattern/usefulness/issue-3096-2.stderr
diff --git a/src/test/ui/issues/issue-31221.rs b/src/test/ui/pattern/usefulness/issue-31221.rs
similarity index 100%
rename from src/test/ui/issues/issue-31221.rs
rename to src/test/ui/pattern/usefulness/issue-31221.rs
diff --git a/src/test/ui/issues/issue-31221.stderr b/src/test/ui/pattern/usefulness/issue-31221.stderr
similarity index 100%
rename from src/test/ui/issues/issue-31221.stderr
rename to src/test/ui/pattern/usefulness/issue-31221.stderr
diff --git a/src/test/ui/issues/issue-31561.rs b/src/test/ui/pattern/usefulness/issue-31561.rs
similarity index 100%
rename from src/test/ui/issues/issue-31561.rs
rename to src/test/ui/pattern/usefulness/issue-31561.rs
diff --git a/src/test/ui/issues/issue-31561.stderr b/src/test/ui/pattern/usefulness/issue-31561.stderr
similarity index 100%
rename from src/test/ui/issues/issue-31561.stderr
rename to src/test/ui/pattern/usefulness/issue-31561.stderr
diff --git a/src/test/ui/issues/issue-3601.rs b/src/test/ui/pattern/usefulness/issue-3601.rs
similarity index 100%
rename from src/test/ui/issues/issue-3601.rs
rename to src/test/ui/pattern/usefulness/issue-3601.rs
diff --git a/src/test/ui/issues/issue-3601.stderr b/src/test/ui/pattern/usefulness/issue-3601.stderr
similarity index 100%
rename from src/test/ui/issues/issue-3601.stderr
rename to src/test/ui/pattern/usefulness/issue-3601.stderr
diff --git a/src/test/ui/issues/issue-39362.rs b/src/test/ui/pattern/usefulness/issue-39362.rs
similarity index 100%
rename from src/test/ui/issues/issue-39362.rs
rename to src/test/ui/pattern/usefulness/issue-39362.rs
diff --git a/src/test/ui/issues/issue-39362.stderr b/src/test/ui/pattern/usefulness/issue-39362.stderr
similarity index 100%
rename from src/test/ui/issues/issue-39362.stderr
rename to src/test/ui/pattern/usefulness/issue-39362.stderr
diff --git a/src/test/ui/missing/missing-items/issue-40221.rs b/src/test/ui/pattern/usefulness/issue-40221.rs
similarity index 100%
rename from src/test/ui/missing/missing-items/issue-40221.rs
rename to src/test/ui/pattern/usefulness/issue-40221.rs
diff --git a/src/test/ui/missing/missing-items/issue-40221.stderr b/src/test/ui/pattern/usefulness/issue-40221.stderr
similarity index 100%
rename from src/test/ui/missing/missing-items/issue-40221.stderr
rename to src/test/ui/pattern/usefulness/issue-40221.stderr
diff --git a/src/test/ui/issues/issue-4321.rs b/src/test/ui/pattern/usefulness/issue-4321.rs
similarity index 100%
rename from src/test/ui/issues/issue-4321.rs
rename to src/test/ui/pattern/usefulness/issue-4321.rs
diff --git a/src/test/ui/issues/issue-4321.stderr b/src/test/ui/pattern/usefulness/issue-4321.stderr
similarity index 100%
rename from src/test/ui/issues/issue-4321.stderr
rename to src/test/ui/pattern/usefulness/issue-4321.stderr
diff --git a/src/test/ui/pattern/usefulness/issue-43253.rs b/src/test/ui/pattern/usefulness/issue-43253.rs
deleted file mode 100644
index 349ba11a7cdff..0000000000000
--- a/src/test/ui/pattern/usefulness/issue-43253.rs
+++ /dev/null
@@ -1,47 +0,0 @@
-// 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 unreachable pattern
-        _ => {},
-    }
-
-    match 10 {
-        5..7 => {},
-        6 => {}, //~ WARNING unreachable pattern
-        1..10 => {},
-        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
deleted file mode 100644
index 04feef1706cf4..0000000000000
--- a/src/test/ui/pattern/usefulness/issue-43253.stderr
+++ /dev/null
@@ -1,52 +0,0 @@
-warning: multiple patterns covering the same range
-  --> $DIR/issue-43253.rs:16:9
-   |
-LL |         1..10 => {},
-   |         ----- this range overlaps on `9_i32`
-LL |         9..=10 => {},
-   |         ^^^^^^ overlapping patterns
-   |
-note: the lint level is defined here
-  --> $DIR/issue-43253.rs:4:9
-   |
-LL | #![warn(overlapping_patterns)]
-   |         ^^^^^^^^^^^^^^^^^^^^
-
-warning: unreachable pattern
-  --> $DIR/issue-43253.rs:29:9
-   |
-LL |         9 => {},
-   |         ^
-   |
-note: the lint level is 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 => {},
-   |         ^
-
-warning: 6 warnings emitted
-
diff --git a/src/test/ui/match/issue-50900.rs b/src/test/ui/pattern/usefulness/issue-50900.rs
similarity index 100%
rename from src/test/ui/match/issue-50900.rs
rename to src/test/ui/pattern/usefulness/issue-50900.rs
diff --git a/src/test/ui/match/issue-50900.stderr b/src/test/ui/pattern/usefulness/issue-50900.stderr
similarity index 100%
rename from src/test/ui/match/issue-50900.stderr
rename to src/test/ui/pattern/usefulness/issue-50900.stderr
diff --git a/src/test/ui/issues/issue-57472.rs b/src/test/ui/pattern/usefulness/issue-57472.rs
similarity index 100%
rename from src/test/ui/issues/issue-57472.rs
rename to src/test/ui/pattern/usefulness/issue-57472.rs
diff --git a/src/test/ui/issues/issue-57472.stderr b/src/test/ui/pattern/usefulness/issue-57472.stderr
similarity index 100%
rename from src/test/ui/issues/issue-57472.stderr
rename to src/test/ui/pattern/usefulness/issue-57472.stderr
diff --git a/src/test/ui/pattern/issue-66501.rs b/src/test/ui/pattern/usefulness/issue-66501.rs
similarity index 100%
rename from src/test/ui/pattern/issue-66501.rs
rename to src/test/ui/pattern/usefulness/issue-66501.rs
diff --git a/src/test/ui/pattern/usefulness/match-range-fail-dominate.rs b/src/test/ui/pattern/usefulness/match-range-fail-dominate.rs
deleted file mode 100644
index 37c4ccda0f5e3..0000000000000
--- a/src/test/ui/pattern/usefulness/match-range-fail-dominate.rs
+++ /dev/null
@@ -1,49 +0,0 @@
-#![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 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
-      //~| WARNING this was previously accepted by the compiler
-      0.02f64 => {} //~ ERROR unreachable pattern
-      //~^ 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
-      _ => {}
-    };
-}
diff --git a/src/test/ui/pattern/usefulness/match-range-fail-dominate.stderr b/src/test/ui/pattern/usefulness/match-range-fail-dominate.stderr
deleted file mode 100644
index 6922170fccbc8..0000000000000
--- a/src/test/ui/pattern/usefulness/match-range-fail-dominate.stderr
+++ /dev/null
@@ -1,93 +0,0 @@
-error: unreachable pattern
-  --> $DIR/match-range-fail-dominate.rs:6:7
-   |
-LL |       5 ..= 6 => { }
-   |       ^^^^^^^
-   |
-note: the lint level is 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:42: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:42: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>
-
-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:42: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: aborting due to 5 previous errors; 6 warnings emitted
-
diff --git a/src/test/ui/match/type_polymorphic_byte_str_literals.rs b/src/test/ui/pattern/usefulness/type_polymorphic_byte_str_literals.rs
similarity index 100%
rename from src/test/ui/match/type_polymorphic_byte_str_literals.rs
rename to src/test/ui/pattern/usefulness/type_polymorphic_byte_str_literals.rs
diff --git a/src/test/ui/match/type_polymorphic_byte_str_literals.stderr b/src/test/ui/pattern/usefulness/type_polymorphic_byte_str_literals.stderr
similarity index 100%
rename from src/test/ui/match/type_polymorphic_byte_str_literals.stderr
rename to src/test/ui/pattern/usefulness/type_polymorphic_byte_str_literals.stderr
diff --git a/src/test/ui/precise_pointer_size_matching.rs b/src/test/ui/precise_pointer_size_matching.rs
deleted file mode 100644
index 54aeb8616d959..0000000000000
--- a/src/test/ui/precise_pointer_size_matching.rs
+++ /dev/null
@@ -1,33 +0,0 @@
-// normalize-stderr-32bit: "-2147483648isize" -> "$$ISIZE_MIN"
-// normalize-stderr-64bit: "-9223372036854775808isize" -> "$$ISIZE_MIN"
-// normalize-stderr-32bit: "2147483647isize" -> "$$ISIZE_MAX"
-// normalize-stderr-64bit: "9223372036854775807isize" -> "$$ISIZE_MAX"
-// normalize-stderr-32bit: "4294967295usize" -> "$$USIZE_MAX"
-// normalize-stderr-64bit: "18446744073709551615usize" -> "$$USIZE_MAX"
-
-#![feature(precise_pointer_size_matching)]
-#![feature(exclusive_range_pattern)]
-
-#![deny(unreachable_patterns, overlapping_patterns)]
-
-use std::{usize, isize};
-
-fn main() {
-    match 0isize {
-        isize::MIN ..= isize::MAX => {} // ok
-    }
-
-    match 0usize {
-        0 ..= usize::MAX => {} // ok
-    }
-
-    match 0isize { //~ ERROR non-exhaustive patterns
-        1 ..= 8 => {}
-        -5 ..= 20 => {}
-    }
-
-    match 0usize { //~ ERROR non-exhaustive patterns
-        1 ..= 8 => {}
-        5 ..= 20 => {}
-    }
-}
diff --git a/src/test/ui/precise_pointer_size_matching.stderr b/src/test/ui/precise_pointer_size_matching.stderr
deleted file mode 100644
index 9a34171a391c4..0000000000000
--- a/src/test/ui/precise_pointer_size_matching.stderr
+++ /dev/null
@@ -1,21 +0,0 @@
-error[E0004]: non-exhaustive patterns: `isize::MIN..=-6_isize` and `21_isize..=isize::MAX` not covered
-  --> $DIR/precise_pointer_size_matching.rs:24:11
-   |
-LL |     match 0isize {
-   |           ^^^^^^ patterns `isize::MIN..=-6_isize` and `21_isize..=isize::MAX` not covered
-   |
-   = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
-   = note: the matched value is of type `isize`
-
-error[E0004]: non-exhaustive patterns: `0_usize` and `21_usize..=usize::MAX` not covered
-  --> $DIR/precise_pointer_size_matching.rs:29:11
-   |
-LL |     match 0usize {
-   |           ^^^^^^ patterns `0_usize` and `21_usize..=usize::MAX` not covered
-   |
-   = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
-   = note: the matched value is of type `usize`
-
-error: aborting due to 2 previous errors
-
-For more information about this error, try `rustc --explain E0004`.