about summary refs log tree commit diff
path: root/src/test/ui/pattern
diff options
context:
space:
mode:
authorbors <bors@rust-lang.org>2020-11-18 21:24:40 +0000
committerbors <bors@rust-lang.org>2020-11-18 21:24:40 +0000
commit8256379832b5ecb7f71e8c5e2018446482223c12 (patch)
tree1d5e866b6b006d84b3d8ce102a1022234ed2e4ae /src/test/ui/pattern
parent8d2d0014922e9f541694bfe87642749239990e0e (diff)
parent69821cf8df86c8f4366e0c16a0a7de8d0135b90f (diff)
downloadrust-8256379832b5ecb7f71e8c5e2018446482223c12.tar.gz
rust-8256379832b5ecb7f71e8c5e2018446482223c12.zip
Auto merge of #78995 - Nadrieril:clean-empty-match, r=varkor
Handle empty matches cleanly in exhaustiveness checking

This removes the special-casing of empty matches that was done in `check_match`. This fixes most of https://github.com/rust-lang/rust/issues/55123.
Somewhat unrelatedly, I also made `_match.rs` more self-contained, because I think it's cleaner.

r? `@varkor`
`@rustbot` modify labels: +A-exhaustiveness-checking
Diffstat (limited to 'src/test/ui/pattern')
-rw-r--r--src/test/ui/pattern/usefulness/auxiliary/empty.rs2
-rw-r--r--src/test/ui/pattern/usefulness/match-empty-exhaustive_patterns.rs33
-rw-r--r--src/test/ui/pattern/usefulness/match-empty-exhaustive_patterns.stderr64
-rw-r--r--src/test/ui/pattern/usefulness/match-empty.rs40
-rw-r--r--src/test/ui/pattern/usefulness/match-empty.stderr78
5 files changed, 162 insertions, 55 deletions
diff --git a/src/test/ui/pattern/usefulness/auxiliary/empty.rs b/src/test/ui/pattern/usefulness/auxiliary/empty.rs
new file mode 100644
index 00000000000..0b0719f48ee
--- /dev/null
+++ b/src/test/ui/pattern/usefulness/auxiliary/empty.rs
@@ -0,0 +1,2 @@
+#![crate_type = "rlib"]
+pub enum EmptyForeignEnum {}
diff --git a/src/test/ui/pattern/usefulness/match-empty-exhaustive_patterns.rs b/src/test/ui/pattern/usefulness/match-empty-exhaustive_patterns.rs
index 57b6b910ca1..c5c3a214f9a 100644
--- a/src/test/ui/pattern/usefulness/match-empty-exhaustive_patterns.rs
+++ b/src/test/ui/pattern/usefulness/match-empty-exhaustive_patterns.rs
@@ -1,7 +1,12 @@
+// aux-build:empty.rs
 #![feature(never_type)]
+#![feature(never_type_fallback)]
 #![feature(exhaustive_patterns)]
 #![deny(unreachable_patterns)]
-enum Foo {}
+
+extern crate empty;
+
+enum EmptyEnum {}
 
 struct NonEmptyStruct(bool); //~ `NonEmptyStruct` defined here
 union NonEmptyUnion1 { //~ `NonEmptyUnion1` defined here
@@ -41,8 +46,28 @@ macro_rules! match_false {
     };
 }
 
-fn foo(x: Foo) {
-    match_empty!(x); // ok
+fn empty_enum(x: EmptyEnum) {
+    match x {} // ok
+    match x {
+        _ => {}, //~ ERROR unreachable pattern
+    }
+    match x {
+        _ if false => {}, //~ ERROR unreachable pattern
+    }
+}
+
+fn empty_foreign_enum(x: empty::EmptyForeignEnum) {
+    match x {} // ok
+    match x {
+        _ => {}, //~ ERROR unreachable pattern
+    }
+    match x {
+        _ if false => {}, //~ ERROR unreachable pattern
+    }
+}
+
+fn never(x: !) {
+    match x {} // ok
     match x {
         _ => {}, //~ ERROR unreachable pattern
     }
@@ -56,7 +81,7 @@ fn main() {
         None => {}
         Some(_) => {} //~ ERROR unreachable pattern
     }
-    match None::<Foo> {
+    match None::<EmptyEnum> {
         None => {}
         Some(_) => {} //~ ERROR unreachable pattern
     }
diff --git a/src/test/ui/pattern/usefulness/match-empty-exhaustive_patterns.stderr b/src/test/ui/pattern/usefulness/match-empty-exhaustive_patterns.stderr
index 1f6503e3e9c..9d8b5f38e8c 100644
--- a/src/test/ui/pattern/usefulness/match-empty-exhaustive_patterns.stderr
+++ b/src/test/ui/pattern/usefulness/match-empty-exhaustive_patterns.stderr
@@ -1,35 +1,59 @@
 error: unreachable pattern
-  --> $DIR/match-empty-exhaustive_patterns.rs:47:9
+  --> $DIR/match-empty-exhaustive_patterns.rs:52:9
    |
 LL |         _ => {},
    |         ^
    |
 note: the lint level is defined here
-  --> $DIR/match-empty-exhaustive_patterns.rs:3:9
+  --> $DIR/match-empty-exhaustive_patterns.rs:5:9
    |
 LL | #![deny(unreachable_patterns)]
    |         ^^^^^^^^^^^^^^^^^^^^
 
 error: unreachable pattern
-  --> $DIR/match-empty-exhaustive_patterns.rs:50:9
+  --> $DIR/match-empty-exhaustive_patterns.rs:55:9
    |
 LL |         _ if false => {},
    |         ^
 
 error: unreachable pattern
-  --> $DIR/match-empty-exhaustive_patterns.rs:57:9
+  --> $DIR/match-empty-exhaustive_patterns.rs:62:9
+   |
+LL |         _ => {},
+   |         ^
+
+error: unreachable pattern
+  --> $DIR/match-empty-exhaustive_patterns.rs:65:9
+   |
+LL |         _ if false => {},
+   |         ^
+
+error: unreachable pattern
+  --> $DIR/match-empty-exhaustive_patterns.rs:72:9
+   |
+LL |         _ => {},
+   |         ^
+
+error: unreachable pattern
+  --> $DIR/match-empty-exhaustive_patterns.rs:75:9
+   |
+LL |         _ if false => {},
+   |         ^
+
+error: unreachable pattern
+  --> $DIR/match-empty-exhaustive_patterns.rs:82:9
    |
 LL |         Some(_) => {}
    |         ^^^^^^^
 
 error: unreachable pattern
-  --> $DIR/match-empty-exhaustive_patterns.rs:61:9
+  --> $DIR/match-empty-exhaustive_patterns.rs:86:9
    |
 LL |         Some(_) => {}
    |         ^^^^^^^
 
 error[E0004]: non-exhaustive patterns: type `u8` is non-empty
-  --> $DIR/match-empty-exhaustive_patterns.rs:64:18
+  --> $DIR/match-empty-exhaustive_patterns.rs:89:18
    |
 LL |     match_empty!(0u8);
    |                  ^^^
@@ -38,7 +62,7 @@ LL |     match_empty!(0u8);
    = note: the matched value is of type `u8`
 
 error[E0004]: non-exhaustive patterns: type `NonEmptyStruct` is non-empty
-  --> $DIR/match-empty-exhaustive_patterns.rs:66:18
+  --> $DIR/match-empty-exhaustive_patterns.rs:91:18
    |
 LL | struct NonEmptyStruct(bool);
    | ---------------------------- `NonEmptyStruct` defined here
@@ -50,7 +74,7 @@ LL |     match_empty!(NonEmptyStruct(true));
    = note: the matched value is of type `NonEmptyStruct`
 
 error[E0004]: non-exhaustive patterns: type `NonEmptyUnion1` is non-empty
-  --> $DIR/match-empty-exhaustive_patterns.rs:68:18
+  --> $DIR/match-empty-exhaustive_patterns.rs:93:18
    |
 LL | / union NonEmptyUnion1 {
 LL | |     foo: (),
@@ -64,7 +88,7 @@ LL |       match_empty!((NonEmptyUnion1 { foo: () }));
    = note: the matched value is of type `NonEmptyUnion1`
 
 error[E0004]: non-exhaustive patterns: type `NonEmptyUnion2` is non-empty
-  --> $DIR/match-empty-exhaustive_patterns.rs:70:18
+  --> $DIR/match-empty-exhaustive_patterns.rs:95:18
    |
 LL | / union NonEmptyUnion2 {
 LL | |     foo: (),
@@ -79,7 +103,7 @@ LL |       match_empty!((NonEmptyUnion2 { foo: () }));
    = note: the matched value is of type `NonEmptyUnion2`
 
 error[E0004]: non-exhaustive patterns: `Foo(_)` not covered
-  --> $DIR/match-empty-exhaustive_patterns.rs:72:18
+  --> $DIR/match-empty-exhaustive_patterns.rs:97:18
    |
 LL | / enum NonEmptyEnum1 {
 LL | |     Foo(bool),
@@ -96,7 +120,7 @@ LL |       match_empty!(NonEmptyEnum1::Foo(true));
    = note: the matched value is of type `NonEmptyEnum1`
 
 error[E0004]: non-exhaustive patterns: `Foo(_)` and `Bar` not covered
-  --> $DIR/match-empty-exhaustive_patterns.rs:74:18
+  --> $DIR/match-empty-exhaustive_patterns.rs:99:18
    |
 LL | / enum NonEmptyEnum2 {
 LL | |     Foo(bool),
@@ -117,7 +141,7 @@ LL |       match_empty!(NonEmptyEnum2::Foo(true));
    = note: the matched value is of type `NonEmptyEnum2`
 
 error[E0004]: non-exhaustive patterns: `V1`, `V2`, `V3` and 2 more not covered
-  --> $DIR/match-empty-exhaustive_patterns.rs:76:18
+  --> $DIR/match-empty-exhaustive_patterns.rs:101:18
    |
 LL | / enum NonEmptyEnum5 {
 LL | |     V1, V2, V3, V4, V5,
@@ -131,7 +155,7 @@ LL |       match_empty!(NonEmptyEnum5::V1);
    = note: the matched value is of type `NonEmptyEnum5`
 
 error[E0004]: non-exhaustive patterns: `_` not covered
-  --> $DIR/match-empty-exhaustive_patterns.rs:79:18
+  --> $DIR/match-empty-exhaustive_patterns.rs:104:18
    |
 LL |     match_false!(0u8);
    |                  ^^^ pattern `_` not covered
@@ -140,7 +164,7 @@ LL |     match_false!(0u8);
    = note: the matched value is of type `u8`
 
 error[E0004]: non-exhaustive patterns: `NonEmptyStruct(_)` not covered
-  --> $DIR/match-empty-exhaustive_patterns.rs:81:18
+  --> $DIR/match-empty-exhaustive_patterns.rs:106:18
    |
 LL | struct NonEmptyStruct(bool);
    | ---------------------------- `NonEmptyStruct` defined here
@@ -152,7 +176,7 @@ LL |     match_false!(NonEmptyStruct(true));
    = note: the matched value is of type `NonEmptyStruct`
 
 error[E0004]: non-exhaustive patterns: `NonEmptyUnion1 { .. }` not covered
-  --> $DIR/match-empty-exhaustive_patterns.rs:83:18
+  --> $DIR/match-empty-exhaustive_patterns.rs:108:18
    |
 LL | / union NonEmptyUnion1 {
 LL | |     foo: (),
@@ -166,7 +190,7 @@ LL |       match_false!((NonEmptyUnion1 { foo: () }));
    = note: the matched value is of type `NonEmptyUnion1`
 
 error[E0004]: non-exhaustive patterns: `NonEmptyUnion2 { .. }` not covered
-  --> $DIR/match-empty-exhaustive_patterns.rs:85:18
+  --> $DIR/match-empty-exhaustive_patterns.rs:110:18
    |
 LL | / union NonEmptyUnion2 {
 LL | |     foo: (),
@@ -181,7 +205,7 @@ LL |       match_false!((NonEmptyUnion2 { foo: () }));
    = note: the matched value is of type `NonEmptyUnion2`
 
 error[E0004]: non-exhaustive patterns: `Foo(_)` not covered
-  --> $DIR/match-empty-exhaustive_patterns.rs:87:18
+  --> $DIR/match-empty-exhaustive_patterns.rs:112:18
    |
 LL | / enum NonEmptyEnum1 {
 LL | |     Foo(bool),
@@ -198,7 +222,7 @@ LL |       match_false!(NonEmptyEnum1::Foo(true));
    = note: the matched value is of type `NonEmptyEnum1`
 
 error[E0004]: non-exhaustive patterns: `Foo(_)` and `Bar` not covered
-  --> $DIR/match-empty-exhaustive_patterns.rs:89:18
+  --> $DIR/match-empty-exhaustive_patterns.rs:114:18
    |
 LL | / enum NonEmptyEnum2 {
 LL | |     Foo(bool),
@@ -219,7 +243,7 @@ LL |       match_false!(NonEmptyEnum2::Foo(true));
    = note: the matched value is of type `NonEmptyEnum2`
 
 error[E0004]: non-exhaustive patterns: `V1`, `V2`, `V3` and 2 more not covered
-  --> $DIR/match-empty-exhaustive_patterns.rs:91:18
+  --> $DIR/match-empty-exhaustive_patterns.rs:116:18
    |
 LL | / enum NonEmptyEnum5 {
 LL | |     V1, V2, V3, V4, V5,
@@ -232,6 +256,6 @@ LL |       match_false!(NonEmptyEnum5::V1);
    = 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 18 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/match-empty.rs b/src/test/ui/pattern/usefulness/match-empty.rs
index f7577125d8a..10ea2a10406 100644
--- a/src/test/ui/pattern/usefulness/match-empty.rs
+++ b/src/test/ui/pattern/usefulness/match-empty.rs
@@ -1,6 +1,11 @@
+// aux-build:empty.rs
 #![feature(never_type)]
+#![feature(never_type_fallback)]
 #![deny(unreachable_patterns)]
-enum Foo {}
+
+extern crate empty;
+
+enum EmptyEnum {}
 
 struct NonEmptyStruct(bool); //~ `NonEmptyStruct` defined here
 union NonEmptyUnion1 { //~ `NonEmptyUnion1` defined here
@@ -40,12 +45,33 @@ macro_rules! match_false {
     };
 }
 
-fn foo(x: Foo) {
-    match_empty!(x); // ok
-    match_false!(x); // Not detected as unreachable nor exhaustive.
-    //~^ ERROR non-exhaustive patterns: `_` not covered
+fn empty_enum(x: EmptyEnum) {
+    match x {} // ok
+    match x {
+        _ => {}, //~ ERROR unreachable pattern
+    }
+    match x {
+        _ if false => {}, //~ ERROR unreachable pattern
+    }
+}
+
+fn empty_foreign_enum(x: empty::EmptyForeignEnum) {
+    match x {} // ok
+    match x {
+        _ => {}, //~ ERROR unreachable pattern
+    }
+    match x {
+        _ if false => {}, //~ ERROR unreachable pattern
+    }
+}
+
+fn never(x: !) {
+    match x {} // ok
+    match x {
+        _ => {}, //~ ERROR unreachable pattern
+    }
     match x {
-        _ => {}, // Not detected as unreachable, see #55123.
+        _ if false => {}, //~ ERROR unreachable pattern
     }
 }
 
@@ -55,7 +81,7 @@ fn main() {
         None => {}
         Some(_) => {}
     }
-    match None::<Foo> {
+    match None::<EmptyEnum> {
         None => {}
         Some(_) => {}
     }
diff --git a/src/test/ui/pattern/usefulness/match-empty.stderr b/src/test/ui/pattern/usefulness/match-empty.stderr
index 08095f6e7fb..6065c552390 100644
--- a/src/test/ui/pattern/usefulness/match-empty.stderr
+++ b/src/test/ui/pattern/usefulness/match-empty.stderr
@@ -1,17 +1,47 @@
-error[E0004]: non-exhaustive patterns: `_` not covered
-  --> $DIR/match-empty.rs:45:18
+error: unreachable pattern
+  --> $DIR/match-empty.rs:51:9
    |
-LL | enum Foo {}
-   | ----------- `Foo` defined here
-...
-LL |     match_false!(x); // Not detected as unreachable nor exhaustive.
-   |                  ^ pattern `_` not covered
+LL |         _ => {},
+   |         ^
    |
-   = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
-   = note: the matched value is of type `Foo`
+note: the lint level is defined here
+  --> $DIR/match-empty.rs:4:9
+   |
+LL | #![deny(unreachable_patterns)]
+   |         ^^^^^^^^^^^^^^^^^^^^
+
+error: unreachable pattern
+  --> $DIR/match-empty.rs:54:9
+   |
+LL |         _ if false => {},
+   |         ^
+
+error: unreachable pattern
+  --> $DIR/match-empty.rs:61:9
+   |
+LL |         _ => {},
+   |         ^
+
+error: unreachable pattern
+  --> $DIR/match-empty.rs:64:9
+   |
+LL |         _ if false => {},
+   |         ^
+
+error: unreachable pattern
+  --> $DIR/match-empty.rs:71:9
+   |
+LL |         _ => {},
+   |         ^
+
+error: unreachable pattern
+  --> $DIR/match-empty.rs:74:9
+   |
+LL |         _ if false => {},
+   |         ^
 
 error[E0004]: non-exhaustive patterns: type `u8` is non-empty
-  --> $DIR/match-empty.rs:63:18
+  --> $DIR/match-empty.rs:89:18
    |
 LL |     match_empty!(0u8);
    |                  ^^^
@@ -20,7 +50,7 @@ LL |     match_empty!(0u8);
    = note: the matched value is of type `u8`
 
 error[E0004]: non-exhaustive patterns: type `NonEmptyStruct` is non-empty
-  --> $DIR/match-empty.rs:65:18
+  --> $DIR/match-empty.rs:91:18
    |
 LL | struct NonEmptyStruct(bool);
    | ---------------------------- `NonEmptyStruct` defined here
@@ -32,7 +62,7 @@ LL |     match_empty!(NonEmptyStruct(true));
    = note: the matched value is of type `NonEmptyStruct`
 
 error[E0004]: non-exhaustive patterns: type `NonEmptyUnion1` is non-empty
-  --> $DIR/match-empty.rs:67:18
+  --> $DIR/match-empty.rs:93:18
    |
 LL | / union NonEmptyUnion1 {
 LL | |     foo: (),
@@ -46,7 +76,7 @@ LL |       match_empty!((NonEmptyUnion1 { foo: () }));
    = note: the matched value is of type `NonEmptyUnion1`
 
 error[E0004]: non-exhaustive patterns: type `NonEmptyUnion2` is non-empty
-  --> $DIR/match-empty.rs:69:18
+  --> $DIR/match-empty.rs:95:18
    |
 LL | / union NonEmptyUnion2 {
 LL | |     foo: (),
@@ -61,7 +91,7 @@ LL |       match_empty!((NonEmptyUnion2 { foo: () }));
    = note: the matched value is of type `NonEmptyUnion2`
 
 error[E0004]: non-exhaustive patterns: `Foo(_)` not covered
-  --> $DIR/match-empty.rs:71:18
+  --> $DIR/match-empty.rs:97:18
    |
 LL | / enum NonEmptyEnum1 {
 LL | |     Foo(bool),
@@ -78,7 +108,7 @@ LL |       match_empty!(NonEmptyEnum1::Foo(true));
    = note: the matched value is of type `NonEmptyEnum1`
 
 error[E0004]: non-exhaustive patterns: `Foo(_)` and `Bar` not covered
-  --> $DIR/match-empty.rs:73:18
+  --> $DIR/match-empty.rs:99:18
    |
 LL | / enum NonEmptyEnum2 {
 LL | |     Foo(bool),
@@ -99,7 +129,7 @@ LL |       match_empty!(NonEmptyEnum2::Foo(true));
    = note: the matched value is of type `NonEmptyEnum2`
 
 error[E0004]: non-exhaustive patterns: `V1`, `V2`, `V3` and 2 more not covered
-  --> $DIR/match-empty.rs:75:18
+  --> $DIR/match-empty.rs:101:18
    |
 LL | / enum NonEmptyEnum5 {
 LL | |     V1, V2, V3, V4, V5,
@@ -113,7 +143,7 @@ LL |       match_empty!(NonEmptyEnum5::V1);
    = note: the matched value is of type `NonEmptyEnum5`
 
 error[E0004]: non-exhaustive patterns: `_` not covered
-  --> $DIR/match-empty.rs:78:18
+  --> $DIR/match-empty.rs:104:18
    |
 LL |     match_false!(0u8);
    |                  ^^^ pattern `_` not covered
@@ -122,7 +152,7 @@ LL |     match_false!(0u8);
    = note: the matched value is of type `u8`
 
 error[E0004]: non-exhaustive patterns: `NonEmptyStruct(_)` not covered
-  --> $DIR/match-empty.rs:80:18
+  --> $DIR/match-empty.rs:106:18
    |
 LL | struct NonEmptyStruct(bool);
    | ---------------------------- `NonEmptyStruct` defined here
@@ -134,7 +164,7 @@ LL |     match_false!(NonEmptyStruct(true));
    = note: the matched value is of type `NonEmptyStruct`
 
 error[E0004]: non-exhaustive patterns: `NonEmptyUnion1 { .. }` not covered
-  --> $DIR/match-empty.rs:82:18
+  --> $DIR/match-empty.rs:108:18
    |
 LL | / union NonEmptyUnion1 {
 LL | |     foo: (),
@@ -148,7 +178,7 @@ LL |       match_false!((NonEmptyUnion1 { foo: () }));
    = note: the matched value is of type `NonEmptyUnion1`
 
 error[E0004]: non-exhaustive patterns: `NonEmptyUnion2 { .. }` not covered
-  --> $DIR/match-empty.rs:84:18
+  --> $DIR/match-empty.rs:110:18
    |
 LL | / union NonEmptyUnion2 {
 LL | |     foo: (),
@@ -163,7 +193,7 @@ LL |       match_false!((NonEmptyUnion2 { foo: () }));
    = note: the matched value is of type `NonEmptyUnion2`
 
 error[E0004]: non-exhaustive patterns: `Foo(_)` not covered
-  --> $DIR/match-empty.rs:86:18
+  --> $DIR/match-empty.rs:112:18
    |
 LL | / enum NonEmptyEnum1 {
 LL | |     Foo(bool),
@@ -180,7 +210,7 @@ LL |       match_false!(NonEmptyEnum1::Foo(true));
    = note: the matched value is of type `NonEmptyEnum1`
 
 error[E0004]: non-exhaustive patterns: `Foo(_)` and `Bar` not covered
-  --> $DIR/match-empty.rs:88:18
+  --> $DIR/match-empty.rs:114:18
    |
 LL | / enum NonEmptyEnum2 {
 LL | |     Foo(bool),
@@ -201,7 +231,7 @@ LL |       match_false!(NonEmptyEnum2::Foo(true));
    = note: the matched value is of type `NonEmptyEnum2`
 
 error[E0004]: non-exhaustive patterns: `V1`, `V2`, `V3` and 2 more not covered
-  --> $DIR/match-empty.rs:90:18
+  --> $DIR/match-empty.rs:116:18
    |
 LL | / enum NonEmptyEnum5 {
 LL | |     V1, V2, V3, V4, V5,
@@ -214,6 +244,6 @@ LL |       match_false!(NonEmptyEnum5::V1);
    = 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 15 previous errors
+error: aborting due to 20 previous errors
 
 For more information about this error, try `rustc --explain E0004`.