From 0db087e6840cc865bcf8be09ff940f2ac13341ac Mon Sep 17 00:00:00 2001 From: David Wood Date: Sat, 4 May 2019 01:15:26 +0100 Subject: [PATCH 1/5] Add uninhabitedness tests w/ `#[non_exhaustive]`. This commit adds tests checking that uninhabited non-exhaustive types are considered inhabited when used in another crate. --- .../auxiliary/uninhabited.rs | 25 +++++++ .../ui/rfc-2008-non-exhaustive/uninhabited.rs | 59 +++++++++++++++ .../uninhabited_same_crate.rs | 71 +++++++++++++++++++ .../uninhabited_same_crate.stderr | 38 ++++++++++ 4 files changed, 193 insertions(+) create mode 100644 src/test/ui/rfc-2008-non-exhaustive/auxiliary/uninhabited.rs create mode 100644 src/test/ui/rfc-2008-non-exhaustive/uninhabited.rs create mode 100644 src/test/ui/rfc-2008-non-exhaustive/uninhabited_same_crate.rs create mode 100644 src/test/ui/rfc-2008-non-exhaustive/uninhabited_same_crate.stderr diff --git a/src/test/ui/rfc-2008-non-exhaustive/auxiliary/uninhabited.rs b/src/test/ui/rfc-2008-non-exhaustive/auxiliary/uninhabited.rs new file mode 100644 index 00000000000..a4b936e376d --- /dev/null +++ b/src/test/ui/rfc-2008-non-exhaustive/auxiliary/uninhabited.rs @@ -0,0 +1,25 @@ +#![crate_type = "rlib"] +#![feature(never_type)] +#![feature(non_exhaustive)] + +#[non_exhaustive] +pub enum UninhabitedEnum { +} + +#[non_exhaustive] +pub struct UninhabitedStruct { + _priv: !, +} + +#[non_exhaustive] +pub struct UninhabitedTupleStruct(!); + +pub enum UninhabitedVariants { + #[non_exhaustive] Tuple(!), + #[non_exhaustive] Struct { x: ! } +} + +pub enum PartiallyInhabitedVariants { + Tuple(u8), + #[non_exhaustive] Struct { x: ! } +} diff --git a/src/test/ui/rfc-2008-non-exhaustive/uninhabited.rs b/src/test/ui/rfc-2008-non-exhaustive/uninhabited.rs new file mode 100644 index 00000000000..97061310d19 --- /dev/null +++ b/src/test/ui/rfc-2008-non-exhaustive/uninhabited.rs @@ -0,0 +1,59 @@ +// aux-build:uninhabited.rs +// compile-pass +#![deny(unreachable_patterns)] +#![feature(exhaustive_patterns)] + +extern crate uninhabited; + +use uninhabited::{ + PartiallyInhabitedVariants, + UninhabitedEnum, + UninhabitedStruct, + UninhabitedTupleStruct, + UninhabitedVariants, +}; + +fn uninhabited_enum() -> Option { + None +} + +fn uninhabited_variant() -> Option { + None +} + +fn partially_inhabited_variant() -> PartiallyInhabitedVariants { + PartiallyInhabitedVariants::Tuple(3) +} + +fn uninhabited_struct() -> Option { + None +} + +fn uninhabited_tuple_struct() -> Option { + None +} + +// This test checks that non-exhaustive types that would normally be considered uninhabited within +// the defining crate are not considered uninhabited from extern crates. + +fn main() { + match uninhabited_enum() { + Some(_x) => (), // This line would normally error. + None => (), + } + + match uninhabited_variant() { + Some(_x) => (), // This line would normally error. + None => (), + } + + // This line would normally error. + while let PartiallyInhabitedVariants::Struct { x, .. } = partially_inhabited_variant() { + } + + while let Some(_x) = uninhabited_struct() { // This line would normally error. + } + + while let Some(_x) = uninhabited_tuple_struct() { // This line would normally error. + } +} diff --git a/src/test/ui/rfc-2008-non-exhaustive/uninhabited_same_crate.rs b/src/test/ui/rfc-2008-non-exhaustive/uninhabited_same_crate.rs new file mode 100644 index 00000000000..302a35cab5f --- /dev/null +++ b/src/test/ui/rfc-2008-non-exhaustive/uninhabited_same_crate.rs @@ -0,0 +1,71 @@ +#![deny(unreachable_patterns)] +#![feature(exhaustive_patterns)] +#![feature(never_type)] +#![feature(non_exhaustive)] + +#[non_exhaustive] +pub enum UninhabitedEnum { +} + +#[non_exhaustive] +pub struct UninhabitedTupleStruct(!); + +#[non_exhaustive] +pub struct UninhabitedStruct { + _priv: !, +} + +pub enum UninhabitedVariants { + #[non_exhaustive] Tuple(!), + #[non_exhaustive] Struct { x: ! } +} + +pub enum PartiallyInhabitedVariants { + Tuple(u8), + #[non_exhaustive] Struct { x: ! } +} + +fn uninhabited_enum() -> Option { + None +} + +fn uninhabited_variant() -> Option { + None +} + +fn partially_inhabited_variant() -> PartiallyInhabitedVariants { + PartiallyInhabitedVariants::Tuple(3) +} + +fn uninhabited_struct() -> Option { + None +} + +fn uninhabited_tuple_struct() -> Option { + None +} + +// This test checks that non-exhaustive types that would normally be considered uninhabited within +// the defining crate are still considered uninhabited. + +fn main() { + match uninhabited_enum() { + Some(_x) => (), //~ ERROR unreachable pattern + None => (), + } + + match uninhabited_variant() { + Some(_x) => (), //~ ERROR unreachable pattern + None => (), + } + + while let PartiallyInhabitedVariants::Struct { x } = partially_inhabited_variant() { + //~^ ERROR unreachable pattern + } + + while let Some(_x) = uninhabited_struct() { //~ ERROR unreachable pattern + } + + while let Some(_x) = uninhabited_tuple_struct() { //~ ERROR unreachable pattern + } +} diff --git a/src/test/ui/rfc-2008-non-exhaustive/uninhabited_same_crate.stderr b/src/test/ui/rfc-2008-non-exhaustive/uninhabited_same_crate.stderr new file mode 100644 index 00000000000..942f004c3cf --- /dev/null +++ b/src/test/ui/rfc-2008-non-exhaustive/uninhabited_same_crate.stderr @@ -0,0 +1,38 @@ +error: unreachable pattern + --> $DIR/uninhabited_same_crate.rs:53:9 + | +LL | Some(_x) => (), + | ^^^^^^^^ + | +note: lint level defined here + --> $DIR/uninhabited_same_crate.rs:1:9 + | +LL | #![deny(unreachable_patterns)] + | ^^^^^^^^^^^^^^^^^^^^ + +error: unreachable pattern + --> $DIR/uninhabited_same_crate.rs:58:9 + | +LL | Some(_x) => (), + | ^^^^^^^^ + +error: unreachable pattern + --> $DIR/uninhabited_same_crate.rs:62:15 + | +LL | while let PartiallyInhabitedVariants::Struct { x } = partially_inhabited_variant() { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: unreachable pattern + --> $DIR/uninhabited_same_crate.rs:66:15 + | +LL | while let Some(_x) = uninhabited_struct() { + | ^^^^^^^^ + +error: unreachable pattern + --> $DIR/uninhabited_same_crate.rs:69:15 + | +LL | while let Some(_x) = uninhabited_tuple_struct() { + | ^^^^^^^^ + +error: aborting due to 5 previous errors + From 0d034a2e4dd9418fa41aba4ebdd1ebc31a08c9e9 Mon Sep 17 00:00:00 2001 From: David Wood Date: Sat, 4 May 2019 01:17:26 +0100 Subject: [PATCH 2/5] Fix inhabitedness of non-exhaustive variants. This commit ensures that non-exhaustive variants are considered inhabited when used in extern crates. --- src/librustc/ty/inhabitedness/mod.rs | 11 +++++++--- src/librustc_mir/hair/pattern/_match.rs | 27 ++++++++++++++++++++---- src/test/ui/pattern/const-pat-ice.stderr | 2 +- 3 files changed, 32 insertions(+), 8 deletions(-) diff --git a/src/librustc/ty/inhabitedness/mod.rs b/src/librustc/ty/inhabitedness/mod.rs index 197d3325f51..2fc07fb20bf 100644 --- a/src/librustc/ty/inhabitedness/mod.rs +++ b/src/librustc/ty/inhabitedness/mod.rs @@ -134,9 +134,14 @@ impl<'a, 'gcx, 'tcx> VariantDef { AdtKind::Enum => true, AdtKind::Struct => false, }; - DefIdForest::union(tcx, self.fields.iter().map(|f| { - f.uninhabited_from(tcx, substs, is_enum) - })) + // Non-exhaustive variants from other crates are always considered inhabited. + if self.is_field_list_non_exhaustive() && !self.def_id.is_local() { + DefIdForest::empty() + } else { + DefIdForest::union(tcx, self.fields.iter().map(|f| { + f.uninhabited_from(tcx, substs, is_enum) + })) + } } } diff --git a/src/librustc_mir/hair/pattern/_match.rs b/src/librustc_mir/hair/pattern/_match.rs index edd36abc0b8..fd4416fc2b7 100644 --- a/src/librustc_mir/hair/pattern/_match.rs +++ b/src/librustc_mir/hair/pattern/_match.rs @@ -388,6 +388,18 @@ impl<'a, 'tcx> MatchCheckCtxt<'a, 'tcx> { } } + fn is_non_exhaustive_variant<'p>(&self, pattern: &'p Pattern<'tcx>) -> bool + where 'a: 'p + { + match *pattern.kind { + PatternKind::Variant { adt_def, variant_index, .. } => { + let ref variant = adt_def.variants[variant_index]; + variant.is_field_list_non_exhaustive() + } + _ => false, + } + } + fn is_non_exhaustive_enum(&self, ty: Ty<'tcx>) -> bool { match ty.sty { ty::Adt(adt_def, ..) => adt_def.is_variant_list_non_exhaustive(), @@ -1097,10 +1109,17 @@ pub fn is_useful<'p, 'a: 'p, 'tcx: 'a>(cx: &mut MatchCheckCtxt<'a, 'tcx>, debug!("is_useful_expand_first_col: pcx={:#?}, expanding {:#?}", pcx, v[0]); if let Some(constructors) = pat_constructors(cx, v[0], pcx) { - debug!("is_useful - expanding constructors: {:#?}", constructors); - split_grouped_constructors(cx.tcx, constructors, matrix, pcx.ty).into_iter().map(|c| - is_useful_specialized(cx, matrix, v, c, pcx.ty, witness) - ).find(|result| result.is_useful()).unwrap_or(NotUseful) + let is_declared_nonexhaustive = cx.is_non_exhaustive_variant(v[0]) && !cx.is_local(pcx.ty); + debug!("is_useful - expanding constructors: {:#?}, is_declared_nonexhaustive: {:?}", + constructors, is_declared_nonexhaustive); + + if is_declared_nonexhaustive { + Useful + } else { + split_grouped_constructors(cx.tcx, constructors, matrix, pcx.ty).into_iter().map(|c| + is_useful_specialized(cx, matrix, v, c, pcx.ty, witness) + ).find(|result| result.is_useful()).unwrap_or(NotUseful) + } } else { debug!("is_useful - expanding wildcard"); diff --git a/src/test/ui/pattern/const-pat-ice.stderr b/src/test/ui/pattern/const-pat-ice.stderr index 261e95229a7..260c2e04d74 100644 --- a/src/test/ui/pattern/const-pat-ice.stderr +++ b/src/test/ui/pattern/const-pat-ice.stderr @@ -1,4 +1,4 @@ -thread 'rustc' panicked at 'assertion failed: rows.iter().all(|r| r.len() == v.len())', src/librustc_mir/hair/pattern/_match.rs:1071:5 +thread 'rustc' panicked at 'assertion failed: rows.iter().all(|r| r.len() == v.len())', src/librustc_mir/hair/pattern/_match.rs:1083:5 note: Run with `RUST_BACKTRACE=1` environment variable to display a backtrace. error: internal compiler error: unexpected panic From 8838b9130e2f6551077f432dddd5a8077ae4d2e1 Mon Sep 17 00:00:00 2001 From: David Wood Date: Sat, 4 May 2019 11:03:06 +0100 Subject: [PATCH 3/5] Fix uninhabitedness of non-exhaustive enums. This commit ensures that non-exhaustive enums are considered inhabited when used in extern crates. --- src/librustc/ty/inhabitedness/mod.rs | 11 ++- src/librustc_mir/hair/pattern/check_match.rs | 6 +- .../ui/rfc-2008-non-exhaustive/uninhabited.rs | 55 +++++--------- .../uninhabited.stderr | 47 ++++++++++++ .../uninhabited_match.rs | 19 +++++ .../uninhabited_match.stderr | 11 +++ .../uninhabited_match_same_crate.rs | 18 +++++ ...nhabited_match_with_exhaustive_patterns.rs | 22 ++++++ ...ited_match_with_exhaustive_patterns.stderr | 11 +++ ...tch_with_exhaustive_patterns_same_crate.rs | 21 ++++++ .../uninhabited_patterns.rs | 59 +++++++++++++++ .../uninhabited_patterns_same_crate.rs | 71 +++++++++++++++++++ .../uninhabited_patterns_same_crate.stderr | 38 ++++++++++ .../uninhabited_same_crate.rs | 57 +++++---------- .../uninhabited_same_crate.stderr | 65 +++++++++-------- 15 files changed, 400 insertions(+), 111 deletions(-) create mode 100644 src/test/ui/rfc-2008-non-exhaustive/uninhabited.stderr create mode 100644 src/test/ui/rfc-2008-non-exhaustive/uninhabited_match.rs create mode 100644 src/test/ui/rfc-2008-non-exhaustive/uninhabited_match.stderr create mode 100644 src/test/ui/rfc-2008-non-exhaustive/uninhabited_match_same_crate.rs create mode 100644 src/test/ui/rfc-2008-non-exhaustive/uninhabited_match_with_exhaustive_patterns.rs create mode 100644 src/test/ui/rfc-2008-non-exhaustive/uninhabited_match_with_exhaustive_patterns.stderr create mode 100644 src/test/ui/rfc-2008-non-exhaustive/uninhabited_match_with_exhaustive_patterns_same_crate.rs create mode 100644 src/test/ui/rfc-2008-non-exhaustive/uninhabited_patterns.rs create mode 100644 src/test/ui/rfc-2008-non-exhaustive/uninhabited_patterns_same_crate.rs create mode 100644 src/test/ui/rfc-2008-non-exhaustive/uninhabited_patterns_same_crate.stderr diff --git a/src/librustc/ty/inhabitedness/mod.rs b/src/librustc/ty/inhabitedness/mod.rs index 2fc07fb20bf..be1d973c2cd 100644 --- a/src/librustc/ty/inhabitedness/mod.rs +++ b/src/librustc/ty/inhabitedness/mod.rs @@ -113,9 +113,14 @@ impl<'a, 'gcx, 'tcx> AdtDef { tcx: TyCtxt<'a, 'gcx, 'tcx>, substs: SubstsRef<'tcx>) -> DefIdForest { - DefIdForest::intersection(tcx, self.variants.iter().map(|v| { - v.uninhabited_from(tcx, substs, self.adt_kind()) - })) + // Non-exhaustive ADTs from other crates are always considered inhabited. + if self.is_variant_list_non_exhaustive() && !self.did.is_local() { + DefIdForest::empty() + } else { + DefIdForest::intersection(tcx, self.variants.iter().map(|v| { + v.uninhabited_from(tcx, substs, self.adt_kind()) + })) + } } } diff --git a/src/librustc_mir/hair/pattern/check_match.rs b/src/librustc_mir/hair/pattern/check_match.rs index 1a7266859ad..8c7155e1df3 100644 --- a/src/librustc_mir/hair/pattern/check_match.rs +++ b/src/librustc_mir/hair/pattern/check_match.rs @@ -208,7 +208,11 @@ impl<'a, 'tcx> MatchVisitor<'a, 'tcx> { .map(|variant| variant.ident) .collect(); } - def.variants.is_empty() + + let is_non_exhaustive_and_non_local = + def.is_variant_list_non_exhaustive() && !def.did.is_local(); + + !(is_non_exhaustive_and_non_local) && def.variants.is_empty() }, _ => false } diff --git a/src/test/ui/rfc-2008-non-exhaustive/uninhabited.rs b/src/test/ui/rfc-2008-non-exhaustive/uninhabited.rs index 97061310d19..80b9dc4c1c3 100644 --- a/src/test/ui/rfc-2008-non-exhaustive/uninhabited.rs +++ b/src/test/ui/rfc-2008-non-exhaustive/uninhabited.rs @@ -1,59 +1,38 @@ // aux-build:uninhabited.rs -// compile-pass -#![deny(unreachable_patterns)] -#![feature(exhaustive_patterns)] +#![feature(never_type)] extern crate uninhabited; use uninhabited::{ - PartiallyInhabitedVariants, UninhabitedEnum, UninhabitedStruct, UninhabitedTupleStruct, UninhabitedVariants, }; -fn uninhabited_enum() -> Option { - None +// This test checks that uninhabited non-exhaustive types cannot coerce to any type, as the never +// type can. + +struct A; + +fn can_coerce_never_type_to_anything(x: !) -> A { + x } -fn uninhabited_variant() -> Option { - None +fn cannot_coerce_empty_enum_to_anything(x: UninhabitedEnum) -> A { + x //~ ERROR mismatched types } -fn partially_inhabited_variant() -> PartiallyInhabitedVariants { - PartiallyInhabitedVariants::Tuple(3) +fn cannot_coerce_empty_tuple_struct_to_anything(x: UninhabitedTupleStruct) -> A { + x //~ ERROR mismatched types } -fn uninhabited_struct() -> Option { - None +fn cannot_coerce_empty_struct_to_anything(x: UninhabitedStruct) -> A { + x //~ ERROR mismatched types } -fn uninhabited_tuple_struct() -> Option { - None +fn cannot_coerce_enum_with_empty_variants_to_anything(x: UninhabitedVariants) -> A { + x //~ ERROR mismatched types } -// This test checks that non-exhaustive types that would normally be considered uninhabited within -// the defining crate are not considered uninhabited from extern crates. - -fn main() { - match uninhabited_enum() { - Some(_x) => (), // This line would normally error. - None => (), - } - - match uninhabited_variant() { - Some(_x) => (), // This line would normally error. - None => (), - } - - // This line would normally error. - while let PartiallyInhabitedVariants::Struct { x, .. } = partially_inhabited_variant() { - } - - while let Some(_x) = uninhabited_struct() { // This line would normally error. - } - - while let Some(_x) = uninhabited_tuple_struct() { // This line would normally error. - } -} +fn main() {} diff --git a/src/test/ui/rfc-2008-non-exhaustive/uninhabited.stderr b/src/test/ui/rfc-2008-non-exhaustive/uninhabited.stderr new file mode 100644 index 00000000000..490a6c10117 --- /dev/null +++ b/src/test/ui/rfc-2008-non-exhaustive/uninhabited.stderr @@ -0,0 +1,47 @@ +error[E0308]: mismatched types + --> $DIR/uninhabited.rs:23:5 + | +LL | fn cannot_coerce_empty_enum_to_anything(x: UninhabitedEnum) -> A { + | - expected `A` because of return type +LL | x + | ^ expected struct `A`, found enum `uninhabited::UninhabitedEnum` + | + = note: expected type `A` + found type `uninhabited::UninhabitedEnum` + +error[E0308]: mismatched types + --> $DIR/uninhabited.rs:27:5 + | +LL | fn cannot_coerce_empty_tuple_struct_to_anything(x: UninhabitedTupleStruct) -> A { + | - expected `A` because of return type +LL | x + | ^ expected struct `A`, found struct `uninhabited::UninhabitedTupleStruct` + | + = note: expected type `A` + found type `uninhabited::UninhabitedTupleStruct` + +error[E0308]: mismatched types + --> $DIR/uninhabited.rs:31:5 + | +LL | fn cannot_coerce_empty_struct_to_anything(x: UninhabitedStruct) -> A { + | - expected `A` because of return type +LL | x + | ^ expected struct `A`, found struct `uninhabited::UninhabitedStruct` + | + = note: expected type `A` + found type `uninhabited::UninhabitedStruct` + +error[E0308]: mismatched types + --> $DIR/uninhabited.rs:35:5 + | +LL | fn cannot_coerce_enum_with_empty_variants_to_anything(x: UninhabitedVariants) -> A { + | - expected `A` because of return type +LL | x + | ^ expected struct `A`, found enum `uninhabited::UninhabitedVariants` + | + = note: expected type `A` + found type `uninhabited::UninhabitedVariants` + +error: aborting due to 4 previous errors + +For more information about this error, try `rustc --explain E0308`. diff --git a/src/test/ui/rfc-2008-non-exhaustive/uninhabited_match.rs b/src/test/ui/rfc-2008-non-exhaustive/uninhabited_match.rs new file mode 100644 index 00000000000..0166b2e46cb --- /dev/null +++ b/src/test/ui/rfc-2008-non-exhaustive/uninhabited_match.rs @@ -0,0 +1,19 @@ +// aux-build:uninhabited.rs +#![feature(never_type)] + +extern crate uninhabited; + +use uninhabited::{ + UninhabitedEnum, +}; + +struct A; + +// This test checks that an empty match on a non-exhaustive uninhabited type from an extern crate +// will not compile. + +fn cannot_empty_match_on_empty_enum_to_anything(x: UninhabitedEnum) -> A { + match x {} //~ ERROR non-exhaustive patterns +} + +fn main() {} diff --git a/src/test/ui/rfc-2008-non-exhaustive/uninhabited_match.stderr b/src/test/ui/rfc-2008-non-exhaustive/uninhabited_match.stderr new file mode 100644 index 00000000000..3000e1b0930 --- /dev/null +++ b/src/test/ui/rfc-2008-non-exhaustive/uninhabited_match.stderr @@ -0,0 +1,11 @@ +error[E0004]: non-exhaustive patterns: type `uninhabited::UninhabitedEnum` is non-empty + --> $DIR/uninhabited_match.rs:16:11 + | +LL | match x {} + | ^ + | + = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0004`. diff --git a/src/test/ui/rfc-2008-non-exhaustive/uninhabited_match_same_crate.rs b/src/test/ui/rfc-2008-non-exhaustive/uninhabited_match_same_crate.rs new file mode 100644 index 00000000000..d8b1c3810f3 --- /dev/null +++ b/src/test/ui/rfc-2008-non-exhaustive/uninhabited_match_same_crate.rs @@ -0,0 +1,18 @@ +// compile-pass +#![feature(never_type)] +#![feature(non_exhaustive)] + +#[non_exhaustive] +pub enum UninhabitedEnum { +} + +struct A; + +// This test checks that an empty match on a non-exhaustive uninhabited type from the defining crate +// will compile. + +fn cannot_empty_match_on_empty_enum_to_anything(x: UninhabitedEnum) -> A { + match x {} +} + +fn main() {} diff --git a/src/test/ui/rfc-2008-non-exhaustive/uninhabited_match_with_exhaustive_patterns.rs b/src/test/ui/rfc-2008-non-exhaustive/uninhabited_match_with_exhaustive_patterns.rs new file mode 100644 index 00000000000..d82010158cc --- /dev/null +++ b/src/test/ui/rfc-2008-non-exhaustive/uninhabited_match_with_exhaustive_patterns.rs @@ -0,0 +1,22 @@ +// aux-build:uninhabited.rs +#![deny(unreachable_patterns)] +#![feature(exhaustive_patterns)] +#![feature(never_type)] + +extern crate uninhabited; + +use uninhabited::{ + UninhabitedEnum, +}; + +struct A; + +// This test checks that an empty match on a non-exhaustive uninhabited type from an extern crate +// will not compile. In particular, this enables the `exhaustive_patterns` feature as this can +// change the branch used in the compiler to determine this. + +fn cannot_empty_match_on_empty_enum_to_anything(x: UninhabitedEnum) -> A { + match x {} //~ ERROR non-exhaustive patterns +} + +fn main() {} diff --git a/src/test/ui/rfc-2008-non-exhaustive/uninhabited_match_with_exhaustive_patterns.stderr b/src/test/ui/rfc-2008-non-exhaustive/uninhabited_match_with_exhaustive_patterns.stderr new file mode 100644 index 00000000000..73d9e689b55 --- /dev/null +++ b/src/test/ui/rfc-2008-non-exhaustive/uninhabited_match_with_exhaustive_patterns.stderr @@ -0,0 +1,11 @@ +error[E0004]: non-exhaustive patterns: type `uninhabited::UninhabitedEnum` is non-empty + --> $DIR/uninhabited_match_with_exhaustive_patterns.rs:19:11 + | +LL | match x {} + | ^ + | + = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0004`. diff --git a/src/test/ui/rfc-2008-non-exhaustive/uninhabited_match_with_exhaustive_patterns_same_crate.rs b/src/test/ui/rfc-2008-non-exhaustive/uninhabited_match_with_exhaustive_patterns_same_crate.rs new file mode 100644 index 00000000000..da814a70a75 --- /dev/null +++ b/src/test/ui/rfc-2008-non-exhaustive/uninhabited_match_with_exhaustive_patterns_same_crate.rs @@ -0,0 +1,21 @@ +// compile-pass +#![deny(unreachable_patterns)] +#![feature(exhaustive_patterns)] +#![feature(never_type)] +#![feature(non_exhaustive)] + +#[non_exhaustive] +pub enum UninhabitedEnum { +} + +struct A; + +// This test checks that an empty match on a non-exhaustive uninhabited type from the defining crate +// will compile. In particular, this enables the `exhaustive_patterns` feature as this can +// change the branch used in the compiler to determine this. + +fn cannot_empty_match_on_empty_enum_to_anything(x: UninhabitedEnum) -> A { + match x {} +} + +fn main() {} diff --git a/src/test/ui/rfc-2008-non-exhaustive/uninhabited_patterns.rs b/src/test/ui/rfc-2008-non-exhaustive/uninhabited_patterns.rs new file mode 100644 index 00000000000..97061310d19 --- /dev/null +++ b/src/test/ui/rfc-2008-non-exhaustive/uninhabited_patterns.rs @@ -0,0 +1,59 @@ +// aux-build:uninhabited.rs +// compile-pass +#![deny(unreachable_patterns)] +#![feature(exhaustive_patterns)] + +extern crate uninhabited; + +use uninhabited::{ + PartiallyInhabitedVariants, + UninhabitedEnum, + UninhabitedStruct, + UninhabitedTupleStruct, + UninhabitedVariants, +}; + +fn uninhabited_enum() -> Option { + None +} + +fn uninhabited_variant() -> Option { + None +} + +fn partially_inhabited_variant() -> PartiallyInhabitedVariants { + PartiallyInhabitedVariants::Tuple(3) +} + +fn uninhabited_struct() -> Option { + None +} + +fn uninhabited_tuple_struct() -> Option { + None +} + +// This test checks that non-exhaustive types that would normally be considered uninhabited within +// the defining crate are not considered uninhabited from extern crates. + +fn main() { + match uninhabited_enum() { + Some(_x) => (), // This line would normally error. + None => (), + } + + match uninhabited_variant() { + Some(_x) => (), // This line would normally error. + None => (), + } + + // This line would normally error. + while let PartiallyInhabitedVariants::Struct { x, .. } = partially_inhabited_variant() { + } + + while let Some(_x) = uninhabited_struct() { // This line would normally error. + } + + while let Some(_x) = uninhabited_tuple_struct() { // This line would normally error. + } +} diff --git a/src/test/ui/rfc-2008-non-exhaustive/uninhabited_patterns_same_crate.rs b/src/test/ui/rfc-2008-non-exhaustive/uninhabited_patterns_same_crate.rs new file mode 100644 index 00000000000..302a35cab5f --- /dev/null +++ b/src/test/ui/rfc-2008-non-exhaustive/uninhabited_patterns_same_crate.rs @@ -0,0 +1,71 @@ +#![deny(unreachable_patterns)] +#![feature(exhaustive_patterns)] +#![feature(never_type)] +#![feature(non_exhaustive)] + +#[non_exhaustive] +pub enum UninhabitedEnum { +} + +#[non_exhaustive] +pub struct UninhabitedTupleStruct(!); + +#[non_exhaustive] +pub struct UninhabitedStruct { + _priv: !, +} + +pub enum UninhabitedVariants { + #[non_exhaustive] Tuple(!), + #[non_exhaustive] Struct { x: ! } +} + +pub enum PartiallyInhabitedVariants { + Tuple(u8), + #[non_exhaustive] Struct { x: ! } +} + +fn uninhabited_enum() -> Option { + None +} + +fn uninhabited_variant() -> Option { + None +} + +fn partially_inhabited_variant() -> PartiallyInhabitedVariants { + PartiallyInhabitedVariants::Tuple(3) +} + +fn uninhabited_struct() -> Option { + None +} + +fn uninhabited_tuple_struct() -> Option { + None +} + +// This test checks that non-exhaustive types that would normally be considered uninhabited within +// the defining crate are still considered uninhabited. + +fn main() { + match uninhabited_enum() { + Some(_x) => (), //~ ERROR unreachable pattern + None => (), + } + + match uninhabited_variant() { + Some(_x) => (), //~ ERROR unreachable pattern + None => (), + } + + while let PartiallyInhabitedVariants::Struct { x } = partially_inhabited_variant() { + //~^ ERROR unreachable pattern + } + + while let Some(_x) = uninhabited_struct() { //~ ERROR unreachable pattern + } + + while let Some(_x) = uninhabited_tuple_struct() { //~ ERROR unreachable pattern + } +} diff --git a/src/test/ui/rfc-2008-non-exhaustive/uninhabited_patterns_same_crate.stderr b/src/test/ui/rfc-2008-non-exhaustive/uninhabited_patterns_same_crate.stderr new file mode 100644 index 00000000000..8e995632b2f --- /dev/null +++ b/src/test/ui/rfc-2008-non-exhaustive/uninhabited_patterns_same_crate.stderr @@ -0,0 +1,38 @@ +error: unreachable pattern + --> $DIR/uninhabited_patterns_same_crate.rs:53:9 + | +LL | Some(_x) => (), + | ^^^^^^^^ + | +note: lint level defined here + --> $DIR/uninhabited_patterns_same_crate.rs:1:9 + | +LL | #![deny(unreachable_patterns)] + | ^^^^^^^^^^^^^^^^^^^^ + +error: unreachable pattern + --> $DIR/uninhabited_patterns_same_crate.rs:58:9 + | +LL | Some(_x) => (), + | ^^^^^^^^ + +error: unreachable pattern + --> $DIR/uninhabited_patterns_same_crate.rs:62:15 + | +LL | while let PartiallyInhabitedVariants::Struct { x } = partially_inhabited_variant() { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: unreachable pattern + --> $DIR/uninhabited_patterns_same_crate.rs:66:15 + | +LL | while let Some(_x) = uninhabited_struct() { + | ^^^^^^^^ + +error: unreachable pattern + --> $DIR/uninhabited_patterns_same_crate.rs:69:15 + | +LL | while let Some(_x) = uninhabited_tuple_struct() { + | ^^^^^^^^ + +error: aborting due to 5 previous errors + diff --git a/src/test/ui/rfc-2008-non-exhaustive/uninhabited_same_crate.rs b/src/test/ui/rfc-2008-non-exhaustive/uninhabited_same_crate.rs index 302a35cab5f..803a542f8aa 100644 --- a/src/test/ui/rfc-2008-non-exhaustive/uninhabited_same_crate.rs +++ b/src/test/ui/rfc-2008-non-exhaustive/uninhabited_same_crate.rs @@ -1,5 +1,3 @@ -#![deny(unreachable_patterns)] -#![feature(exhaustive_patterns)] #![feature(never_type)] #![feature(non_exhaustive)] @@ -20,52 +18,29 @@ pub enum UninhabitedVariants { #[non_exhaustive] Struct { x: ! } } -pub enum PartiallyInhabitedVariants { - Tuple(u8), - #[non_exhaustive] Struct { x: ! } +struct A; + +// This test checks that uninhabited non-exhaustive types defined in the same crate cannot coerce +// to any type, as the never type can. + +fn can_coerce_never_type_to_anything(x: !) -> A { + x } -fn uninhabited_enum() -> Option { - None +fn cannot_coerce_empty_enum_to_anything(x: UninhabitedEnum) -> A { + x //~ ERROR mismatched types } -fn uninhabited_variant() -> Option { - None +fn cannot_coerce_empty_tuple_struct_to_anything(x: UninhabitedTupleStruct) -> A { + x //~ ERROR mismatched types } -fn partially_inhabited_variant() -> PartiallyInhabitedVariants { - PartiallyInhabitedVariants::Tuple(3) +fn cannot_coerce_empty_struct_to_anything(x: UninhabitedStruct) -> A { + x //~ ERROR mismatched types } -fn uninhabited_struct() -> Option { - None +fn cannot_coerce_enum_with_empty_variants_to_anything(x: UninhabitedVariants) -> A { + x //~ ERROR mismatched types } -fn uninhabited_tuple_struct() -> Option { - None -} - -// This test checks that non-exhaustive types that would normally be considered uninhabited within -// the defining crate are still considered uninhabited. - -fn main() { - match uninhabited_enum() { - Some(_x) => (), //~ ERROR unreachable pattern - None => (), - } - - match uninhabited_variant() { - Some(_x) => (), //~ ERROR unreachable pattern - None => (), - } - - while let PartiallyInhabitedVariants::Struct { x } = partially_inhabited_variant() { - //~^ ERROR unreachable pattern - } - - while let Some(_x) = uninhabited_struct() { //~ ERROR unreachable pattern - } - - while let Some(_x) = uninhabited_tuple_struct() { //~ ERROR unreachable pattern - } -} +fn main() {} diff --git a/src/test/ui/rfc-2008-non-exhaustive/uninhabited_same_crate.stderr b/src/test/ui/rfc-2008-non-exhaustive/uninhabited_same_crate.stderr index 942f004c3cf..ea79e7105d5 100644 --- a/src/test/ui/rfc-2008-non-exhaustive/uninhabited_same_crate.stderr +++ b/src/test/ui/rfc-2008-non-exhaustive/uninhabited_same_crate.stderr @@ -1,38 +1,47 @@ -error: unreachable pattern - --> $DIR/uninhabited_same_crate.rs:53:9 +error[E0308]: mismatched types + --> $DIR/uninhabited_same_crate.rs:31:5 | -LL | Some(_x) => (), - | ^^^^^^^^ +LL | fn cannot_coerce_empty_enum_to_anything(x: UninhabitedEnum) -> A { + | - expected `A` because of return type +LL | x + | ^ expected struct `A`, found enum `UninhabitedEnum` | -note: lint level defined here - --> $DIR/uninhabited_same_crate.rs:1:9 - | -LL | #![deny(unreachable_patterns)] - | ^^^^^^^^^^^^^^^^^^^^ + = note: expected type `A` + found type `UninhabitedEnum` -error: unreachable pattern - --> $DIR/uninhabited_same_crate.rs:58:9 +error[E0308]: mismatched types + --> $DIR/uninhabited_same_crate.rs:35:5 | -LL | Some(_x) => (), - | ^^^^^^^^ - -error: unreachable pattern - --> $DIR/uninhabited_same_crate.rs:62:15 +LL | fn cannot_coerce_empty_tuple_struct_to_anything(x: UninhabitedTupleStruct) -> A { + | - expected `A` because of return type +LL | x + | ^ expected struct `A`, found struct `UninhabitedTupleStruct` | -LL | while let PartiallyInhabitedVariants::Struct { x } = partially_inhabited_variant() { - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + = note: expected type `A` + found type `UninhabitedTupleStruct` -error: unreachable pattern - --> $DIR/uninhabited_same_crate.rs:66:15 +error[E0308]: mismatched types + --> $DIR/uninhabited_same_crate.rs:39:5 | -LL | while let Some(_x) = uninhabited_struct() { - | ^^^^^^^^ - -error: unreachable pattern - --> $DIR/uninhabited_same_crate.rs:69:15 +LL | fn cannot_coerce_empty_struct_to_anything(x: UninhabitedStruct) -> A { + | - expected `A` because of return type +LL | x + | ^ expected struct `A`, found struct `UninhabitedStruct` | -LL | while let Some(_x) = uninhabited_tuple_struct() { - | ^^^^^^^^ + = note: expected type `A` + found type `UninhabitedStruct` -error: aborting due to 5 previous errors +error[E0308]: mismatched types + --> $DIR/uninhabited_same_crate.rs:43:5 + | +LL | fn cannot_coerce_enum_with_empty_variants_to_anything(x: UninhabitedVariants) -> A { + | - expected `A` because of return type +LL | x + | ^ expected struct `A`, found enum `UninhabitedVariants` + | + = note: expected type `A` + found type `UninhabitedVariants` +error: aborting due to 4 previous errors + +For more information about this error, try `rustc --explain E0308`. From 214f977fee19aeeb4f5ab4df8e0b5d37e611cb48 Mon Sep 17 00:00:00 2001 From: David Wood Date: Sat, 4 May 2019 11:08:57 +0100 Subject: [PATCH 4/5] Move uninhabited tests into subdirectory. This commit just tries to tidy up a little. --- .../{ => uninhabited}/auxiliary/uninhabited.rs | 0 .../{uninhabited.rs => uninhabited/coercions.rs} | 0 .../coercions.stderr} | 8 ++++---- .../coercions_same_crate.rs} | 0 .../coercions_same_crate.stderr} | 8 ++++---- .../{uninhabited_match.rs => uninhabited/match.rs} | 0 .../match.stderr} | 2 +- .../match_same_crate.rs} | 0 .../match_with_exhaustive_patterns.rs} | 0 .../match_with_exhaustive_patterns.stderr} | 2 +- .../match_with_exhaustive_patterns_same_crate.rs} | 0 .../patterns.rs} | 0 .../patterns_same_crate.rs} | 0 .../patterns_same_crate.stderr} | 12 ++++++------ 14 files changed, 16 insertions(+), 16 deletions(-) rename src/test/ui/rfc-2008-non-exhaustive/{ => uninhabited}/auxiliary/uninhabited.rs (100%) rename src/test/ui/rfc-2008-non-exhaustive/{uninhabited.rs => uninhabited/coercions.rs} (100%) rename src/test/ui/rfc-2008-non-exhaustive/{uninhabited.stderr => uninhabited/coercions.stderr} (93%) rename src/test/ui/rfc-2008-non-exhaustive/{uninhabited_same_crate.rs => uninhabited/coercions_same_crate.rs} (100%) rename src/test/ui/rfc-2008-non-exhaustive/{uninhabited_same_crate.stderr => uninhabited/coercions_same_crate.stderr} (90%) rename src/test/ui/rfc-2008-non-exhaustive/{uninhabited_match.rs => uninhabited/match.rs} (100%) rename src/test/ui/rfc-2008-non-exhaustive/{uninhabited_match.stderr => uninhabited/match.stderr} (90%) rename src/test/ui/rfc-2008-non-exhaustive/{uninhabited_match_same_crate.rs => uninhabited/match_same_crate.rs} (100%) rename src/test/ui/rfc-2008-non-exhaustive/{uninhabited_match_with_exhaustive_patterns.rs => uninhabited/match_with_exhaustive_patterns.rs} (100%) rename src/test/ui/rfc-2008-non-exhaustive/{uninhabited_match_with_exhaustive_patterns.stderr => uninhabited/match_with_exhaustive_patterns.stderr} (84%) rename src/test/ui/rfc-2008-non-exhaustive/{uninhabited_match_with_exhaustive_patterns_same_crate.rs => uninhabited/match_with_exhaustive_patterns_same_crate.rs} (100%) rename src/test/ui/rfc-2008-non-exhaustive/{uninhabited_patterns.rs => uninhabited/patterns.rs} (100%) rename src/test/ui/rfc-2008-non-exhaustive/{uninhabited_patterns_same_crate.rs => uninhabited/patterns_same_crate.rs} (100%) rename src/test/ui/rfc-2008-non-exhaustive/{uninhabited_patterns_same_crate.stderr => uninhabited/patterns_same_crate.stderr} (70%) diff --git a/src/test/ui/rfc-2008-non-exhaustive/auxiliary/uninhabited.rs b/src/test/ui/rfc-2008-non-exhaustive/uninhabited/auxiliary/uninhabited.rs similarity index 100% rename from src/test/ui/rfc-2008-non-exhaustive/auxiliary/uninhabited.rs rename to src/test/ui/rfc-2008-non-exhaustive/uninhabited/auxiliary/uninhabited.rs diff --git a/src/test/ui/rfc-2008-non-exhaustive/uninhabited.rs b/src/test/ui/rfc-2008-non-exhaustive/uninhabited/coercions.rs similarity index 100% rename from src/test/ui/rfc-2008-non-exhaustive/uninhabited.rs rename to src/test/ui/rfc-2008-non-exhaustive/uninhabited/coercions.rs diff --git a/src/test/ui/rfc-2008-non-exhaustive/uninhabited.stderr b/src/test/ui/rfc-2008-non-exhaustive/uninhabited/coercions.stderr similarity index 93% rename from src/test/ui/rfc-2008-non-exhaustive/uninhabited.stderr rename to src/test/ui/rfc-2008-non-exhaustive/uninhabited/coercions.stderr index 490a6c10117..d05ee1d39ec 100644 --- a/src/test/ui/rfc-2008-non-exhaustive/uninhabited.stderr +++ b/src/test/ui/rfc-2008-non-exhaustive/uninhabited/coercions.stderr @@ -1,5 +1,5 @@ error[E0308]: mismatched types - --> $DIR/uninhabited.rs:23:5 + --> $DIR/coercions.rs:23:5 | LL | fn cannot_coerce_empty_enum_to_anything(x: UninhabitedEnum) -> A { | - expected `A` because of return type @@ -10,7 +10,7 @@ LL | x found type `uninhabited::UninhabitedEnum` error[E0308]: mismatched types - --> $DIR/uninhabited.rs:27:5 + --> $DIR/coercions.rs:27:5 | LL | fn cannot_coerce_empty_tuple_struct_to_anything(x: UninhabitedTupleStruct) -> A { | - expected `A` because of return type @@ -21,7 +21,7 @@ LL | x found type `uninhabited::UninhabitedTupleStruct` error[E0308]: mismatched types - --> $DIR/uninhabited.rs:31:5 + --> $DIR/coercions.rs:31:5 | LL | fn cannot_coerce_empty_struct_to_anything(x: UninhabitedStruct) -> A { | - expected `A` because of return type @@ -32,7 +32,7 @@ LL | x found type `uninhabited::UninhabitedStruct` error[E0308]: mismatched types - --> $DIR/uninhabited.rs:35:5 + --> $DIR/coercions.rs:35:5 | LL | fn cannot_coerce_enum_with_empty_variants_to_anything(x: UninhabitedVariants) -> A { | - expected `A` because of return type diff --git a/src/test/ui/rfc-2008-non-exhaustive/uninhabited_same_crate.rs b/src/test/ui/rfc-2008-non-exhaustive/uninhabited/coercions_same_crate.rs similarity index 100% rename from src/test/ui/rfc-2008-non-exhaustive/uninhabited_same_crate.rs rename to src/test/ui/rfc-2008-non-exhaustive/uninhabited/coercions_same_crate.rs diff --git a/src/test/ui/rfc-2008-non-exhaustive/uninhabited_same_crate.stderr b/src/test/ui/rfc-2008-non-exhaustive/uninhabited/coercions_same_crate.stderr similarity index 90% rename from src/test/ui/rfc-2008-non-exhaustive/uninhabited_same_crate.stderr rename to src/test/ui/rfc-2008-non-exhaustive/uninhabited/coercions_same_crate.stderr index ea79e7105d5..8f6b709bb1f 100644 --- a/src/test/ui/rfc-2008-non-exhaustive/uninhabited_same_crate.stderr +++ b/src/test/ui/rfc-2008-non-exhaustive/uninhabited/coercions_same_crate.stderr @@ -1,5 +1,5 @@ error[E0308]: mismatched types - --> $DIR/uninhabited_same_crate.rs:31:5 + --> $DIR/coercions_same_crate.rs:31:5 | LL | fn cannot_coerce_empty_enum_to_anything(x: UninhabitedEnum) -> A { | - expected `A` because of return type @@ -10,7 +10,7 @@ LL | x found type `UninhabitedEnum` error[E0308]: mismatched types - --> $DIR/uninhabited_same_crate.rs:35:5 + --> $DIR/coercions_same_crate.rs:35:5 | LL | fn cannot_coerce_empty_tuple_struct_to_anything(x: UninhabitedTupleStruct) -> A { | - expected `A` because of return type @@ -21,7 +21,7 @@ LL | x found type `UninhabitedTupleStruct` error[E0308]: mismatched types - --> $DIR/uninhabited_same_crate.rs:39:5 + --> $DIR/coercions_same_crate.rs:39:5 | LL | fn cannot_coerce_empty_struct_to_anything(x: UninhabitedStruct) -> A { | - expected `A` because of return type @@ -32,7 +32,7 @@ LL | x found type `UninhabitedStruct` error[E0308]: mismatched types - --> $DIR/uninhabited_same_crate.rs:43:5 + --> $DIR/coercions_same_crate.rs:43:5 | LL | fn cannot_coerce_enum_with_empty_variants_to_anything(x: UninhabitedVariants) -> A { | - expected `A` because of return type diff --git a/src/test/ui/rfc-2008-non-exhaustive/uninhabited_match.rs b/src/test/ui/rfc-2008-non-exhaustive/uninhabited/match.rs similarity index 100% rename from src/test/ui/rfc-2008-non-exhaustive/uninhabited_match.rs rename to src/test/ui/rfc-2008-non-exhaustive/uninhabited/match.rs diff --git a/src/test/ui/rfc-2008-non-exhaustive/uninhabited_match.stderr b/src/test/ui/rfc-2008-non-exhaustive/uninhabited/match.stderr similarity index 90% rename from src/test/ui/rfc-2008-non-exhaustive/uninhabited_match.stderr rename to src/test/ui/rfc-2008-non-exhaustive/uninhabited/match.stderr index 3000e1b0930..356c6fba32d 100644 --- a/src/test/ui/rfc-2008-non-exhaustive/uninhabited_match.stderr +++ b/src/test/ui/rfc-2008-non-exhaustive/uninhabited/match.stderr @@ -1,5 +1,5 @@ error[E0004]: non-exhaustive patterns: type `uninhabited::UninhabitedEnum` is non-empty - --> $DIR/uninhabited_match.rs:16:11 + --> $DIR/match.rs:16:11 | LL | match x {} | ^ diff --git a/src/test/ui/rfc-2008-non-exhaustive/uninhabited_match_same_crate.rs b/src/test/ui/rfc-2008-non-exhaustive/uninhabited/match_same_crate.rs similarity index 100% rename from src/test/ui/rfc-2008-non-exhaustive/uninhabited_match_same_crate.rs rename to src/test/ui/rfc-2008-non-exhaustive/uninhabited/match_same_crate.rs diff --git a/src/test/ui/rfc-2008-non-exhaustive/uninhabited_match_with_exhaustive_patterns.rs b/src/test/ui/rfc-2008-non-exhaustive/uninhabited/match_with_exhaustive_patterns.rs similarity index 100% rename from src/test/ui/rfc-2008-non-exhaustive/uninhabited_match_with_exhaustive_patterns.rs rename to src/test/ui/rfc-2008-non-exhaustive/uninhabited/match_with_exhaustive_patterns.rs diff --git a/src/test/ui/rfc-2008-non-exhaustive/uninhabited_match_with_exhaustive_patterns.stderr b/src/test/ui/rfc-2008-non-exhaustive/uninhabited/match_with_exhaustive_patterns.stderr similarity index 84% rename from src/test/ui/rfc-2008-non-exhaustive/uninhabited_match_with_exhaustive_patterns.stderr rename to src/test/ui/rfc-2008-non-exhaustive/uninhabited/match_with_exhaustive_patterns.stderr index 73d9e689b55..ec2e9d0995b 100644 --- a/src/test/ui/rfc-2008-non-exhaustive/uninhabited_match_with_exhaustive_patterns.stderr +++ b/src/test/ui/rfc-2008-non-exhaustive/uninhabited/match_with_exhaustive_patterns.stderr @@ -1,5 +1,5 @@ error[E0004]: non-exhaustive patterns: type `uninhabited::UninhabitedEnum` is non-empty - --> $DIR/uninhabited_match_with_exhaustive_patterns.rs:19:11 + --> $DIR/match_with_exhaustive_patterns.rs:19:11 | LL | match x {} | ^ diff --git a/src/test/ui/rfc-2008-non-exhaustive/uninhabited_match_with_exhaustive_patterns_same_crate.rs b/src/test/ui/rfc-2008-non-exhaustive/uninhabited/match_with_exhaustive_patterns_same_crate.rs similarity index 100% rename from src/test/ui/rfc-2008-non-exhaustive/uninhabited_match_with_exhaustive_patterns_same_crate.rs rename to src/test/ui/rfc-2008-non-exhaustive/uninhabited/match_with_exhaustive_patterns_same_crate.rs diff --git a/src/test/ui/rfc-2008-non-exhaustive/uninhabited_patterns.rs b/src/test/ui/rfc-2008-non-exhaustive/uninhabited/patterns.rs similarity index 100% rename from src/test/ui/rfc-2008-non-exhaustive/uninhabited_patterns.rs rename to src/test/ui/rfc-2008-non-exhaustive/uninhabited/patterns.rs diff --git a/src/test/ui/rfc-2008-non-exhaustive/uninhabited_patterns_same_crate.rs b/src/test/ui/rfc-2008-non-exhaustive/uninhabited/patterns_same_crate.rs similarity index 100% rename from src/test/ui/rfc-2008-non-exhaustive/uninhabited_patterns_same_crate.rs rename to src/test/ui/rfc-2008-non-exhaustive/uninhabited/patterns_same_crate.rs diff --git a/src/test/ui/rfc-2008-non-exhaustive/uninhabited_patterns_same_crate.stderr b/src/test/ui/rfc-2008-non-exhaustive/uninhabited/patterns_same_crate.stderr similarity index 70% rename from src/test/ui/rfc-2008-non-exhaustive/uninhabited_patterns_same_crate.stderr rename to src/test/ui/rfc-2008-non-exhaustive/uninhabited/patterns_same_crate.stderr index 8e995632b2f..72f37d9a60b 100644 --- a/src/test/ui/rfc-2008-non-exhaustive/uninhabited_patterns_same_crate.stderr +++ b/src/test/ui/rfc-2008-non-exhaustive/uninhabited/patterns_same_crate.stderr @@ -1,35 +1,35 @@ error: unreachable pattern - --> $DIR/uninhabited_patterns_same_crate.rs:53:9 + --> $DIR/patterns_same_crate.rs:53:9 | LL | Some(_x) => (), | ^^^^^^^^ | note: lint level defined here - --> $DIR/uninhabited_patterns_same_crate.rs:1:9 + --> $DIR/patterns_same_crate.rs:1:9 | LL | #![deny(unreachable_patterns)] | ^^^^^^^^^^^^^^^^^^^^ error: unreachable pattern - --> $DIR/uninhabited_patterns_same_crate.rs:58:9 + --> $DIR/patterns_same_crate.rs:58:9 | LL | Some(_x) => (), | ^^^^^^^^ error: unreachable pattern - --> $DIR/uninhabited_patterns_same_crate.rs:62:15 + --> $DIR/patterns_same_crate.rs:62:15 | LL | while let PartiallyInhabitedVariants::Struct { x } = partially_inhabited_variant() { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: unreachable pattern - --> $DIR/uninhabited_patterns_same_crate.rs:66:15 + --> $DIR/patterns_same_crate.rs:66:15 | LL | while let Some(_x) = uninhabited_struct() { | ^^^^^^^^ error: unreachable pattern - --> $DIR/uninhabited_patterns_same_crate.rs:69:15 + --> $DIR/patterns_same_crate.rs:69:15 | LL | while let Some(_x) = uninhabited_tuple_struct() { | ^^^^^^^^ From 1f0fb0391caf232dacabdf73fbbb84f2452b25c1 Mon Sep 17 00:00:00 2001 From: David Wood Date: Sat, 4 May 2019 12:07:04 +0100 Subject: [PATCH 5/5] Add a bunch more tests. --- .../uninhabited/auxiliary/uninhabited.rs | 8 +++ .../uninhabited/indirect_match.rs | 36 +++++++++++ .../uninhabited/indirect_match.stderr | 35 +++++++++++ .../uninhabited/indirect_match_same_crate.rs | 52 ++++++++++++++++ .../indirect_match_same_crate.stderr | 59 +++++++++++++++++++ ...indirect_match_with_exhaustive_patterns.rs | 40 +++++++++++++ ...rect_match_with_exhaustive_patterns.stderr | 35 +++++++++++ ...tch_with_exhaustive_patterns_same_crate.rs | 58 ++++++++++++++++++ .../uninhabited/match.rs | 15 +++++ .../uninhabited/match.stderr | 28 ++++++++- .../uninhabited/match_same_crate.rs | 26 +++++++- .../uninhabited/match_same_crate.stderr | 49 +++++++++++++++ .../match_with_exhaustive_patterns.rs | 15 +++++ .../match_with_exhaustive_patterns.stderr | 28 ++++++++- ...tch_with_exhaustive_patterns_same_crate.rs | 27 +++++++++ 15 files changed, 506 insertions(+), 5 deletions(-) create mode 100644 src/test/ui/rfc-2008-non-exhaustive/uninhabited/indirect_match.rs create mode 100644 src/test/ui/rfc-2008-non-exhaustive/uninhabited/indirect_match.stderr create mode 100644 src/test/ui/rfc-2008-non-exhaustive/uninhabited/indirect_match_same_crate.rs create mode 100644 src/test/ui/rfc-2008-non-exhaustive/uninhabited/indirect_match_same_crate.stderr create mode 100644 src/test/ui/rfc-2008-non-exhaustive/uninhabited/indirect_match_with_exhaustive_patterns.rs create mode 100644 src/test/ui/rfc-2008-non-exhaustive/uninhabited/indirect_match_with_exhaustive_patterns.stderr create mode 100644 src/test/ui/rfc-2008-non-exhaustive/uninhabited/indirect_match_with_exhaustive_patterns_same_crate.rs create mode 100644 src/test/ui/rfc-2008-non-exhaustive/uninhabited/match_same_crate.stderr diff --git a/src/test/ui/rfc-2008-non-exhaustive/uninhabited/auxiliary/uninhabited.rs b/src/test/ui/rfc-2008-non-exhaustive/uninhabited/auxiliary/uninhabited.rs index a4b936e376d..8cb9a8cf1f6 100644 --- a/src/test/ui/rfc-2008-non-exhaustive/uninhabited/auxiliary/uninhabited.rs +++ b/src/test/ui/rfc-2008-non-exhaustive/uninhabited/auxiliary/uninhabited.rs @@ -23,3 +23,11 @@ pub enum PartiallyInhabitedVariants { Tuple(u8), #[non_exhaustive] Struct { x: ! } } + +pub struct IndirectUninhabitedEnum(UninhabitedEnum); + +pub struct IndirectUninhabitedStruct(UninhabitedStruct); + +pub struct IndirectUninhabitedTupleStruct(UninhabitedTupleStruct); + +pub struct IndirectUninhabitedVariants(UninhabitedVariants); diff --git a/src/test/ui/rfc-2008-non-exhaustive/uninhabited/indirect_match.rs b/src/test/ui/rfc-2008-non-exhaustive/uninhabited/indirect_match.rs new file mode 100644 index 00000000000..98a7fdbc504 --- /dev/null +++ b/src/test/ui/rfc-2008-non-exhaustive/uninhabited/indirect_match.rs @@ -0,0 +1,36 @@ +// aux-build:uninhabited.rs +#![feature(never_type)] + +extern crate uninhabited; + +use uninhabited::{ + IndirectUninhabitedEnum, + IndirectUninhabitedStruct, + IndirectUninhabitedTupleStruct, + IndirectUninhabitedVariants, +}; + +struct A; + +// This test checks that an empty match on a non-exhaustive uninhabited type through a level of +// indirection from an extern crate will not compile. + +fn cannot_empty_match_on_empty_enum_to_anything(x: IndirectUninhabitedEnum) -> A { + match x {} //~ ERROR non-exhaustive patterns +} + +fn cannot_empty_match_on_empty_struct_to_anything(x: IndirectUninhabitedStruct) -> A { + match x {} //~ ERROR non-exhaustive patterns +} + +fn cannot_empty_match_on_empty_tuple_struct_to_anything(x: IndirectUninhabitedTupleStruct) -> A { + match x {} //~ ERROR non-exhaustive patterns +} + +fn cannot_empty_match_on_enum_with_empty_variants_struct_to_anything( + x: IndirectUninhabitedVariants, +) -> A { + match x {} //~ ERROR non-exhaustive patterns +} + +fn main() {} diff --git a/src/test/ui/rfc-2008-non-exhaustive/uninhabited/indirect_match.stderr b/src/test/ui/rfc-2008-non-exhaustive/uninhabited/indirect_match.stderr new file mode 100644 index 00000000000..af82022e1da --- /dev/null +++ b/src/test/ui/rfc-2008-non-exhaustive/uninhabited/indirect_match.stderr @@ -0,0 +1,35 @@ +error[E0004]: non-exhaustive patterns: pattern `IndirectUninhabitedEnum` of type `uninhabited::IndirectUninhabitedEnum` is not handled + --> $DIR/indirect_match.rs:19:11 + | +LL | match x {} + | ^ + | + = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms + +error[E0004]: non-exhaustive patterns: pattern `IndirectUninhabitedStruct` of type `uninhabited::IndirectUninhabitedStruct` is not handled + --> $DIR/indirect_match.rs:23:11 + | +LL | match x {} + | ^ + | + = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms + +error[E0004]: non-exhaustive patterns: pattern `IndirectUninhabitedTupleStruct` of type `uninhabited::IndirectUninhabitedTupleStruct` is not handled + --> $DIR/indirect_match.rs:27:11 + | +LL | match x {} + | ^ + | + = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms + +error[E0004]: non-exhaustive patterns: pattern `IndirectUninhabitedVariants` of type `uninhabited::IndirectUninhabitedVariants` is not handled + --> $DIR/indirect_match.rs:33:11 + | +LL | match x {} + | ^ + | + = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms + +error: aborting due to 4 previous errors + +For more information about this error, try `rustc --explain E0004`. diff --git a/src/test/ui/rfc-2008-non-exhaustive/uninhabited/indirect_match_same_crate.rs b/src/test/ui/rfc-2008-non-exhaustive/uninhabited/indirect_match_same_crate.rs new file mode 100644 index 00000000000..3c8d495e12c --- /dev/null +++ b/src/test/ui/rfc-2008-non-exhaustive/uninhabited/indirect_match_same_crate.rs @@ -0,0 +1,52 @@ +#![feature(never_type)] +#![feature(non_exhaustive)] + +#[non_exhaustive] +pub enum UninhabitedEnum { +} + +#[non_exhaustive] +pub struct UninhabitedStruct { + _priv: !, +} + +#[non_exhaustive] +pub struct UninhabitedTupleStruct(!); + +pub enum UninhabitedVariants { + #[non_exhaustive] Tuple(!), + #[non_exhaustive] Struct { x: ! } +} + +pub struct IndirectUninhabitedEnum(UninhabitedEnum); + +pub struct IndirectUninhabitedStruct(UninhabitedStruct); + +pub struct IndirectUninhabitedTupleStruct(UninhabitedTupleStruct); + +pub struct IndirectUninhabitedVariants(UninhabitedVariants); + +struct A; + +// This test checks that an empty match on a non-exhaustive uninhabited type through a level of +// indirection from the defining crate will not compile without `#![feature(exhaustive_patterns)]`. + +fn cannot_empty_match_on_empty_enum_to_anything(x: IndirectUninhabitedEnum) -> A { + match x {} //~ ERROR non-exhaustive patterns +} + +fn cannot_empty_match_on_empty_struct_to_anything(x: IndirectUninhabitedStruct) -> A { + match x {} //~ ERROR non-exhaustive patterns +} + +fn cannot_empty_match_on_empty_tuple_struct_to_anything(x: IndirectUninhabitedTupleStruct) -> A { + match x {} //~ ERROR non-exhaustive patterns +} + +fn cannot_empty_match_on_enum_with_empty_variants_struct_to_anything( + x: IndirectUninhabitedVariants, +) -> A { + match x {} //~ ERROR non-exhaustive patterns +} + +fn main() {} diff --git a/src/test/ui/rfc-2008-non-exhaustive/uninhabited/indirect_match_same_crate.stderr b/src/test/ui/rfc-2008-non-exhaustive/uninhabited/indirect_match_same_crate.stderr new file mode 100644 index 00000000000..27b120792d6 --- /dev/null +++ b/src/test/ui/rfc-2008-non-exhaustive/uninhabited/indirect_match_same_crate.stderr @@ -0,0 +1,59 @@ +error[E0004]: non-exhaustive patterns: pattern `IndirectUninhabitedEnum` of type `IndirectUninhabitedEnum` is not handled + --> $DIR/indirect_match_same_crate.rs:35:11 + | +LL | pub struct IndirectUninhabitedEnum(UninhabitedEnum); + | ---------------------------------------------------- + | | | + | | variant not covered + | `IndirectUninhabitedEnum` defined here +... +LL | match x {} + | ^ + | + = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms + +error[E0004]: non-exhaustive patterns: pattern `IndirectUninhabitedStruct` of type `IndirectUninhabitedStruct` is not handled + --> $DIR/indirect_match_same_crate.rs:39:11 + | +LL | pub struct IndirectUninhabitedStruct(UninhabitedStruct); + | -------------------------------------------------------- + | | | + | | variant not covered + | `IndirectUninhabitedStruct` defined here +... +LL | match x {} + | ^ + | + = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms + +error[E0004]: non-exhaustive patterns: pattern `IndirectUninhabitedTupleStruct` of type `IndirectUninhabitedTupleStruct` is not handled + --> $DIR/indirect_match_same_crate.rs:43:11 + | +LL | pub struct IndirectUninhabitedTupleStruct(UninhabitedTupleStruct); + | ------------------------------------------------------------------ + | | | + | | variant not covered + | `IndirectUninhabitedTupleStruct` defined here +... +LL | match x {} + | ^ + | + = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms + +error[E0004]: non-exhaustive patterns: pattern `IndirectUninhabitedVariants` of type `IndirectUninhabitedVariants` is not handled + --> $DIR/indirect_match_same_crate.rs:49:11 + | +LL | pub struct IndirectUninhabitedVariants(UninhabitedVariants); + | ------------------------------------------------------------ + | | | + | | variant not covered + | `IndirectUninhabitedVariants` defined here +... +LL | match x {} + | ^ + | + = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms + +error: aborting due to 4 previous errors + +For more information about this error, try `rustc --explain E0004`. diff --git a/src/test/ui/rfc-2008-non-exhaustive/uninhabited/indirect_match_with_exhaustive_patterns.rs b/src/test/ui/rfc-2008-non-exhaustive/uninhabited/indirect_match_with_exhaustive_patterns.rs new file mode 100644 index 00000000000..be86519ecb1 --- /dev/null +++ b/src/test/ui/rfc-2008-non-exhaustive/uninhabited/indirect_match_with_exhaustive_patterns.rs @@ -0,0 +1,40 @@ +// aux-build:uninhabited.rs +#![deny(unreachable_patterns)] +#![feature(exhaustive_patterns)] +#![feature(never_type)] + +extern crate uninhabited; + +use uninhabited::{ + IndirectUninhabitedEnum, + IndirectUninhabitedStruct, + IndirectUninhabitedTupleStruct, + IndirectUninhabitedVariants, +}; + +struct A; + +// This test checks that an empty match on a non-exhaustive uninhabited type through a level of +// indirection from an extern crate will not compile. In particular, this enables the +// `exhaustive_patterns` feature as this can change the branch used in the compiler to determine +// this. + +fn cannot_empty_match_on_empty_enum_to_anything(x: IndirectUninhabitedEnum) -> A { + match x {} //~ ERROR non-exhaustive patterns +} + +fn cannot_empty_match_on_empty_struct_to_anything(x: IndirectUninhabitedStruct) -> A { + match x {} //~ ERROR non-exhaustive patterns +} + +fn cannot_empty_match_on_empty_tuple_struct_to_anything(x: IndirectUninhabitedTupleStruct) -> A { + match x {} //~ ERROR non-exhaustive patterns +} + +fn cannot_empty_match_on_enum_with_empty_variants_struct_to_anything( + x: IndirectUninhabitedVariants, +) -> A { + match x {} //~ ERROR non-exhaustive patterns +} + +fn main() {} diff --git a/src/test/ui/rfc-2008-non-exhaustive/uninhabited/indirect_match_with_exhaustive_patterns.stderr b/src/test/ui/rfc-2008-non-exhaustive/uninhabited/indirect_match_with_exhaustive_patterns.stderr new file mode 100644 index 00000000000..17a8d010072 --- /dev/null +++ b/src/test/ui/rfc-2008-non-exhaustive/uninhabited/indirect_match_with_exhaustive_patterns.stderr @@ -0,0 +1,35 @@ +error[E0004]: non-exhaustive patterns: type `uninhabited::IndirectUninhabitedEnum` is non-empty + --> $DIR/indirect_match_with_exhaustive_patterns.rs:23:11 + | +LL | match x {} + | ^ + | + = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms + +error[E0004]: non-exhaustive patterns: type `uninhabited::IndirectUninhabitedStruct` is non-empty + --> $DIR/indirect_match_with_exhaustive_patterns.rs:27:11 + | +LL | match x {} + | ^ + | + = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms + +error[E0004]: non-exhaustive patterns: type `uninhabited::IndirectUninhabitedTupleStruct` is non-empty + --> $DIR/indirect_match_with_exhaustive_patterns.rs:31:11 + | +LL | match x {} + | ^ + | + = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms + +error[E0004]: non-exhaustive patterns: type `uninhabited::IndirectUninhabitedVariants` is non-empty + --> $DIR/indirect_match_with_exhaustive_patterns.rs:37:11 + | +LL | match x {} + | ^ + | + = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms + +error: aborting due to 4 previous errors + +For more information about this error, try `rustc --explain E0004`. diff --git a/src/test/ui/rfc-2008-non-exhaustive/uninhabited/indirect_match_with_exhaustive_patterns_same_crate.rs b/src/test/ui/rfc-2008-non-exhaustive/uninhabited/indirect_match_with_exhaustive_patterns_same_crate.rs new file mode 100644 index 00000000000..5dbd38e07df --- /dev/null +++ b/src/test/ui/rfc-2008-non-exhaustive/uninhabited/indirect_match_with_exhaustive_patterns_same_crate.rs @@ -0,0 +1,58 @@ +// compile-pass +// skip-codegen +#![deny(unreachable_patterns)] +#![feature(exhaustive_patterns)] +#![feature(never_type)] +#![feature(non_exhaustive)] + +#[non_exhaustive] +pub enum UninhabitedEnum { +} + +#[non_exhaustive] +pub struct UninhabitedStruct { + _priv: !, +} + +#[non_exhaustive] +pub struct UninhabitedTupleStruct(!); + +pub enum UninhabitedVariants { + #[non_exhaustive] Tuple(!), + #[non_exhaustive] Struct { x: ! } +} + +pub struct IndirectUninhabitedEnum(UninhabitedEnum); + +pub struct IndirectUninhabitedStruct(UninhabitedStruct); + +pub struct IndirectUninhabitedTupleStruct(UninhabitedTupleStruct); + +pub struct IndirectUninhabitedVariants(UninhabitedVariants); + +struct A; + +// This test checks that an empty match on a non-exhaustive uninhabited type from the defining crate +// will compile. In particular, this enables the `exhaustive_patterns` feature as this can +// change the branch used in the compiler to determine this. +// Codegen is skipped because tests with long names can cause issues on Windows CI, see #60648. + +fn cannot_empty_match_on_empty_enum_to_anything(x: IndirectUninhabitedEnum) -> A { + match x {} +} + +fn cannot_empty_match_on_empty_struct_to_anything(x: IndirectUninhabitedStruct) -> A { + match x {} +} + +fn cannot_empty_match_on_empty_tuple_struct_to_anything(x: IndirectUninhabitedTupleStruct) -> A { + match x {} +} + +fn cannot_empty_match_on_enum_with_empty_variants_struct_to_anything( + x: IndirectUninhabitedVariants, +) -> A { + match x {} +} + +fn main() {} diff --git a/src/test/ui/rfc-2008-non-exhaustive/uninhabited/match.rs b/src/test/ui/rfc-2008-non-exhaustive/uninhabited/match.rs index 0166b2e46cb..e54098d4d48 100644 --- a/src/test/ui/rfc-2008-non-exhaustive/uninhabited/match.rs +++ b/src/test/ui/rfc-2008-non-exhaustive/uninhabited/match.rs @@ -5,6 +5,9 @@ extern crate uninhabited; use uninhabited::{ UninhabitedEnum, + UninhabitedStruct, + UninhabitedTupleStruct, + UninhabitedVariants, }; struct A; @@ -16,4 +19,16 @@ fn cannot_empty_match_on_empty_enum_to_anything(x: UninhabitedEnum) -> A { match x {} //~ ERROR non-exhaustive patterns } +fn cannot_empty_match_on_empty_struct_to_anything(x: UninhabitedStruct) -> A { + match x {} //~ ERROR non-exhaustive patterns +} + +fn cannot_empty_match_on_empty_tuple_struct_to_anything(x: UninhabitedTupleStruct) -> A { + match x {} //~ ERROR non-exhaustive patterns +} + +fn cannot_empty_match_on_enum_with_empty_variants_struct_to_anything(x: UninhabitedVariants) -> A { + match x {} //~ ERROR non-exhaustive patterns +} + fn main() {} diff --git a/src/test/ui/rfc-2008-non-exhaustive/uninhabited/match.stderr b/src/test/ui/rfc-2008-non-exhaustive/uninhabited/match.stderr index 356c6fba32d..de39688f45a 100644 --- a/src/test/ui/rfc-2008-non-exhaustive/uninhabited/match.stderr +++ b/src/test/ui/rfc-2008-non-exhaustive/uninhabited/match.stderr @@ -1,11 +1,35 @@ error[E0004]: non-exhaustive patterns: type `uninhabited::UninhabitedEnum` is non-empty - --> $DIR/match.rs:16:11 + --> $DIR/match.rs:19:11 | LL | match x {} | ^ | = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms -error: aborting due to previous error +error[E0004]: non-exhaustive patterns: pattern `UninhabitedStruct` of type `uninhabited::UninhabitedStruct` is not handled + --> $DIR/match.rs:23:11 + | +LL | match x {} + | ^ + | + = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms + +error[E0004]: non-exhaustive patterns: pattern `UninhabitedTupleStruct` of type `uninhabited::UninhabitedTupleStruct` is not handled + --> $DIR/match.rs:27:11 + | +LL | match x {} + | ^ + | + = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms + +error[E0004]: non-exhaustive patterns: multiple patterns of type `uninhabited::UninhabitedVariants` are not handled + --> $DIR/match.rs:31:11 + | +LL | match x {} + | ^ + | + = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms + +error: aborting due to 4 previous errors For more information about this error, try `rustc --explain E0004`. diff --git a/src/test/ui/rfc-2008-non-exhaustive/uninhabited/match_same_crate.rs b/src/test/ui/rfc-2008-non-exhaustive/uninhabited/match_same_crate.rs index d8b1c3810f3..6405dd3bd65 100644 --- a/src/test/ui/rfc-2008-non-exhaustive/uninhabited/match_same_crate.rs +++ b/src/test/ui/rfc-2008-non-exhaustive/uninhabited/match_same_crate.rs @@ -1,4 +1,3 @@ -// compile-pass #![feature(never_type)] #![feature(non_exhaustive)] @@ -6,6 +5,19 @@ pub enum UninhabitedEnum { } +#[non_exhaustive] +pub struct UninhabitedStruct { + _priv: !, +} + +#[non_exhaustive] +pub struct UninhabitedTupleStruct(!); + +pub enum UninhabitedVariants { + #[non_exhaustive] Tuple(!), + #[non_exhaustive] Struct { x: ! } +} + struct A; // This test checks that an empty match on a non-exhaustive uninhabited type from the defining crate @@ -15,4 +27,16 @@ fn cannot_empty_match_on_empty_enum_to_anything(x: UninhabitedEnum) -> A { match x {} } +fn cannot_empty_match_on_empty_struct_to_anything(x: UninhabitedStruct) -> A { + match x {} //~ ERROR non-exhaustive patterns +} + +fn cannot_empty_match_on_empty_tuple_struct_to_anything(x: UninhabitedTupleStruct) -> A { + match x {} //~ ERROR non-exhaustive patterns +} + +fn cannot_empty_match_on_enum_with_empty_variants_struct_to_anything(x: UninhabitedVariants) -> A { + match x {} //~ ERROR non-exhaustive patterns +} + fn main() {} diff --git a/src/test/ui/rfc-2008-non-exhaustive/uninhabited/match_same_crate.stderr b/src/test/ui/rfc-2008-non-exhaustive/uninhabited/match_same_crate.stderr new file mode 100644 index 00000000000..410285a39a9 --- /dev/null +++ b/src/test/ui/rfc-2008-non-exhaustive/uninhabited/match_same_crate.stderr @@ -0,0 +1,49 @@ +error[E0004]: non-exhaustive patterns: pattern `UninhabitedStruct` of type `UninhabitedStruct` is not handled + --> $DIR/match_same_crate.rs:31:11 + | +LL | pub struct UninhabitedStruct { + | - ----------------- variant not covered + | _| + | | +LL | | _priv: !, +LL | | } + | |_- `UninhabitedStruct` defined here +... +LL | match x {} + | ^ + | + = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms + +error[E0004]: non-exhaustive patterns: pattern `UninhabitedTupleStruct` of type `UninhabitedTupleStruct` is not handled + --> $DIR/match_same_crate.rs:35:11 + | +LL | pub struct UninhabitedTupleStruct(!); + | ------------------------------------- + | | | + | | variant not covered + | `UninhabitedTupleStruct` defined here +... +LL | match x {} + | ^ + | + = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms + +error[E0004]: non-exhaustive patterns: multiple patterns of type `UninhabitedVariants` are not handled + --> $DIR/match_same_crate.rs:39:11 + | +LL | / pub enum UninhabitedVariants { +LL | | #[non_exhaustive] Tuple(!), + | | ----- variant not covered +LL | | #[non_exhaustive] Struct { x: ! } + | | ------ variant not covered +LL | | } + | |_- `UninhabitedVariants` defined here +... +LL | match x {} + | ^ + | + = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms + +error: aborting due to 3 previous errors + +For more information about this error, try `rustc --explain E0004`. diff --git a/src/test/ui/rfc-2008-non-exhaustive/uninhabited/match_with_exhaustive_patterns.rs b/src/test/ui/rfc-2008-non-exhaustive/uninhabited/match_with_exhaustive_patterns.rs index d82010158cc..900dfff652e 100644 --- a/src/test/ui/rfc-2008-non-exhaustive/uninhabited/match_with_exhaustive_patterns.rs +++ b/src/test/ui/rfc-2008-non-exhaustive/uninhabited/match_with_exhaustive_patterns.rs @@ -7,6 +7,9 @@ extern crate uninhabited; use uninhabited::{ UninhabitedEnum, + UninhabitedStruct, + UninhabitedTupleStruct, + UninhabitedVariants, }; struct A; @@ -19,4 +22,16 @@ fn cannot_empty_match_on_empty_enum_to_anything(x: UninhabitedEnum) -> A { match x {} //~ ERROR non-exhaustive patterns } +fn cannot_empty_match_on_empty_struct_to_anything(x: UninhabitedStruct) -> A { + match x {} //~ ERROR non-exhaustive patterns +} + +fn cannot_empty_match_on_empty_tuple_struct_to_anything(x: UninhabitedTupleStruct) -> A { + match x {} //~ ERROR non-exhaustive patterns +} + +fn cannot_empty_match_on_enum_with_empty_variants_struct_to_anything(x: UninhabitedVariants) -> A { + match x {} //~ ERROR non-exhaustive patterns +} + fn main() {} diff --git a/src/test/ui/rfc-2008-non-exhaustive/uninhabited/match_with_exhaustive_patterns.stderr b/src/test/ui/rfc-2008-non-exhaustive/uninhabited/match_with_exhaustive_patterns.stderr index ec2e9d0995b..48a888bc50b 100644 --- a/src/test/ui/rfc-2008-non-exhaustive/uninhabited/match_with_exhaustive_patterns.stderr +++ b/src/test/ui/rfc-2008-non-exhaustive/uninhabited/match_with_exhaustive_patterns.stderr @@ -1,11 +1,35 @@ error[E0004]: non-exhaustive patterns: type `uninhabited::UninhabitedEnum` is non-empty - --> $DIR/match_with_exhaustive_patterns.rs:19:11 + --> $DIR/match_with_exhaustive_patterns.rs:22:11 | LL | match x {} | ^ | = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms -error: aborting due to previous error +error[E0004]: non-exhaustive patterns: type `uninhabited::UninhabitedStruct` is non-empty + --> $DIR/match_with_exhaustive_patterns.rs:26:11 + | +LL | match x {} + | ^ + | + = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms + +error[E0004]: non-exhaustive patterns: type `uninhabited::UninhabitedTupleStruct` is non-empty + --> $DIR/match_with_exhaustive_patterns.rs:30:11 + | +LL | match x {} + | ^ + | + = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms + +error[E0004]: non-exhaustive patterns: type `uninhabited::UninhabitedVariants` is non-empty + --> $DIR/match_with_exhaustive_patterns.rs:34:11 + | +LL | match x {} + | ^ + | + = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms + +error: aborting due to 4 previous errors For more information about this error, try `rustc --explain E0004`. diff --git a/src/test/ui/rfc-2008-non-exhaustive/uninhabited/match_with_exhaustive_patterns_same_crate.rs b/src/test/ui/rfc-2008-non-exhaustive/uninhabited/match_with_exhaustive_patterns_same_crate.rs index da814a70a75..74922d4bcb5 100644 --- a/src/test/ui/rfc-2008-non-exhaustive/uninhabited/match_with_exhaustive_patterns_same_crate.rs +++ b/src/test/ui/rfc-2008-non-exhaustive/uninhabited/match_with_exhaustive_patterns_same_crate.rs @@ -1,4 +1,5 @@ // compile-pass +// skip-codegen #![deny(unreachable_patterns)] #![feature(exhaustive_patterns)] #![feature(never_type)] @@ -8,14 +9,40 @@ pub enum UninhabitedEnum { } +#[non_exhaustive] +pub struct UninhabitedStruct { + _priv: !, +} + +#[non_exhaustive] +pub struct UninhabitedTupleStruct(!); + +pub enum UninhabitedVariants { + #[non_exhaustive] Tuple(!), + #[non_exhaustive] Struct { x: ! } +} + struct A; // This test checks that an empty match on a non-exhaustive uninhabited type from the defining crate // will compile. In particular, this enables the `exhaustive_patterns` feature as this can // change the branch used in the compiler to determine this. +// Codegen is skipped because tests with long names can cause issues on Windows CI, see #60648. fn cannot_empty_match_on_empty_enum_to_anything(x: UninhabitedEnum) -> A { match x {} } +fn cannot_empty_match_on_empty_struct_to_anything(x: UninhabitedStruct) -> A { + match x {} +} + +fn cannot_empty_match_on_empty_tuple_struct_to_anything(x: UninhabitedTupleStruct) -> A { + match x {} +} + +fn cannot_empty_match_on_enum_with_empty_variants_struct_to_anything(x: UninhabitedVariants) -> A { + match x {} +} + fn main() {}