diff options
| author | bors <bors@rust-lang.org> | 2020-11-18 21:24:40 +0000 |
|---|---|---|
| committer | bors <bors@rust-lang.org> | 2020-11-18 21:24:40 +0000 |
| commit | 8256379832b5ecb7f71e8c5e2018446482223c12 (patch) | |
| tree | 1d5e866b6b006d84b3d8ce102a1022234ed2e4ae /src/test/ui/pattern | |
| parent | 8d2d0014922e9f541694bfe87642749239990e0e (diff) | |
| parent | 69821cf8df86c8f4366e0c16a0a7de8d0135b90f (diff) | |
| download | rust-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')
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`. |
