about summary refs log tree commit diff
diff options
context:
space:
mode:
authorNadrieril <nadrieril+git@gmail.com>2020-12-02 23:11:29 +0000
committerNadrieril <nadrieril+git@gmail.com>2021-01-12 19:59:10 +0000
commitb82f149d08a0afcc17afa54f5bb3c7031babd44a (patch)
treea04c389861c92ea57891fbc137a7f0466bd03114
parent622bfdb2fdfc3da9ca2959b5e9ae686b1c9ed249 (diff)
downloadrust-b82f149d08a0afcc17afa54f5bb3c7031babd44a.tar.gz
rust-b82f149d08a0afcc17afa54f5bb3c7031babd44a.zip
Add tests for uninhabited types
-rw-r--r--src/test/ui/pattern/usefulness/auxiliary/empty.rs8
-rw-r--r--src/test/ui/pattern/usefulness/empty-match.exhaustive_patterns.stderr160
-rw-r--r--src/test/ui/pattern/usefulness/empty-match.normal.stderr152
-rw-r--r--src/test/ui/pattern/usefulness/empty-match.rs100
-rw-r--r--src/test/ui/pattern/usefulness/uninhabited.rs143
5 files changed, 351 insertions, 212 deletions
diff --git a/src/test/ui/pattern/usefulness/auxiliary/empty.rs b/src/test/ui/pattern/usefulness/auxiliary/empty.rs
index 0b0719f48ee..29a03c9e8b5 100644
--- a/src/test/ui/pattern/usefulness/auxiliary/empty.rs
+++ b/src/test/ui/pattern/usefulness/auxiliary/empty.rs
@@ -1,2 +1,10 @@
 #![crate_type = "rlib"]
 pub enum EmptyForeignEnum {}
+
+pub struct VisiblyUninhabitedForeignStruct {
+    pub field: EmptyForeignEnum,
+}
+
+pub struct SecretlyUninhabitedForeignStruct {
+    _priv: EmptyForeignEnum,
+}
diff --git a/src/test/ui/pattern/usefulness/empty-match.exhaustive_patterns.stderr b/src/test/ui/pattern/usefulness/empty-match.exhaustive_patterns.stderr
index a5c8af1f814..b99386e7402 100644
--- a/src/test/ui/pattern/usefulness/empty-match.exhaustive_patterns.stderr
+++ b/src/test/ui/pattern/usefulness/empty-match.exhaustive_patterns.stderr
@@ -1,94 +1,94 @@
 error: unreachable pattern
-  --> $DIR/empty-match.rs:53:9
+  --> $DIR/empty-match.rs:37:9
    |
 LL |         _ => {},
    |         ^
    |
 note: the lint level is defined here
-  --> $DIR/empty-match.rs:6:9
+  --> $DIR/empty-match.rs:8:9
    |
 LL | #![deny(unreachable_patterns)]
    |         ^^^^^^^^^^^^^^^^^^^^
 
 error: unreachable pattern
-  --> $DIR/empty-match.rs:56:9
+  --> $DIR/empty-match.rs:40:9
    |
 LL |         _ if false => {},
    |         ^
 
 error: unreachable pattern
-  --> $DIR/empty-match.rs:63:9
+  --> $DIR/empty-match.rs:47:9
    |
 LL |         _ => {},
    |         ^
 
 error: unreachable pattern
-  --> $DIR/empty-match.rs:66:9
+  --> $DIR/empty-match.rs:50:9
    |
 LL |         _ if false => {},
    |         ^
 
 error: unreachable pattern
-  --> $DIR/empty-match.rs:73:9
+  --> $DIR/empty-match.rs:57:9
    |
 LL |         _ => {},
    |         ^
 
 error: unreachable pattern
-  --> $DIR/empty-match.rs:76:9
+  --> $DIR/empty-match.rs:60:9
    |
 LL |         _ if false => {},
    |         ^
 
-error: unreachable pattern
-  --> $DIR/empty-match.rs:83:9
+error[E0004]: non-exhaustive patterns: type `u8` is non-empty
+  --> $DIR/empty-match.rs:78:20
    |
-LL |         Some(_) => {}
-   |         ^^^^^^^
-
-error: unreachable pattern
-  --> $DIR/empty-match.rs:87:9
+LL |     match_no_arms!(0u8);
+   |                    ^^^
    |
-LL |         Some(_) => {}
-   |         ^^^^^^^
+   = 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: type `u8` is non-empty
-  --> $DIR/empty-match.rs:90:18
+error[E0004]: non-exhaustive patterns: type `NonEmptyStruct1` is non-empty
+  --> $DIR/empty-match.rs:79:20
    |
-LL |     match_empty!(0u8);
-   |                  ^^^
+LL | struct NonEmptyStruct1;
+   | ----------------------- `NonEmptyStruct1` defined here
+...
+LL |     match_no_arms!(NonEmptyStruct1);
+   |                    ^^^^^^^^^^^^^^^
    |
    = 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`
+   = note: the matched value is of type `NonEmptyStruct1`
 
-error[E0004]: non-exhaustive patterns: type `NonEmptyStruct` is non-empty
-  --> $DIR/empty-match.rs:92:18
+error[E0004]: non-exhaustive patterns: type `NonEmptyStruct2` is non-empty
+  --> $DIR/empty-match.rs:80:20
    |
-LL | struct NonEmptyStruct(bool);
-   | ---------------------------- `NonEmptyStruct` defined here
+LL | struct NonEmptyStruct2(bool);
+   | ----------------------------- `NonEmptyStruct2` defined here
 ...
-LL |     match_empty!(NonEmptyStruct(true));
-   |                  ^^^^^^^^^^^^^^^^^^^^
+LL |     match_no_arms!(NonEmptyStruct2(true));
+   |                    ^^^^^^^^^^^^^^^^^^^^^
    |
    = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
-   = note: the matched value is of type `NonEmptyStruct`
+   = note: the matched value is of type `NonEmptyStruct2`
 
 error[E0004]: non-exhaustive patterns: type `NonEmptyUnion1` is non-empty
-  --> $DIR/empty-match.rs:94:18
+  --> $DIR/empty-match.rs:81:20
    |
 LL | / union NonEmptyUnion1 {
 LL | |     foo: (),
 LL | | }
    | |_- `NonEmptyUnion1` defined here
 ...
-LL |       match_empty!((NonEmptyUnion1 { foo: () }));
-   |                    ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+LL |       match_no_arms!((NonEmptyUnion1 { foo: () }));
+   |                      ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    |
    = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
    = note: the matched value is of type `NonEmptyUnion1`
 
 error[E0004]: non-exhaustive patterns: type `NonEmptyUnion2` is non-empty
-  --> $DIR/empty-match.rs:96:18
+  --> $DIR/empty-match.rs:82:20
    |
 LL | / union NonEmptyUnion2 {
 LL | |     foo: (),
@@ -96,101 +96,107 @@ LL | |     bar: (),
 LL | | }
    | |_- `NonEmptyUnion2` defined here
 ...
-LL |       match_empty!((NonEmptyUnion2 { foo: () }));
-   |                    ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+LL |       match_no_arms!((NonEmptyUnion2 { foo: () }));
+   |                      ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    |
    = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
    = note: the matched value is of type `NonEmptyUnion2`
 
 error[E0004]: non-exhaustive patterns: `Foo(_)` not covered
-  --> $DIR/empty-match.rs:98:18
+  --> $DIR/empty-match.rs:83:20
    |
 LL | / enum NonEmptyEnum1 {
 LL | |     Foo(bool),
    | |     --- not covered
-LL | |
-LL | |
 LL | | }
    | |_- `NonEmptyEnum1` defined here
 ...
-LL |       match_empty!(NonEmptyEnum1::Foo(true));
-   |                    ^^^^^^^^^^^^^^^^^^^^^^^^ pattern `Foo(_)` not covered
+LL |       match_no_arms!(NonEmptyEnum1::Foo(true));
+   |                      ^^^^^^^^^^^^^^^^^^^^^^^^ pattern `Foo(_)` 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 `NonEmptyEnum1`
 
 error[E0004]: non-exhaustive patterns: `Foo(_)` and `Bar` not covered
-  --> $DIR/empty-match.rs:100:18
+  --> $DIR/empty-match.rs:84:20
    |
 LL | / enum NonEmptyEnum2 {
 LL | |     Foo(bool),
    | |     --- not covered
-LL | |
-LL | |
 LL | |     Bar,
    | |     --- not covered
-LL | |
-LL | |
 LL | | }
    | |_- `NonEmptyEnum2` defined here
 ...
-LL |       match_empty!(NonEmptyEnum2::Foo(true));
-   |                    ^^^^^^^^^^^^^^^^^^^^^^^^ patterns `Foo(_)` and `Bar` not covered
+LL |       match_no_arms!(NonEmptyEnum2::Foo(true));
+   |                      ^^^^^^^^^^^^^^^^^^^^^^^^ patterns `Foo(_)` and `Bar` 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 `NonEmptyEnum2`
 
 error[E0004]: non-exhaustive patterns: `V1`, `V2`, `V3` and 2 more not covered
-  --> $DIR/empty-match.rs:102:18
+  --> $DIR/empty-match.rs:85:20
    |
 LL | / enum NonEmptyEnum5 {
 LL | |     V1, V2, V3, V4, V5,
 LL | | }
    | |_- `NonEmptyEnum5` defined here
 ...
-LL |       match_empty!(NonEmptyEnum5::V1);
-   |                    ^^^^^^^^^^^^^^^^^ patterns `V1`, `V2`, `V3` and 2 more not covered
+LL |       match_no_arms!(NonEmptyEnum5::V1);
+   |                      ^^^^^^^^^^^^^^^^^ patterns `V1`, `V2`, `V3` and 2 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 `NonEmptyEnum5`
 
 error[E0004]: non-exhaustive patterns: `_` not covered
-  --> $DIR/empty-match.rs:105:18
+  --> $DIR/empty-match.rs:87:24
    |
-LL |     match_false!(0u8);
-   |                  ^^^ pattern `_` not covered
+LL |     match_guarded_arm!(0u8);
+   |                        ^^^ 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 `u8`
 
-error[E0004]: non-exhaustive patterns: `NonEmptyStruct(_)` not covered
-  --> $DIR/empty-match.rs:107:18
+error[E0004]: non-exhaustive patterns: `NonEmptyStruct1` not covered
+  --> $DIR/empty-match.rs:88:24
+   |
+LL | struct NonEmptyStruct1;
+   | ----------------------- `NonEmptyStruct1` defined here
+...
+LL |     match_guarded_arm!(NonEmptyStruct1);
+   |                        ^^^^^^^^^^^^^^^ pattern `NonEmptyStruct1` 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 `NonEmptyStruct1`
+
+error[E0004]: non-exhaustive patterns: `NonEmptyStruct2(_)` not covered
+  --> $DIR/empty-match.rs:89:24
    |
-LL | struct NonEmptyStruct(bool);
-   | ---------------------------- `NonEmptyStruct` defined here
+LL | struct NonEmptyStruct2(bool);
+   | ----------------------------- `NonEmptyStruct2` defined here
 ...
-LL |     match_false!(NonEmptyStruct(true));
-   |                  ^^^^^^^^^^^^^^^^^^^^ pattern `NonEmptyStruct(_)` not covered
+LL |     match_guarded_arm!(NonEmptyStruct2(true));
+   |                        ^^^^^^^^^^^^^^^^^^^^^ pattern `NonEmptyStruct2(_)` 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 `NonEmptyStruct`
+   = note: the matched value is of type `NonEmptyStruct2`
 
 error[E0004]: non-exhaustive patterns: `NonEmptyUnion1 { .. }` not covered
-  --> $DIR/empty-match.rs:109:18
+  --> $DIR/empty-match.rs:90:24
    |
 LL | / union NonEmptyUnion1 {
 LL | |     foo: (),
 LL | | }
    | |_- `NonEmptyUnion1` defined here
 ...
-LL |       match_false!((NonEmptyUnion1 { foo: () }));
-   |                    ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ pattern `NonEmptyUnion1 { .. }` not covered
+LL |       match_guarded_arm!((NonEmptyUnion1 { foo: () }));
+   |                          ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ pattern `NonEmptyUnion1 { .. }` 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 `NonEmptyUnion1`
 
 error[E0004]: non-exhaustive patterns: `NonEmptyUnion2 { .. }` not covered
-  --> $DIR/empty-match.rs:111:18
+  --> $DIR/empty-match.rs:91:24
    |
 LL | / union NonEmptyUnion2 {
 LL | |     foo: (),
@@ -198,60 +204,54 @@ LL | |     bar: (),
 LL | | }
    | |_- `NonEmptyUnion2` defined here
 ...
-LL |       match_false!((NonEmptyUnion2 { foo: () }));
-   |                    ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ pattern `NonEmptyUnion2 { .. }` not covered
+LL |       match_guarded_arm!((NonEmptyUnion2 { foo: () }));
+   |                          ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ pattern `NonEmptyUnion2 { .. }` 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 `NonEmptyUnion2`
 
 error[E0004]: non-exhaustive patterns: `Foo(_)` not covered
-  --> $DIR/empty-match.rs:113:18
+  --> $DIR/empty-match.rs:92:24
    |
 LL | / enum NonEmptyEnum1 {
 LL | |     Foo(bool),
    | |     --- not covered
-LL | |
-LL | |
 LL | | }
    | |_- `NonEmptyEnum1` defined here
 ...
-LL |       match_false!(NonEmptyEnum1::Foo(true));
-   |                    ^^^^^^^^^^^^^^^^^^^^^^^^ pattern `Foo(_)` not covered
+LL |       match_guarded_arm!(NonEmptyEnum1::Foo(true));
+   |                          ^^^^^^^^^^^^^^^^^^^^^^^^ pattern `Foo(_)` 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 `NonEmptyEnum1`
 
 error[E0004]: non-exhaustive patterns: `Foo(_)` and `Bar` not covered
-  --> $DIR/empty-match.rs:115:18
+  --> $DIR/empty-match.rs:93:24
    |
 LL | / enum NonEmptyEnum2 {
 LL | |     Foo(bool),
    | |     --- not covered
-LL | |
-LL | |
 LL | |     Bar,
    | |     --- not covered
-LL | |
-LL | |
 LL | | }
    | |_- `NonEmptyEnum2` defined here
 ...
-LL |       match_false!(NonEmptyEnum2::Foo(true));
-   |                    ^^^^^^^^^^^^^^^^^^^^^^^^ patterns `Foo(_)` and `Bar` not covered
+LL |       match_guarded_arm!(NonEmptyEnum2::Foo(true));
+   |                          ^^^^^^^^^^^^^^^^^^^^^^^^ patterns `Foo(_)` and `Bar` 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 `NonEmptyEnum2`
 
 error[E0004]: non-exhaustive patterns: `V1`, `V2`, `V3` and 2 more not covered
-  --> $DIR/empty-match.rs:117:18
+  --> $DIR/empty-match.rs:94:24
    |
 LL | / enum NonEmptyEnum5 {
 LL | |     V1, V2, V3, V4, V5,
 LL | | }
    | |_- `NonEmptyEnum5` defined here
 ...
-LL |       match_false!(NonEmptyEnum5::V1);
-   |                    ^^^^^^^^^^^^^^^^^ patterns `V1`, `V2`, `V3` and 2 more not covered
+LL |       match_guarded_arm!(NonEmptyEnum5::V1);
+   |                          ^^^^^^^^^^^^^^^^^ patterns `V1`, `V2`, `V3` and 2 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 `NonEmptyEnum5`
diff --git a/src/test/ui/pattern/usefulness/empty-match.normal.stderr b/src/test/ui/pattern/usefulness/empty-match.normal.stderr
index 7db11f146b2..b99386e7402 100644
--- a/src/test/ui/pattern/usefulness/empty-match.normal.stderr
+++ b/src/test/ui/pattern/usefulness/empty-match.normal.stderr
@@ -1,82 +1,94 @@
 error: unreachable pattern
-  --> $DIR/empty-match.rs:53:9
+  --> $DIR/empty-match.rs:37:9
    |
 LL |         _ => {},
    |         ^
    |
 note: the lint level is defined here
-  --> $DIR/empty-match.rs:6:9
+  --> $DIR/empty-match.rs:8:9
    |
 LL | #![deny(unreachable_patterns)]
    |         ^^^^^^^^^^^^^^^^^^^^
 
 error: unreachable pattern
-  --> $DIR/empty-match.rs:56:9
+  --> $DIR/empty-match.rs:40:9
    |
 LL |         _ if false => {},
    |         ^
 
 error: unreachable pattern
-  --> $DIR/empty-match.rs:63:9
+  --> $DIR/empty-match.rs:47:9
    |
 LL |         _ => {},
    |         ^
 
 error: unreachable pattern
-  --> $DIR/empty-match.rs:66:9
+  --> $DIR/empty-match.rs:50:9
    |
 LL |         _ if false => {},
    |         ^
 
 error: unreachable pattern
-  --> $DIR/empty-match.rs:73:9
+  --> $DIR/empty-match.rs:57:9
    |
 LL |         _ => {},
    |         ^
 
 error: unreachable pattern
-  --> $DIR/empty-match.rs:76:9
+  --> $DIR/empty-match.rs:60:9
    |
 LL |         _ if false => {},
    |         ^
 
 error[E0004]: non-exhaustive patterns: type `u8` is non-empty
-  --> $DIR/empty-match.rs:90:18
+  --> $DIR/empty-match.rs:78:20
    |
-LL |     match_empty!(0u8);
-   |                  ^^^
+LL |     match_no_arms!(0u8);
+   |                    ^^^
    |
    = 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: type `NonEmptyStruct` is non-empty
-  --> $DIR/empty-match.rs:92:18
+error[E0004]: non-exhaustive patterns: type `NonEmptyStruct1` is non-empty
+  --> $DIR/empty-match.rs:79:20
    |
-LL | struct NonEmptyStruct(bool);
-   | ---------------------------- `NonEmptyStruct` defined here
+LL | struct NonEmptyStruct1;
+   | ----------------------- `NonEmptyStruct1` defined here
 ...
-LL |     match_empty!(NonEmptyStruct(true));
-   |                  ^^^^^^^^^^^^^^^^^^^^
+LL |     match_no_arms!(NonEmptyStruct1);
+   |                    ^^^^^^^^^^^^^^^
    |
    = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
-   = note: the matched value is of type `NonEmptyStruct`
+   = note: the matched value is of type `NonEmptyStruct1`
+
+error[E0004]: non-exhaustive patterns: type `NonEmptyStruct2` is non-empty
+  --> $DIR/empty-match.rs:80:20
+   |
+LL | struct NonEmptyStruct2(bool);
+   | ----------------------------- `NonEmptyStruct2` defined here
+...
+LL |     match_no_arms!(NonEmptyStruct2(true));
+   |                    ^^^^^^^^^^^^^^^^^^^^^
+   |
+   = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
+   = note: the matched value is of type `NonEmptyStruct2`
 
 error[E0004]: non-exhaustive patterns: type `NonEmptyUnion1` is non-empty
-  --> $DIR/empty-match.rs:94:18
+  --> $DIR/empty-match.rs:81:20
    |
 LL | / union NonEmptyUnion1 {
 LL | |     foo: (),
 LL | | }
    | |_- `NonEmptyUnion1` defined here
 ...
-LL |       match_empty!((NonEmptyUnion1 { foo: () }));
-   |                    ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+LL |       match_no_arms!((NonEmptyUnion1 { foo: () }));
+   |                      ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    |
    = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
    = note: the matched value is of type `NonEmptyUnion1`
 
 error[E0004]: non-exhaustive patterns: type `NonEmptyUnion2` is non-empty
-  --> $DIR/empty-match.rs:96:18
+  --> $DIR/empty-match.rs:82:20
    |
 LL | / union NonEmptyUnion2 {
 LL | |     foo: (),
@@ -84,101 +96,107 @@ LL | |     bar: (),
 LL | | }
    | |_- `NonEmptyUnion2` defined here
 ...
-LL |       match_empty!((NonEmptyUnion2 { foo: () }));
-   |                    ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+LL |       match_no_arms!((NonEmptyUnion2 { foo: () }));
+   |                      ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    |
    = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
    = note: the matched value is of type `NonEmptyUnion2`
 
 error[E0004]: non-exhaustive patterns: `Foo(_)` not covered
-  --> $DIR/empty-match.rs:98:18
+  --> $DIR/empty-match.rs:83:20
    |
 LL | / enum NonEmptyEnum1 {
 LL | |     Foo(bool),
    | |     --- not covered
-LL | |
-LL | |
 LL | | }
    | |_- `NonEmptyEnum1` defined here
 ...
-LL |       match_empty!(NonEmptyEnum1::Foo(true));
-   |                    ^^^^^^^^^^^^^^^^^^^^^^^^ pattern `Foo(_)` not covered
+LL |       match_no_arms!(NonEmptyEnum1::Foo(true));
+   |                      ^^^^^^^^^^^^^^^^^^^^^^^^ pattern `Foo(_)` 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 `NonEmptyEnum1`
 
 error[E0004]: non-exhaustive patterns: `Foo(_)` and `Bar` not covered
-  --> $DIR/empty-match.rs:100:18
+  --> $DIR/empty-match.rs:84:20
    |
 LL | / enum NonEmptyEnum2 {
 LL | |     Foo(bool),
    | |     --- not covered
-LL | |
-LL | |
 LL | |     Bar,
    | |     --- not covered
-LL | |
-LL | |
 LL | | }
    | |_- `NonEmptyEnum2` defined here
 ...
-LL |       match_empty!(NonEmptyEnum2::Foo(true));
-   |                    ^^^^^^^^^^^^^^^^^^^^^^^^ patterns `Foo(_)` and `Bar` not covered
+LL |       match_no_arms!(NonEmptyEnum2::Foo(true));
+   |                      ^^^^^^^^^^^^^^^^^^^^^^^^ patterns `Foo(_)` and `Bar` 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 `NonEmptyEnum2`
 
 error[E0004]: non-exhaustive patterns: `V1`, `V2`, `V3` and 2 more not covered
-  --> $DIR/empty-match.rs:102:18
+  --> $DIR/empty-match.rs:85:20
    |
 LL | / enum NonEmptyEnum5 {
 LL | |     V1, V2, V3, V4, V5,
 LL | | }
    | |_- `NonEmptyEnum5` defined here
 ...
-LL |       match_empty!(NonEmptyEnum5::V1);
-   |                    ^^^^^^^^^^^^^^^^^ patterns `V1`, `V2`, `V3` and 2 more not covered
+LL |       match_no_arms!(NonEmptyEnum5::V1);
+   |                      ^^^^^^^^^^^^^^^^^ patterns `V1`, `V2`, `V3` and 2 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 `NonEmptyEnum5`
 
 error[E0004]: non-exhaustive patterns: `_` not covered
-  --> $DIR/empty-match.rs:105:18
+  --> $DIR/empty-match.rs:87:24
    |
-LL |     match_false!(0u8);
-   |                  ^^^ pattern `_` not covered
+LL |     match_guarded_arm!(0u8);
+   |                        ^^^ 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 `u8`
 
-error[E0004]: non-exhaustive patterns: `NonEmptyStruct(_)` not covered
-  --> $DIR/empty-match.rs:107:18
+error[E0004]: non-exhaustive patterns: `NonEmptyStruct1` not covered
+  --> $DIR/empty-match.rs:88:24
+   |
+LL | struct NonEmptyStruct1;
+   | ----------------------- `NonEmptyStruct1` defined here
+...
+LL |     match_guarded_arm!(NonEmptyStruct1);
+   |                        ^^^^^^^^^^^^^^^ pattern `NonEmptyStruct1` 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 `NonEmptyStruct1`
+
+error[E0004]: non-exhaustive patterns: `NonEmptyStruct2(_)` not covered
+  --> $DIR/empty-match.rs:89:24
    |
-LL | struct NonEmptyStruct(bool);
-   | ---------------------------- `NonEmptyStruct` defined here
+LL | struct NonEmptyStruct2(bool);
+   | ----------------------------- `NonEmptyStruct2` defined here
 ...
-LL |     match_false!(NonEmptyStruct(true));
-   |                  ^^^^^^^^^^^^^^^^^^^^ pattern `NonEmptyStruct(_)` not covered
+LL |     match_guarded_arm!(NonEmptyStruct2(true));
+   |                        ^^^^^^^^^^^^^^^^^^^^^ pattern `NonEmptyStruct2(_)` 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 `NonEmptyStruct`
+   = note: the matched value is of type `NonEmptyStruct2`
 
 error[E0004]: non-exhaustive patterns: `NonEmptyUnion1 { .. }` not covered
-  --> $DIR/empty-match.rs:109:18
+  --> $DIR/empty-match.rs:90:24
    |
 LL | / union NonEmptyUnion1 {
 LL | |     foo: (),
 LL | | }
    | |_- `NonEmptyUnion1` defined here
 ...
-LL |       match_false!((NonEmptyUnion1 { foo: () }));
-   |                    ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ pattern `NonEmptyUnion1 { .. }` not covered
+LL |       match_guarded_arm!((NonEmptyUnion1 { foo: () }));
+   |                          ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ pattern `NonEmptyUnion1 { .. }` 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 `NonEmptyUnion1`
 
 error[E0004]: non-exhaustive patterns: `NonEmptyUnion2 { .. }` not covered
-  --> $DIR/empty-match.rs:111:18
+  --> $DIR/empty-match.rs:91:24
    |
 LL | / union NonEmptyUnion2 {
 LL | |     foo: (),
@@ -186,64 +204,58 @@ LL | |     bar: (),
 LL | | }
    | |_- `NonEmptyUnion2` defined here
 ...
-LL |       match_false!((NonEmptyUnion2 { foo: () }));
-   |                    ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ pattern `NonEmptyUnion2 { .. }` not covered
+LL |       match_guarded_arm!((NonEmptyUnion2 { foo: () }));
+   |                          ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ pattern `NonEmptyUnion2 { .. }` 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 `NonEmptyUnion2`
 
 error[E0004]: non-exhaustive patterns: `Foo(_)` not covered
-  --> $DIR/empty-match.rs:113:18
+  --> $DIR/empty-match.rs:92:24
    |
 LL | / enum NonEmptyEnum1 {
 LL | |     Foo(bool),
    | |     --- not covered
-LL | |
-LL | |
 LL | | }
    | |_- `NonEmptyEnum1` defined here
 ...
-LL |       match_false!(NonEmptyEnum1::Foo(true));
-   |                    ^^^^^^^^^^^^^^^^^^^^^^^^ pattern `Foo(_)` not covered
+LL |       match_guarded_arm!(NonEmptyEnum1::Foo(true));
+   |                          ^^^^^^^^^^^^^^^^^^^^^^^^ pattern `Foo(_)` 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 `NonEmptyEnum1`
 
 error[E0004]: non-exhaustive patterns: `Foo(_)` and `Bar` not covered
-  --> $DIR/empty-match.rs:115:18
+  --> $DIR/empty-match.rs:93:24
    |
 LL | / enum NonEmptyEnum2 {
 LL | |     Foo(bool),
    | |     --- not covered
-LL | |
-LL | |
 LL | |     Bar,
    | |     --- not covered
-LL | |
-LL | |
 LL | | }
    | |_- `NonEmptyEnum2` defined here
 ...
-LL |       match_false!(NonEmptyEnum2::Foo(true));
-   |                    ^^^^^^^^^^^^^^^^^^^^^^^^ patterns `Foo(_)` and `Bar` not covered
+LL |       match_guarded_arm!(NonEmptyEnum2::Foo(true));
+   |                          ^^^^^^^^^^^^^^^^^^^^^^^^ patterns `Foo(_)` and `Bar` 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 `NonEmptyEnum2`
 
 error[E0004]: non-exhaustive patterns: `V1`, `V2`, `V3` and 2 more not covered
-  --> $DIR/empty-match.rs:117:18
+  --> $DIR/empty-match.rs:94:24
    |
 LL | / enum NonEmptyEnum5 {
 LL | |     V1, V2, V3, V4, V5,
 LL | | }
    | |_- `NonEmptyEnum5` defined here
 ...
-LL |       match_false!(NonEmptyEnum5::V1);
-   |                    ^^^^^^^^^^^^^^^^^ patterns `V1`, `V2`, `V3` and 2 more not covered
+LL |       match_guarded_arm!(NonEmptyEnum5::V1);
+   |                          ^^^^^^^^^^^^^^^^^ patterns `V1`, `V2`, `V3` and 2 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 `NonEmptyEnum5`
 
-error: aborting due to 20 previous errors
+error: aborting due to 22 previous errors
 
 For more information about this error, try `rustc --explain E0004`.
diff --git a/src/test/ui/pattern/usefulness/empty-match.rs b/src/test/ui/pattern/usefulness/empty-match.rs
index 98d8ac18002..8110ec013d7 100644
--- a/src/test/ui/pattern/usefulness/empty-match.rs
+++ b/src/test/ui/pattern/usefulness/empty-match.rs
@@ -1,5 +1,7 @@
 // aux-build:empty.rs
 // revisions: normal exhaustive_patterns
+//
+// This tests a match with no arms on various types.
 #![feature(never_type)]
 #![feature(never_type_fallback)]
 #![cfg_attr(exhaustive_patterns, feature(exhaustive_patterns))]
@@ -9,44 +11,26 @@ extern crate empty;
 
 enum EmptyEnum {}
 
-struct NonEmptyStruct(bool); //~ `NonEmptyStruct` defined here
-union NonEmptyUnion1 { //~ `NonEmptyUnion1` defined here
+struct NonEmptyStruct1;
+struct NonEmptyStruct2(bool);
+union NonEmptyUnion1 {
     foo: (),
 }
-union NonEmptyUnion2 { //~ `NonEmptyUnion2` defined here
+union NonEmptyUnion2 {
     foo: (),
     bar: (),
 }
-enum NonEmptyEnum1 { //~ `NonEmptyEnum1` defined here
+enum NonEmptyEnum1 {
     Foo(bool),
-    //~^ not covered
-    //~| not covered
 }
-enum NonEmptyEnum2 { //~ `NonEmptyEnum2` defined here
+enum NonEmptyEnum2 {
     Foo(bool),
-    //~^ not covered
-    //~| not covered
     Bar,
-    //~^ not covered
-    //~| not covered
 }
-enum NonEmptyEnum5 { //~ `NonEmptyEnum5` defined here
+enum NonEmptyEnum5 {
     V1, V2, V3, V4, V5,
 }
 
-macro_rules! match_empty {
-    ($e:expr) => {
-        match $e {}
-    };
-}
-macro_rules! match_false {
-    ($e:expr) => {
-        match $e {
-            _ if false => {}
-        }
-    };
-}
-
 fn empty_enum(x: EmptyEnum) {
     match x {} // ok
     match x {
@@ -77,43 +61,35 @@ fn never(x: !) {
     }
 }
 
-fn main() {
-    match None::<!> {
-        None => {}
-        Some(_) => {} //[exhaustive_patterns]~ ERROR unreachable pattern
-    }
-    match None::<EmptyEnum> {
-        None => {}
-        Some(_) => {} //[exhaustive_patterns]~ ERROR unreachable pattern
-    }
+macro_rules! match_no_arms {
+    ($e:expr) => {
+        match $e {}
+    };
+}
+macro_rules! match_guarded_arm {
+    ($e:expr) => {
+        match $e {
+            _ if false => {}
+        }
+    };
+}
 
-    match_empty!(0u8);
-    //~^ ERROR type `u8` is non-empty
-    match_empty!(NonEmptyStruct(true));
-    //~^ ERROR type `NonEmptyStruct` is non-empty
-    match_empty!((NonEmptyUnion1 { foo: () }));
-    //~^ ERROR type `NonEmptyUnion1` is non-empty
-    match_empty!((NonEmptyUnion2 { foo: () }));
-    //~^ ERROR type `NonEmptyUnion2` is non-empty
-    match_empty!(NonEmptyEnum1::Foo(true));
-    //~^ ERROR `Foo(_)` not covered
-    match_empty!(NonEmptyEnum2::Foo(true));
-    //~^ ERROR `Foo(_)` and `Bar` not covered
-    match_empty!(NonEmptyEnum5::V1);
-    //~^ ERROR `V1`, `V2`, `V3` and 2 more not covered
+fn main() {
+    match_no_arms!(0u8); //~ ERROR type `u8` is non-empty
+    match_no_arms!(NonEmptyStruct1); //~ ERROR type `NonEmptyStruct1` is non-empty
+    match_no_arms!(NonEmptyStruct2(true)); //~ ERROR type `NonEmptyStruct2` is non-empty
+    match_no_arms!((NonEmptyUnion1 { foo: () })); //~ ERROR type `NonEmptyUnion1` is non-empty
+    match_no_arms!((NonEmptyUnion2 { foo: () })); //~ ERROR type `NonEmptyUnion2` is non-empty
+    match_no_arms!(NonEmptyEnum1::Foo(true)); //~ ERROR `Foo(_)` not covered
+    match_no_arms!(NonEmptyEnum2::Foo(true)); //~ ERROR `Foo(_)` and `Bar` not covered
+    match_no_arms!(NonEmptyEnum5::V1); //~ ERROR `V1`, `V2`, `V3` and 2 more not covered
 
-    match_false!(0u8);
-    //~^ ERROR `_` not covered
-    match_false!(NonEmptyStruct(true));
-    //~^ ERROR `NonEmptyStruct(_)` not covered
-    match_false!((NonEmptyUnion1 { foo: () }));
-    //~^ ERROR `NonEmptyUnion1 { .. }` not covered
-    match_false!((NonEmptyUnion2 { foo: () }));
-    //~^ ERROR `NonEmptyUnion2 { .. }` not covered
-    match_false!(NonEmptyEnum1::Foo(true));
-    //~^ ERROR `Foo(_)` not covered
-    match_false!(NonEmptyEnum2::Foo(true));
-    //~^ ERROR `Foo(_)` and `Bar` not covered
-    match_false!(NonEmptyEnum5::V1);
-    //~^ ERROR `V1`, `V2`, `V3` and 2 more not covered
+    match_guarded_arm!(0u8); //~ ERROR `_` not covered
+    match_guarded_arm!(NonEmptyStruct1); //~ ERROR `NonEmptyStruct1` not covered
+    match_guarded_arm!(NonEmptyStruct2(true)); //~ ERROR `NonEmptyStruct2(_)` not covered
+    match_guarded_arm!((NonEmptyUnion1 { foo: () })); //~ ERROR `NonEmptyUnion1 { .. }` not covered
+    match_guarded_arm!((NonEmptyUnion2 { foo: () })); //~ ERROR `NonEmptyUnion2 { .. }` not covered
+    match_guarded_arm!(NonEmptyEnum1::Foo(true)); //~ ERROR `Foo(_)` not covered
+    match_guarded_arm!(NonEmptyEnum2::Foo(true)); //~ ERROR `Foo(_)` and `Bar` not covered
+    match_guarded_arm!(NonEmptyEnum5::V1); //~ ERROR `V1`, `V2`, `V3` and 2 more not covered
 }
diff --git a/src/test/ui/pattern/usefulness/uninhabited.rs b/src/test/ui/pattern/usefulness/uninhabited.rs
new file mode 100644
index 00000000000..77cd0f4005e
--- /dev/null
+++ b/src/test/ui/pattern/usefulness/uninhabited.rs
@@ -0,0 +1,143 @@
+// check-pass
+// aux-build:empty.rs
+//
+// This tests plays with matching and uninhabited types. This also serves as a test for the
+// `tcx.is_ty_uninhabited_from()` function.
+#![feature(never_type)]
+#![feature(never_type_fallback)]
+#![feature(exhaustive_patterns)]
+#![deny(unreachable_patterns)]
+
+macro_rules! assert_empty {
+    ($ty:ty) => {
+        const _: () = {
+            fn assert_empty(x: $ty) {
+                match x {}
+                match Some(x) {
+                    None => {}
+                }
+            }
+        };
+    };
+}
+macro_rules! assert_non_empty {
+    ($ty:ty) => {
+        const _: () = {
+            fn assert_non_empty(x: $ty) {
+                match x {
+                    _ => {}
+                }
+                match Some(x) {
+                    None => {}
+                    Some(_) => {}
+                }
+            }
+        };
+    };
+}
+
+extern crate empty;
+assert_empty!(empty::EmptyForeignEnum);
+assert_empty!(empty::VisiblyUninhabitedForeignStruct);
+assert_non_empty!(empty::SecretlyUninhabitedForeignStruct);
+
+enum Void {}
+assert_empty!(Void);
+
+enum Enum2 {
+    Foo(Void),
+    Bar(!),
+}
+assert_empty!(Enum2);
+
+enum Enum3 {
+    Foo(Void),
+    Bar {
+        x: u64,
+        y: !,
+    },
+}
+assert_empty!(Enum3);
+
+enum Enum4 {
+    Foo(u64),
+    Bar(!),
+}
+assert_non_empty!(Enum4);
+
+struct Struct1(empty::EmptyForeignEnum);
+assert_empty!(Struct1);
+
+struct Struct2 {
+    x: u64,
+    y: !,
+}
+assert_empty!(Struct2);
+
+union Union {
+    foo: !,
+}
+assert_non_empty!(Union);
+
+assert_empty!((!, String));
+
+assert_non_empty!(&'static !);
+assert_non_empty!(&'static Struct1);
+assert_non_empty!(&'static &'static &'static !);
+
+assert_empty!([!; 1]);
+assert_empty!([Void; 2]);
+assert_non_empty!([!; 0]);
+assert_non_empty!(&'static [!]);
+
+mod visibility {
+    /// This struct can only be seen to be inhabited in modules `b`, `c` or `d`, because otherwise
+    /// the uninhabitedness of both `SecretlyUninhabited` structs is hidden.
+    struct SometimesEmptyStruct {
+        x: a::b::SecretlyUninhabited,
+        y: c::AlsoSecretlyUninhabited,
+    }
+
+    /// This enum can only be seen to be inhabited in module `d`.
+    enum SometimesEmptyEnum {
+        X(c::AlsoSecretlyUninhabited),
+        Y(c::d::VerySecretlyUninhabited),
+    }
+
+    mod a {
+        use super::*;
+        pub mod b {
+            use super::*;
+            pub struct SecretlyUninhabited {
+                _priv: !,
+            }
+            assert_empty!(SometimesEmptyStruct);
+        }
+
+        assert_non_empty!(SometimesEmptyStruct);
+        assert_non_empty!(SometimesEmptyEnum);
+    }
+
+    mod c {
+        use super::*;
+        pub struct AlsoSecretlyUninhabited {
+            _priv: ::Struct1,
+        }
+        assert_empty!(SometimesEmptyStruct);
+        assert_non_empty!(SometimesEmptyEnum);
+
+        pub mod d {
+            use super::*;
+            pub struct VerySecretlyUninhabited {
+                _priv: !,
+            }
+            assert_empty!(SometimesEmptyStruct);
+            assert_empty!(SometimesEmptyEnum);
+        }
+    }
+
+    assert_non_empty!(SometimesEmptyStruct);
+    assert_non_empty!(SometimesEmptyEnum);
+}
+
+fn main() {}