diff options
| author | bors <bors@rust-lang.org> | 2021-01-12 22:58:42 +0000 |
|---|---|---|
| committer | bors <bors@rust-lang.org> | 2021-01-12 22:58:42 +0000 |
| commit | 058a71016553f267ae80b90276ef79956457d51a (patch) | |
| tree | 9cd990416b0821aaa898a16bca44205fd92a4bba /src/test | |
| parent | 7a9b552cb1621c9c57898d147228aab32b65a7c3 (diff) | |
| parent | e608d8f4e5e8e33b5d480323596d2aeabd129e4f (diff) | |
Auto merge of #79670 - Nadrieril:uninhabited-query, r=estebank
Turn type inhabitedness into a query to fix `exhaustive_patterns` perf We measured in https://github.com/rust-lang/rust/pull/79394 that enabling the [`exhaustive_patterns` feature](https://github.com/rust-lang/rust/issues/51085) causes significant perf degradation. It was conjectured that the culprit is type inhabitedness checking, and [I hypothesized](https://github.com/rust-lang/rust/pull/79394#issuecomment-733861149) that turning this computation into a query would solve most of the problem. This PR turns `tcx.is_ty_uninhabited_from` into a query, and I measured a 25% perf gain on the benchmark that stress-tests `exhaustiveness_patterns`. This more than compensates for the 30% perf hit I measured [when creating it](https://github.com/rust-lang/rustc-perf/pull/801). We'll have to measure enabling the feature again, but I suspect this fixes the perf regression entirely. I'd like a perf run on this PR obviously. I made small atomic commits to help reviewing. The first one is just me discovering the "revisions" feature of the testing framework. I believe there's a push to move things out of `rustc_middle` because it's huge. I guess `inhabitedness/mod.rs` could be moved out, but it's quite small. `DefIdForest` might be movable somewhere too. I don't know what the policy is for that. Ping `@camelid` since you were interested in following along `@rustbot` modify labels: +A-exhaustiveness-checking
Diffstat (limited to 'src/test')
11 files changed, 434 insertions, 448 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/match-empty-exhaustive_patterns.stderr b/src/test/ui/pattern/usefulness/empty-match.exhaustive_patterns.stderr index 9d8b5f38e8c..b99386e7402 100644 --- a/src/test/ui/pattern/usefulness/match-empty-exhaustive_patterns.stderr +++ b/src/test/ui/pattern/usefulness/empty-match.exhaustive_patterns.stderr @@ -1,94 +1,94 @@ error: unreachable pattern - --> $DIR/match-empty-exhaustive_patterns.rs:52:9 + --> $DIR/empty-match.rs:37:9 | LL | _ => {}, | ^ | note: the lint level is defined here - --> $DIR/match-empty-exhaustive_patterns.rs:5:9 + --> $DIR/empty-match.rs:8:9 | LL | #![deny(unreachable_patterns)] | ^^^^^^^^^^^^^^^^^^^^ error: unreachable pattern - --> $DIR/match-empty-exhaustive_patterns.rs:55:9 + --> $DIR/empty-match.rs:40:9 | LL | _ if false => {}, | ^ error: unreachable pattern - --> $DIR/match-empty-exhaustive_patterns.rs:62:9 + --> $DIR/empty-match.rs:47:9 | LL | _ => {}, | ^ error: unreachable pattern - --> $DIR/match-empty-exhaustive_patterns.rs:65:9 + --> $DIR/empty-match.rs:50:9 | LL | _ if false => {}, | ^ error: unreachable pattern - --> $DIR/match-empty-exhaustive_patterns.rs:72:9 + --> $DIR/empty-match.rs:57:9 | LL | _ => {}, | ^ error: unreachable pattern - --> $DIR/match-empty-exhaustive_patterns.rs:75:9 + --> $DIR/empty-match.rs:60:9 | LL | _ if false => {}, | ^ -error: unreachable pattern - --> $DIR/match-empty-exhaustive_patterns.rs:82:9 +error[E0004]: non-exhaustive patterns: type `u8` is non-empty + --> $DIR/empty-match.rs:78:20 | -LL | Some(_) => {} - | ^^^^^^^ - -error: unreachable pattern - --> $DIR/match-empty-exhaustive_patterns.rs:86: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/match-empty-exhaustive_patterns.rs:89: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/match-empty-exhaustive_patterns.rs:91: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/match-empty-exhaustive_patterns.rs:93: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/match-empty-exhaustive_patterns.rs:95: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/match-empty-exhaustive_patterns.rs:97: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/match-empty-exhaustive_patterns.rs:99: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/match-empty-exhaustive_patterns.rs:101: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/match-empty-exhaustive_patterns.rs:104: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/match-empty-exhaustive_patterns.rs:106: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/match-empty-exhaustive_patterns.rs:108: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/match-empty-exhaustive_patterns.rs:110: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/match-empty-exhaustive_patterns.rs:112: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/match-empty-exhaustive_patterns.rs:114: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/match-empty-exhaustive_patterns.rs:116: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/match-empty.stderr b/src/test/ui/pattern/usefulness/empty-match.normal.stderr index 6065c552390..b99386e7402 100644 --- a/src/test/ui/pattern/usefulness/match-empty.stderr +++ b/src/test/ui/pattern/usefulness/empty-match.normal.stderr @@ -1,82 +1,94 @@ error: unreachable pattern - --> $DIR/match-empty.rs:51:9 + --> $DIR/empty-match.rs:37:9 | LL | _ => {}, | ^ | note: the lint level is defined here - --> $DIR/match-empty.rs:4:9 + --> $DIR/empty-match.rs:8:9 | LL | #![deny(unreachable_patterns)] | ^^^^^^^^^^^^^^^^^^^^ error: unreachable pattern - --> $DIR/match-empty.rs:54:9 + --> $DIR/empty-match.rs:40:9 | LL | _ if false => {}, | ^ error: unreachable pattern - --> $DIR/match-empty.rs:61:9 + --> $DIR/empty-match.rs:47:9 | LL | _ => {}, | ^ error: unreachable pattern - --> $DIR/match-empty.rs:64:9 + --> $DIR/empty-match.rs:50:9 | LL | _ if false => {}, | ^ error: unreachable pattern - --> $DIR/match-empty.rs:71:9 + --> $DIR/empty-match.rs:57:9 | LL | _ => {}, | ^ error: unreachable pattern - --> $DIR/match-empty.rs:74:9 + --> $DIR/empty-match.rs:60:9 | LL | _ if false => {}, | ^ error[E0004]: non-exhaustive patterns: type `u8` is non-empty - --> $DIR/match-empty.rs:89: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/match-empty.rs:91: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/match-empty.rs:93: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/match-empty.rs:95: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/match-empty.rs:97: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/match-empty.rs:99: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/match-empty.rs:101: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/match-empty.rs:104: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/match-empty.rs:106: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/match-empty.rs:108: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/match-empty.rs:110: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/match-empty.rs:112: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/match-empty.rs:114: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/match-empty.rs:116: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 new file mode 100644 index 00000000000..8110ec013d7 --- /dev/null +++ b/src/test/ui/pattern/usefulness/empty-match.rs @@ -0,0 +1,95 @@ +// 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))] +#![deny(unreachable_patterns)] + +extern crate empty; + +enum EmptyEnum {} + +struct NonEmptyStruct1; +struct NonEmptyStruct2(bool); +union NonEmptyUnion1 { + foo: (), +} +union NonEmptyUnion2 { + foo: (), + bar: (), +} +enum NonEmptyEnum1 { + Foo(bool), +} +enum NonEmptyEnum2 { + Foo(bool), + Bar, +} +enum NonEmptyEnum5 { + V1, V2, V3, V4, V5, +} + +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 { + _ if false => {}, //~ ERROR unreachable pattern + } +} + +macro_rules! match_no_arms { + ($e:expr) => { + match $e {} + }; +} +macro_rules! match_guarded_arm { + ($e:expr) => { + match $e { + _ if false => {} + } + }; +} + +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_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/integer-ranges/pointer-sized-int-deny.rs b/src/test/ui/pattern/usefulness/integer-ranges/pointer-sized-int-deny.rs deleted file mode 100644 index 9292f22e09e..00000000000 --- a/src/test/ui/pattern/usefulness/integer-ranges/pointer-sized-int-deny.rs +++ /dev/null @@ -1,48 +0,0 @@ -#![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-allow.stderr b/src/test/ui/pattern/usefulness/integer-ranges/pointer-sized-int.allow.stderr index 0b3c65166ee..25632934583 100644 --- 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 @@ -1,5 +1,5 @@ error[E0004]: non-exhaustive patterns: type `usize` is non-empty - --> $DIR/pointer-sized-int-allow.rs:36:11 + --> $DIR/pointer-sized-int.rs:48:11 | LL | match 7usize {} | ^^^^^^ 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 index 9d566b0e775..e8ac9f3cfe1 100644 --- 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 @@ -1,5 +1,5 @@ error[E0004]: non-exhaustive patterns: `_` not covered - --> $DIR/pointer-sized-int-deny.rs:10:11 + --> $DIR/pointer-sized-int.rs:12: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/pointer-sized-int-deny.rs:15:11 + --> $DIR/pointer-sized-int.rs:17:11 | LL | match 0isize { | ^^^^^^ pattern `_` not covered @@ -21,7 +21,7 @@ LL | match 0isize { = 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 + --> $DIR/pointer-sized-int.rs:22:8 | LL | m!(0usize, 0..=usize::MAX); | ^^^^^^ pattern `_` not covered @@ -32,7 +32,7 @@ LL | m!(0usize, 0..=usize::MAX); = 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 + --> $DIR/pointer-sized-int.rs:24:8 | LL | m!(0usize, 0..5 | 5..=usize::MAX); | ^^^^^^ pattern `_` not covered @@ -43,7 +43,7 @@ LL | m!(0usize, 0..5 | 5..=usize::MAX); = 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 + --> $DIR/pointer-sized-int.rs:26:8 | LL | m!(0usize, 0..usize::MAX | usize::MAX); | ^^^^^^ pattern `_` not covered @@ -54,7 +54,7 @@ LL | m!(0usize, 0..usize::MAX | usize::MAX); = 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 + --> $DIR/pointer-sized-int.rs:28:8 | LL | m!((0usize, true), (0..5, true) | (5..=usize::MAX, true) | (0..=usize::MAX, false)); | ^^^^^^^^^^^^^^ pattern `(_, _)` not covered @@ -63,7 +63,7 @@ LL | m!((0usize, true), (0..5, true) | (5..=usize::MAX, true) | (0..=usize:: = note: the matched value is of type `(usize, bool)` error[E0004]: non-exhaustive patterns: `_` not covered - --> $DIR/pointer-sized-int-deny.rs:29:8 + --> $DIR/pointer-sized-int.rs:31:8 | LL | m!(0isize, isize::MIN..=isize::MAX); | ^^^^^^ pattern `_` not covered @@ -74,7 +74,7 @@ LL | m!(0isize, isize::MIN..=isize::MAX); = 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 + --> $DIR/pointer-sized-int.rs:33:8 | LL | m!(0isize, isize::MIN..5 | 5..=isize::MAX); | ^^^^^^ pattern `_` not covered @@ -85,7 +85,7 @@ LL | m!(0isize, isize::MIN..5 | 5..=isize::MAX); = 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 + --> $DIR/pointer-sized-int.rs:35:8 | LL | m!(0isize, isize::MIN..isize::MAX | isize::MAX); | ^^^^^^ pattern `_` not covered @@ -96,7 +96,7 @@ LL | m!(0isize, isize::MIN..isize::MAX | isize::MAX); = 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 + --> $DIR/pointer-sized-int.rs:37:8 | LL | m!((0isize, true), (isize::MIN..5, true) | ^^^^^^^^^^^^^^ pattern `(_, _)` not covered @@ -105,7 +105,7 @@ LL | m!((0isize, true), (isize::MIN..5, true) = note: the matched value is of type `(isize, bool)` error[E0004]: non-exhaustive patterns: `_` not covered - --> $DIR/pointer-sized-int-deny.rs:39:11 + --> $DIR/pointer-sized-int.rs:41:11 | LL | match 0isize { | ^^^^^^ pattern `_` not covered @@ -116,7 +116,7 @@ LL | match 0isize { = 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 + --> $DIR/pointer-sized-int.rs:48:11 | LL | match 7usize {} | ^^^^^^ 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.rs index 6173053cc4f..1ed18c26763 100644 --- a/src/test/ui/pattern/usefulness/integer-ranges/pointer-sized-int-allow.rs +++ b/src/test/ui/pattern/usefulness/integer-ranges/pointer-sized-int.rs @@ -1,5 +1,6 @@ -#![feature(precise_pointer_size_matching)] +// revisions: allow deny #![feature(exclusive_range_pattern)] +#![cfg_attr(allow, feature(precise_pointer_size_matching))] macro_rules! m { ($s:expr, $($t:tt)+) => { @@ -9,25 +10,36 @@ macro_rules! m { fn main() { match 0usize { + //[deny]~^ ERROR non-exhaustive patterns 0 ..= usize::MAX => {} } match 0isize { + //[deny]~^ ERROR non-exhaustive patterns isize::MIN ..= isize::MAX => {} } m!(0usize, 0..=usize::MAX); + //[deny]~^ ERROR non-exhaustive patterns m!(0usize, 0..5 | 5..=usize::MAX); + //[deny]~^ ERROR non-exhaustive patterns m!(0usize, 0..usize::MAX | usize::MAX); + //[deny]~^ ERROR non-exhaustive patterns m!((0usize, true), (0..5, true) | (5..=usize::MAX, true) | (0..=usize::MAX, false)); + //[deny]~^ ERROR non-exhaustive patterns m!(0isize, isize::MIN..=isize::MAX); + //[deny]~^ ERROR non-exhaustive patterns m!(0isize, isize::MIN..5 | 5..=isize::MAX); + //[deny]~^ ERROR non-exhaustive patterns m!(0isize, isize::MIN..isize::MAX | isize::MAX); + //[deny]~^ ERROR non-exhaustive patterns m!((0isize, true), (isize::MIN..5, true) | (5..=isize::MAX, true) | (isize::MIN..=isize::MAX, false)); + //[deny]~^^ ERROR non-exhaustive patterns match 0isize { + //[deny]~^ ERROR non-exhaustive patterns isize::MIN ..= -1 => {} 0 => {} 1 ..= isize::MAX => {} diff --git a/src/test/ui/pattern/usefulness/match-empty-exhaustive_patterns.rs b/src/test/ui/pattern/usefulness/match-empty-exhaustive_patterns.rs deleted file mode 100644 index c5c3a214f9a..00000000000 --- a/src/test/ui/pattern/usefulness/match-empty-exhaustive_patterns.rs +++ /dev/null @@ -1,118 +0,0 @@ -// aux-build:empty.rs -#![feature(never_type)] -#![feature(never_type_fallback)] -#![feature(exhaustive_patterns)] -#![deny(unreachable_patterns)] - -extern crate empty; - -enum EmptyEnum {} - -struct NonEmptyStruct(bool); //~ `NonEmptyStruct` defined here -union NonEmptyUnion1 { //~ `NonEmptyUnion1` defined here - foo: (), -} -union NonEmptyUnion2 { //~ `NonEmptyUnion2` defined here - foo: (), - bar: (), -} -enum NonEmptyEnum1 { //~ `NonEmptyEnum1` defined here - Foo(bool), - //~^ not covered - //~| not covered -} -enum NonEmptyEnum2 { //~ `NonEmptyEnum2` defined here - Foo(bool), - //~^ not covered - //~| not covered - Bar, - //~^ not covered - //~| not covered -} -enum NonEmptyEnum5 { //~ `NonEmptyEnum5` defined here - 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 { - _ => {}, //~ 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 { - _ if false => {}, //~ ERROR unreachable pattern - } -} - -fn main() { - match None::<!> { - None => {} - Some(_) => {} //~ ERROR unreachable pattern - } - match None::<EmptyEnum> { - None => {} - Some(_) => {} //~ ERROR unreachable pattern - } - - 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 - - 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 -} diff --git a/src/test/ui/pattern/usefulness/match-empty.rs b/src/test/ui/pattern/usefulness/match-empty.rs deleted file mode 100644 index 10ea2a10406..00000000000 --- a/src/test/ui/pattern/usefulness/match-empty.rs +++ /dev/null @@ -1,118 +0,0 @@ -// aux-build:empty.rs -#![feature(never_type)] -#![feature(never_type_fallback)] -#![deny(unreachable_patterns)] - -extern crate empty; - -enum EmptyEnum {} - -struct NonEmptyStruct(bool); //~ `NonEmptyStruct` defined here -union NonEmptyUnion1 { //~ `NonEmptyUnion1` defined here - foo: (), -} -union NonEmptyUnion2 { //~ `NonEmptyUnion2` defined here - foo: (), - bar: (), -} -enum NonEmptyEnum1 { //~ `NonEmptyEnum1` defined here - Foo(bool), - //~^ not covered - //~| not covered -} -enum NonEmptyEnum2 { //~ `NonEmptyEnum2` defined here - Foo(bool), - //~^ not covered - //~| not covered - Bar, - //~^ not covered - //~| not covered -} -enum NonEmptyEnum5 { //~ `NonEmptyEnum5` defined here - 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 { - _ => {}, //~ 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 { - _ if false => {}, //~ ERROR unreachable pattern - } -} - -fn main() { - // `exhaustive_patterns` is not on, so uninhabited branches are not detected as unreachable. - match None::<!> { - None => {} - Some(_) => {} - } - match None::<EmptyEnum> { - None => {} - Some(_) => {} - } - - 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 - - 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 -} 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() {} |
