From b82f149d08a0afcc17afa54f5bb3c7031babd44a Mon Sep 17 00:00:00 2001 From: Nadrieril Date: Wed, 2 Dec 2020 23:11:29 +0000 Subject: [PATCH] Add tests for uninhabited types --- .../ui/pattern/usefulness/auxiliary/empty.rs | 8 + .../empty-match.exhaustive_patterns.stderr | 160 +++++++++--------- .../usefulness/empty-match.normal.stderr | 152 +++++++++-------- src/test/ui/pattern/usefulness/empty-match.rs | 100 +++++------ src/test/ui/pattern/usefulness/uninhabited.rs | 143 ++++++++++++++++ 5 files changed, 351 insertions(+), 212 deletions(-) create mode 100644 src/test/ui/pattern/usefulness/uninhabited.rs diff --git a/src/test/ui/pattern/usefulness/auxiliary/empty.rs b/src/test/ui/pattern/usefulness/auxiliary/empty.rs index 0b0719f48ee02..29a03c9e8b50c 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 a5c8af1f81467..b99386e74020e 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 7db11f146b219..b99386e74020e 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 98d8ac180026d..8110ec013d7c1 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:: { - 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 0000000000000..77cd0f4005e95 --- /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() {}