From 6f6a6bc710e538741aa06d40df6492471e4be8af Mon Sep 17 00:00:00 2001 From: Nadrieril Date: Sat, 10 Aug 2024 19:06:26 +0200 Subject: [PATCH] Non-exhaustive structs may be empty --- .../rustc_middle/src/ty/inhabitedness/mod.rs | 4 -- compiler/rustc_pattern_analysis/src/rustc.rs | 8 +-- .../uninhabited/auxiliary/uninhabited.rs | 10 ++- .../uninhabited/indirect_match.stderr | 8 +-- ...rect_match_with_exhaustive_patterns.stderr | 8 +-- .../issue-65157-repeated-match-arm.rs | 9 +-- .../issue-65157-repeated-match-arm.stderr | 19 ++++-- .../uninhabited/match.rs | 21 +++--- .../uninhabited/match.stderr | 66 ++++--------------- .../match_with_exhaustive_patterns.rs | 26 ++++---- .../match_with_exhaustive_patterns.stderr | 65 +----------------- ...tch_with_exhaustive_patterns_same_crate.rs | 21 +++--- .../uninhabited/patterns.rs | 25 +++---- .../uninhabited/patterns.stderr | 39 +++++++++++ .../uninhabited/patterns_same_crate.rs | 5 +- .../uninhabited/patterns_same_crate.stderr | 10 +-- 16 files changed, 136 insertions(+), 208 deletions(-) create mode 100644 tests/ui/rfcs/rfc-2008-non-exhaustive/uninhabited/patterns.stderr diff --git a/compiler/rustc_middle/src/ty/inhabitedness/mod.rs b/compiler/rustc_middle/src/ty/inhabitedness/mod.rs index 698104b0462..dd00db8635f 100644 --- a/compiler/rustc_middle/src/ty/inhabitedness/mod.rs +++ b/compiler/rustc_middle/src/ty/inhabitedness/mod.rs @@ -81,10 +81,6 @@ pub fn inhabited_predicate( adt: ty::AdtDef<'_>, ) -> InhabitedPredicate<'tcx> { debug_assert!(!adt.is_union()); - if self.is_field_list_non_exhaustive() && !self.def_id.is_local() { - // Non-exhaustive variants from other crates are always considered inhabited. - return InhabitedPredicate::True; - } InhabitedPredicate::all( tcx, self.fields.iter().map(|field| { diff --git a/compiler/rustc_pattern_analysis/src/rustc.rs b/compiler/rustc_pattern_analysis/src/rustc.rs index d7885e05a2f..6c09f97bfe7 100644 --- a/compiler/rustc_pattern_analysis/src/rustc.rs +++ b/compiler/rustc_pattern_analysis/src/rustc.rs @@ -229,17 +229,11 @@ fn reveal_and_alloc<'a, 'tcx>( } else { let variant = &adt.variant(RustcPatCtxt::variant_index_for_adt(&ctor, *adt)); - - // In the cases of either a `#[non_exhaustive]` field list or a non-public - // field, we skip uninhabited fields in order not to reveal the - // uninhabitedness of the whole variant. - let is_non_exhaustive = - variant.is_field_list_non_exhaustive() && !adt.did().is_local(); let tys = cx.variant_sub_tys(ty, variant).map(|(field, ty)| { let is_visible = adt.is_enum() || field.vis.is_accessible_from(cx.module, cx.tcx); let is_uninhabited = cx.is_uninhabited(*ty); - let skip = is_uninhabited && (!is_visible || is_non_exhaustive); + let skip = is_uninhabited && !is_visible; (ty, PrivateUninhabitedField(skip)) }); cx.dropless_arena.alloc_from_iter(tys) diff --git a/tests/ui/rfcs/rfc-2008-non-exhaustive/uninhabited/auxiliary/uninhabited.rs b/tests/ui/rfcs/rfc-2008-non-exhaustive/uninhabited/auxiliary/uninhabited.rs index a2735d4cbfb..e1799761b69 100644 --- a/tests/ui/rfcs/rfc-2008-non-exhaustive/uninhabited/auxiliary/uninhabited.rs +++ b/tests/ui/rfcs/rfc-2008-non-exhaustive/uninhabited/auxiliary/uninhabited.rs @@ -7,11 +7,17 @@ pub enum UninhabitedEnum { #[non_exhaustive] pub struct UninhabitedStruct { - _priv: !, + pub never: !, + _priv: (), } #[non_exhaustive] -pub struct UninhabitedTupleStruct(!); +pub struct PrivatelyUninhabitedStruct { + never: !, +} + +#[non_exhaustive] +pub struct UninhabitedTupleStruct(pub !); pub enum UninhabitedVariants { #[non_exhaustive] Tuple(!), diff --git a/tests/ui/rfcs/rfc-2008-non-exhaustive/uninhabited/indirect_match.stderr b/tests/ui/rfcs/rfc-2008-non-exhaustive/uninhabited/indirect_match.stderr index 66e93291c72..f332e6deeb8 100644 --- a/tests/ui/rfcs/rfc-2008-non-exhaustive/uninhabited/indirect_match.stderr +++ b/tests/ui/rfcs/rfc-2008-non-exhaustive/uninhabited/indirect_match.stderr @@ -5,7 +5,7 @@ LL | match x {} | ^ | note: `IndirectUninhabitedEnum` defined here - --> $DIR/auxiliary/uninhabited.rs:26:1 + --> $DIR/auxiliary/uninhabited.rs:32:1 | LL | pub struct IndirectUninhabitedEnum(UninhabitedEnum); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -24,7 +24,7 @@ LL | match x {} | ^ | note: `IndirectUninhabitedStruct` defined here - --> $DIR/auxiliary/uninhabited.rs:28:1 + --> $DIR/auxiliary/uninhabited.rs:34:1 | LL | pub struct IndirectUninhabitedStruct(UninhabitedStruct); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -43,7 +43,7 @@ LL | match x {} | ^ | note: `IndirectUninhabitedTupleStruct` defined here - --> $DIR/auxiliary/uninhabited.rs:30:1 + --> $DIR/auxiliary/uninhabited.rs:36:1 | LL | pub struct IndirectUninhabitedTupleStruct(UninhabitedTupleStruct); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -62,7 +62,7 @@ LL | match x {} | ^ | note: `IndirectUninhabitedVariants` defined here - --> $DIR/auxiliary/uninhabited.rs:32:1 + --> $DIR/auxiliary/uninhabited.rs:38:1 | LL | pub struct IndirectUninhabitedVariants(UninhabitedVariants); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ diff --git a/tests/ui/rfcs/rfc-2008-non-exhaustive/uninhabited/indirect_match_with_exhaustive_patterns.stderr b/tests/ui/rfcs/rfc-2008-non-exhaustive/uninhabited/indirect_match_with_exhaustive_patterns.stderr index 745b196a0e3..48f3857bfa7 100644 --- a/tests/ui/rfcs/rfc-2008-non-exhaustive/uninhabited/indirect_match_with_exhaustive_patterns.stderr +++ b/tests/ui/rfcs/rfc-2008-non-exhaustive/uninhabited/indirect_match_with_exhaustive_patterns.stderr @@ -5,7 +5,7 @@ LL | match x {} | ^ | note: `IndirectUninhabitedEnum` defined here - --> $DIR/auxiliary/uninhabited.rs:26:1 + --> $DIR/auxiliary/uninhabited.rs:32:1 | LL | pub struct IndirectUninhabitedEnum(UninhabitedEnum); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -24,7 +24,7 @@ LL | match x {} | ^ | note: `IndirectUninhabitedStruct` defined here - --> $DIR/auxiliary/uninhabited.rs:28:1 + --> $DIR/auxiliary/uninhabited.rs:34:1 | LL | pub struct IndirectUninhabitedStruct(UninhabitedStruct); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -43,7 +43,7 @@ LL | match x {} | ^ | note: `IndirectUninhabitedTupleStruct` defined here - --> $DIR/auxiliary/uninhabited.rs:30:1 + --> $DIR/auxiliary/uninhabited.rs:36:1 | LL | pub struct IndirectUninhabitedTupleStruct(UninhabitedTupleStruct); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -62,7 +62,7 @@ LL | match x {} | ^ | note: `IndirectUninhabitedVariants` defined here - --> $DIR/auxiliary/uninhabited.rs:32:1 + --> $DIR/auxiliary/uninhabited.rs:38:1 | LL | pub struct IndirectUninhabitedVariants(UninhabitedVariants); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ diff --git a/tests/ui/rfcs/rfc-2008-non-exhaustive/uninhabited/issue-65157-repeated-match-arm.rs b/tests/ui/rfcs/rfc-2008-non-exhaustive/uninhabited/issue-65157-repeated-match-arm.rs index fd77fab8738..6bee019e897 100644 --- a/tests/ui/rfcs/rfc-2008-non-exhaustive/uninhabited/issue-65157-repeated-match-arm.rs +++ b/tests/ui/rfcs/rfc-2008-non-exhaustive/uninhabited/issue-65157-repeated-match-arm.rs @@ -11,11 +11,12 @@ pub fn foo(x: PartiallyInhabitedVariants) { match x { - PartiallyInhabitedVariants::Struct { .. } => {}, - PartiallyInhabitedVariants::Struct { .. } => {}, + PartiallyInhabitedVariants::Struct { .. } => {} //~^ ERROR unreachable pattern - _ => {}, + PartiallyInhabitedVariants::Struct { .. } => {} + //~^ ERROR unreachable pattern + _ => {} } } -fn main() { } +fn main() {} diff --git a/tests/ui/rfcs/rfc-2008-non-exhaustive/uninhabited/issue-65157-repeated-match-arm.stderr b/tests/ui/rfcs/rfc-2008-non-exhaustive/uninhabited/issue-65157-repeated-match-arm.stderr index 956725fc10e..4fa53101a55 100644 --- a/tests/ui/rfcs/rfc-2008-non-exhaustive/uninhabited/issue-65157-repeated-match-arm.stderr +++ b/tests/ui/rfcs/rfc-2008-non-exhaustive/uninhabited/issue-65157-repeated-match-arm.stderr @@ -1,16 +1,23 @@ error: unreachable pattern - --> $DIR/issue-65157-repeated-match-arm.rs:15:9 + --> $DIR/issue-65157-repeated-match-arm.rs:14:9 | -LL | PartiallyInhabitedVariants::Struct { .. } => {}, - | ----------------------------------------- matches all the relevant values -LL | PartiallyInhabitedVariants::Struct { .. } => {}, - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ no value can reach this +LL | PartiallyInhabitedVariants::Struct { .. } => {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ matches no values because `PartiallyInhabitedVariants` is uninhabited | + = note: to learn more about uninhabited types, see https://doc.rust-lang.org/nomicon/exotic-sizes.html#empty-types note: the lint level is defined here --> $DIR/issue-65157-repeated-match-arm.rs:2:9 | LL | #![deny(unreachable_patterns)] | ^^^^^^^^^^^^^^^^^^^^ -error: aborting due to 1 previous error +error: unreachable pattern + --> $DIR/issue-65157-repeated-match-arm.rs:16:9 + | +LL | PartiallyInhabitedVariants::Struct { .. } => {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ matches no values because `PartiallyInhabitedVariants` is uninhabited + | + = note: to learn more about uninhabited types, see https://doc.rust-lang.org/nomicon/exotic-sizes.html#empty-types + +error: aborting due to 2 previous errors diff --git a/tests/ui/rfcs/rfc-2008-non-exhaustive/uninhabited/match.rs b/tests/ui/rfcs/rfc-2008-non-exhaustive/uninhabited/match.rs index c330f3aa05c..58d7bbd2c17 100644 --- a/tests/ui/rfcs/rfc-2008-non-exhaustive/uninhabited/match.rs +++ b/tests/ui/rfcs/rfc-2008-non-exhaustive/uninhabited/match.rs @@ -3,12 +3,7 @@ extern crate uninhabited; -use uninhabited::{ - UninhabitedEnum, - UninhabitedStruct, - UninhabitedTupleStruct, - UninhabitedVariants, -}; +use uninhabited::*; struct A; @@ -19,16 +14,20 @@ 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 { +fn empty_match_on_empty_struct(x: UninhabitedStruct) -> A { + match x {} +} + +fn cannot_empty_match_on_privately_empty_struct(x: PrivatelyUninhabitedStruct) -> 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 empty_match_on_empty_tuple_struct(x: UninhabitedTupleStruct) -> A { + match x {} } -fn cannot_empty_match_on_enum_with_empty_variants_struct_to_anything(x: UninhabitedVariants) -> A { - match x {} //~ ERROR non-exhaustive patterns +fn empty_match_on_enum_with_empty_variants_struct(x: UninhabitedVariants) -> A { + match x {} } fn main() {} diff --git a/tests/ui/rfcs/rfc-2008-non-exhaustive/uninhabited/match.stderr b/tests/ui/rfcs/rfc-2008-non-exhaustive/uninhabited/match.stderr index c125756a646..0232e7106aa 100644 --- a/tests/ui/rfcs/rfc-2008-non-exhaustive/uninhabited/match.stderr +++ b/tests/ui/rfcs/rfc-2008-non-exhaustive/uninhabited/match.stderr @@ -1,15 +1,15 @@ -error[E0004]: non-exhaustive patterns: type `UninhabitedEnum` is non-empty - --> $DIR/match.rs:19:11 +error[E0004]: non-exhaustive patterns: type `uninhabited::UninhabitedEnum` is non-empty + --> $DIR/match.rs:14:11 | LL | match x {} | ^ | -note: `UninhabitedEnum` defined here +note: `uninhabited::UninhabitedEnum` defined here --> $DIR/auxiliary/uninhabited.rs:5:1 | LL | pub enum UninhabitedEnum { | ^^^^^^^^^^^^^^^^^^^^^^^^ - = note: the matched value is of type `UninhabitedEnum`, which is marked as non-exhaustive + = note: the matched value is of type `uninhabited::UninhabitedEnum`, which is marked as non-exhaustive help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern as shown | LL ~ match x { @@ -17,18 +17,18 @@ LL + _ => todo!(), LL ~ } | -error[E0004]: non-exhaustive patterns: type `UninhabitedStruct` is non-empty - --> $DIR/match.rs:23:11 +error[E0004]: non-exhaustive patterns: type `uninhabited::PrivatelyUninhabitedStruct` is non-empty + --> $DIR/match.rs:22:11 | LL | match x {} | ^ | -note: `UninhabitedStruct` defined here - --> $DIR/auxiliary/uninhabited.rs:9:1 +note: `uninhabited::PrivatelyUninhabitedStruct` defined here + --> $DIR/auxiliary/uninhabited.rs:15:1 | -LL | pub struct UninhabitedStruct { - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - = note: the matched value is of type `UninhabitedStruct` +LL | pub struct PrivatelyUninhabitedStruct { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + = note: the matched value is of type `uninhabited::PrivatelyUninhabitedStruct` help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern as shown | LL ~ match x { @@ -36,48 +36,6 @@ LL + _ => todo!(), LL ~ } | -error[E0004]: non-exhaustive patterns: type `UninhabitedTupleStruct` is non-empty - --> $DIR/match.rs:27:11 - | -LL | match x {} - | ^ - | -note: `UninhabitedTupleStruct` defined here - --> $DIR/auxiliary/uninhabited.rs:14:1 - | -LL | pub struct UninhabitedTupleStruct(!); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - = note: the matched value is of type `UninhabitedTupleStruct` -help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern as shown - | -LL ~ match x { -LL + _ => todo!(), -LL ~ } - | - -error[E0004]: non-exhaustive patterns: `UninhabitedVariants::Tuple(_)` and `UninhabitedVariants::Struct { .. }` not covered - --> $DIR/match.rs:31:11 - | -LL | match x {} - | ^ patterns `UninhabitedVariants::Tuple(_)` and `UninhabitedVariants::Struct { .. }` not covered - | -note: `UninhabitedVariants` defined here - --> $DIR/auxiliary/uninhabited.rs:16:1 - | -LL | pub enum UninhabitedVariants { - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -LL | #[non_exhaustive] Tuple(!), - | ----- not covered -LL | #[non_exhaustive] Struct { x: ! } - | ------ not covered - = note: the matched value is of type `UninhabitedVariants` -help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern, a match arm with multiple or-patterns as shown, or multiple match arms - | -LL ~ match x { -LL + UninhabitedVariants::Tuple(_) | UninhabitedVariants::Struct { .. } => todo!(), -LL ~ } - | - -error: aborting due to 4 previous errors +error: aborting due to 2 previous errors For more information about this error, try `rustc --explain E0004`. diff --git a/tests/ui/rfcs/rfc-2008-non-exhaustive/uninhabited/match_with_exhaustive_patterns.rs b/tests/ui/rfcs/rfc-2008-non-exhaustive/uninhabited/match_with_exhaustive_patterns.rs index 108cac7099e..c214581549c 100644 --- a/tests/ui/rfcs/rfc-2008-non-exhaustive/uninhabited/match_with_exhaustive_patterns.rs +++ b/tests/ui/rfcs/rfc-2008-non-exhaustive/uninhabited/match_with_exhaustive_patterns.rs @@ -5,32 +5,28 @@ extern crate uninhabited; use uninhabited::{ - UninhabitedEnum, - UninhabitedStruct, - UninhabitedTupleStruct, - UninhabitedVariants, + UninhabitedEnum, UninhabitedStruct, UninhabitedTupleStruct, UninhabitedVariants, }; 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 { +// This test checks that non-exhaustive enums are never considered uninhabited outside their +// defining crate, and non-exhaustive structs are considered uninhabited the same way as normal +// ones. +fn cannot_empty_match_on_non_exhaustive_empty_enum(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 empty_match_on_empty_struct(x: UninhabitedStruct) -> A { + match x {} } -fn cannot_empty_match_on_empty_tuple_struct_to_anything(x: UninhabitedTupleStruct) -> A { - match x {} //~ ERROR non-exhaustive patterns +fn empty_match_on_empty_tuple_struct(x: UninhabitedTupleStruct) -> A { + match x {} } -fn cannot_empty_match_on_enum_with_empty_variants_struct_to_anything(x: UninhabitedVariants) -> A { - match x {} //~ ERROR non-exhaustive patterns +fn empty_match_on_enum_with_empty_variants_struct(x: UninhabitedVariants) -> A { + match x {} } fn main() {} diff --git a/tests/ui/rfcs/rfc-2008-non-exhaustive/uninhabited/match_with_exhaustive_patterns.stderr b/tests/ui/rfcs/rfc-2008-non-exhaustive/uninhabited/match_with_exhaustive_patterns.stderr index 0c8b14ab69d..d6f0bc724a9 100644 --- a/tests/ui/rfcs/rfc-2008-non-exhaustive/uninhabited/match_with_exhaustive_patterns.stderr +++ b/tests/ui/rfcs/rfc-2008-non-exhaustive/uninhabited/match_with_exhaustive_patterns.stderr @@ -1,5 +1,5 @@ error[E0004]: non-exhaustive patterns: type `UninhabitedEnum` is non-empty - --> $DIR/match_with_exhaustive_patterns.rs:21:11 + --> $DIR/match_with_exhaustive_patterns.rs:17:11 | LL | match x {} | ^ @@ -17,67 +17,6 @@ LL + _ => todo!(), LL ~ } | -error[E0004]: non-exhaustive patterns: type `UninhabitedStruct` is non-empty - --> $DIR/match_with_exhaustive_patterns.rs:25:11 - | -LL | match x {} - | ^ - | -note: `UninhabitedStruct` defined here - --> $DIR/auxiliary/uninhabited.rs:9:1 - | -LL | pub struct UninhabitedStruct { - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - = note: the matched value is of type `UninhabitedStruct` -help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern as shown - | -LL ~ match x { -LL + _ => todo!(), -LL ~ } - | - -error[E0004]: non-exhaustive patterns: type `UninhabitedTupleStruct` is non-empty - --> $DIR/match_with_exhaustive_patterns.rs:29:11 - | -LL | match x {} - | ^ - | -note: `UninhabitedTupleStruct` defined here - --> $DIR/auxiliary/uninhabited.rs:14:1 - | -LL | pub struct UninhabitedTupleStruct(!); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - = note: the matched value is of type `UninhabitedTupleStruct` -help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern as shown - | -LL ~ match x { -LL + _ => todo!(), -LL ~ } - | - -error[E0004]: non-exhaustive patterns: `UninhabitedVariants::Tuple(_)` and `UninhabitedVariants::Struct { .. }` not covered - --> $DIR/match_with_exhaustive_patterns.rs:33:11 - | -LL | match x {} - | ^ patterns `UninhabitedVariants::Tuple(_)` and `UninhabitedVariants::Struct { .. }` not covered - | -note: `UninhabitedVariants` defined here - --> $DIR/auxiliary/uninhabited.rs:16:1 - | -LL | pub enum UninhabitedVariants { - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -LL | #[non_exhaustive] Tuple(!), - | ----- not covered -LL | #[non_exhaustive] Struct { x: ! } - | ------ not covered - = note: the matched value is of type `UninhabitedVariants` -help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern, a match arm with multiple or-patterns as shown, or multiple match arms - | -LL ~ match x { -LL + UninhabitedVariants::Tuple(_) | UninhabitedVariants::Struct { .. } => todo!(), -LL ~ } - | - -error: aborting due to 4 previous errors +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0004`. diff --git a/tests/ui/rfcs/rfc-2008-non-exhaustive/uninhabited/match_with_exhaustive_patterns_same_crate.rs b/tests/ui/rfcs/rfc-2008-non-exhaustive/uninhabited/match_with_exhaustive_patterns_same_crate.rs index 468703c78e0..96620162212 100644 --- a/tests/ui/rfcs/rfc-2008-non-exhaustive/uninhabited/match_with_exhaustive_patterns_same_crate.rs +++ b/tests/ui/rfcs/rfc-2008-non-exhaustive/uninhabited/match_with_exhaustive_patterns_same_crate.rs @@ -1,5 +1,4 @@ //@ check-pass - #![deny(unreachable_patterns)] #![feature(never_type)] @@ -9,11 +8,12 @@ pub enum UninhabitedEnum { #[non_exhaustive] pub struct UninhabitedStruct { - _priv: !, + pub never: !, + _priv: (), } #[non_exhaustive] -pub struct UninhabitedTupleStruct(!); +pub struct UninhabitedTupleStruct(pub !); pub enum UninhabitedVariants { #[non_exhaustive] Tuple(!), @@ -22,24 +22,21 @@ pub enum 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: UninhabitedEnum) -> A { +// This checks that `non_exhaustive` annotations do not affect exhaustiveness checking within the +// defining crate. +fn empty_match_on_empty_enum(x: UninhabitedEnum) -> A { match x {} } -fn cannot_empty_match_on_empty_struct_to_anything(x: UninhabitedStruct) -> A { +fn empty_match_on_empty_struct(x: UninhabitedStruct) -> A { match x {} } -fn cannot_empty_match_on_empty_tuple_struct_to_anything(x: UninhabitedTupleStruct) -> A { +fn empty_match_on_empty_tuple_struct(x: UninhabitedTupleStruct) -> A { match x {} } -fn cannot_empty_match_on_enum_with_empty_variants_struct_to_anything(x: UninhabitedVariants) -> A { +fn empty_match_on_enum_with_empty_variants_struct(x: UninhabitedVariants) -> A { match x {} } diff --git a/tests/ui/rfcs/rfc-2008-non-exhaustive/uninhabited/patterns.rs b/tests/ui/rfcs/rfc-2008-non-exhaustive/uninhabited/patterns.rs index be55ad51578..edc588777eb 100644 --- a/tests/ui/rfcs/rfc-2008-non-exhaustive/uninhabited/patterns.rs +++ b/tests/ui/rfcs/rfc-2008-non-exhaustive/uninhabited/patterns.rs @@ -1,14 +1,10 @@ //@ aux-build:uninhabited.rs -//@ build-pass (FIXME(62277): could be check-pass?) #![deny(unreachable_patterns)] extern crate uninhabited; use uninhabited::{ - PartiallyInhabitedVariants, - UninhabitedEnum, - UninhabitedStruct, - UninhabitedTupleStruct, + PartiallyInhabitedVariants, UninhabitedEnum, UninhabitedStruct, UninhabitedTupleStruct, UninhabitedVariants, }; @@ -32,27 +28,26 @@ 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. - +// This test checks that non-exhaustive enums are never considered uninhabited outside their +// defining crate, and non-exhaustive structs are considered uninhabited the same way as normal +// ones. fn main() { match uninhabited_enum() { - Some(_x) => (), // This line would normally error. + Some(_x) => (), // This would error without `non_exhaustive` None => (), } match uninhabited_variant() { - Some(_x) => (), // This line would normally error. + Some(_x) => (), //~ ERROR unreachable None => (), } // This line would normally error. - while let PartiallyInhabitedVariants::Struct { x, .. } = partially_inhabited_variant() { + while let PartiallyInhabitedVariants::Struct { x, .. } = partially_inhabited_variant() {} //~ ERROR unreachable + + while let Some(_x) = uninhabited_struct() { //~ ERROR unreachable } - while let Some(_x) = uninhabited_struct() { // This line would normally error. - } - - while let Some(_x) = uninhabited_tuple_struct() { // This line would normally error. + while let Some(_x) = uninhabited_tuple_struct() { //~ ERROR unreachable } } diff --git a/tests/ui/rfcs/rfc-2008-non-exhaustive/uninhabited/patterns.stderr b/tests/ui/rfcs/rfc-2008-non-exhaustive/uninhabited/patterns.stderr new file mode 100644 index 00000000000..deaa2ffd927 --- /dev/null +++ b/tests/ui/rfcs/rfc-2008-non-exhaustive/uninhabited/patterns.stderr @@ -0,0 +1,39 @@ +error: unreachable pattern + --> $DIR/patterns.rs:41:9 + | +LL | Some(_x) => (), + | ^^^^^^^^ matches no values because `UninhabitedVariants` is uninhabited + | + = note: to learn more about uninhabited types, see https://doc.rust-lang.org/nomicon/exotic-sizes.html#empty-types +note: the lint level is defined here + --> $DIR/patterns.rs:2:9 + | +LL | #![deny(unreachable_patterns)] + | ^^^^^^^^^^^^^^^^^^^^ + +error: unreachable pattern + --> $DIR/patterns.rs:46:15 + | +LL | while let PartiallyInhabitedVariants::Struct { x, .. } = partially_inhabited_variant() {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ matches no values because `!` is uninhabited + | + = note: to learn more about uninhabited types, see https://doc.rust-lang.org/nomicon/exotic-sizes.html#empty-types + +error: unreachable pattern + --> $DIR/patterns.rs:48:15 + | +LL | while let Some(_x) = uninhabited_struct() { + | ^^^^^^^^ matches no values because `UninhabitedStruct` is uninhabited + | + = note: to learn more about uninhabited types, see https://doc.rust-lang.org/nomicon/exotic-sizes.html#empty-types + +error: unreachable pattern + --> $DIR/patterns.rs:51:15 + | +LL | while let Some(_x) = uninhabited_tuple_struct() { + | ^^^^^^^^ matches no values because `UninhabitedTupleStruct` is uninhabited + | + = note: to learn more about uninhabited types, see https://doc.rust-lang.org/nomicon/exotic-sizes.html#empty-types + +error: aborting due to 4 previous errors + diff --git a/tests/ui/rfcs/rfc-2008-non-exhaustive/uninhabited/patterns_same_crate.rs b/tests/ui/rfcs/rfc-2008-non-exhaustive/uninhabited/patterns_same_crate.rs index 1194d7b858d..58cced3d23d 100644 --- a/tests/ui/rfcs/rfc-2008-non-exhaustive/uninhabited/patterns_same_crate.rs +++ b/tests/ui/rfcs/rfc-2008-non-exhaustive/uninhabited/patterns_same_crate.rs @@ -6,11 +6,12 @@ pub enum UninhabitedEnum { } #[non_exhaustive] -pub struct UninhabitedTupleStruct(!); +pub struct UninhabitedTupleStruct(pub !); #[non_exhaustive] pub struct UninhabitedStruct { - _priv: !, + pub never: !, + _priv: (), } pub enum UninhabitedVariants { diff --git a/tests/ui/rfcs/rfc-2008-non-exhaustive/uninhabited/patterns_same_crate.stderr b/tests/ui/rfcs/rfc-2008-non-exhaustive/uninhabited/patterns_same_crate.stderr index 7e7dc802e7f..38524bf5b95 100644 --- a/tests/ui/rfcs/rfc-2008-non-exhaustive/uninhabited/patterns_same_crate.stderr +++ b/tests/ui/rfcs/rfc-2008-non-exhaustive/uninhabited/patterns_same_crate.stderr @@ -1,5 +1,5 @@ error: unreachable pattern - --> $DIR/patterns_same_crate.rs:51:9 + --> $DIR/patterns_same_crate.rs:52:9 | LL | Some(_x) => (), | ^^^^^^^^ matches no values because `UninhabitedEnum` is uninhabited @@ -12,7 +12,7 @@ LL | #![deny(unreachable_patterns)] | ^^^^^^^^^^^^^^^^^^^^ error: unreachable pattern - --> $DIR/patterns_same_crate.rs:56:9 + --> $DIR/patterns_same_crate.rs:57:9 | LL | Some(_x) => (), | ^^^^^^^^ matches no values because `UninhabitedVariants` is uninhabited @@ -20,7 +20,7 @@ LL | Some(_x) => (), = note: to learn more about uninhabited types, see https://doc.rust-lang.org/nomicon/exotic-sizes.html#empty-types error: unreachable pattern - --> $DIR/patterns_same_crate.rs:60:15 + --> $DIR/patterns_same_crate.rs:61:15 | LL | while let PartiallyInhabitedVariants::Struct { x } = partially_inhabited_variant() { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ matches no values because `!` is uninhabited @@ -28,7 +28,7 @@ LL | while let PartiallyInhabitedVariants::Struct { x } = partially_inhabite = note: to learn more about uninhabited types, see https://doc.rust-lang.org/nomicon/exotic-sizes.html#empty-types error: unreachable pattern - --> $DIR/patterns_same_crate.rs:64:15 + --> $DIR/patterns_same_crate.rs:65:15 | LL | while let Some(_x) = uninhabited_struct() { | ^^^^^^^^ matches no values because `UninhabitedStruct` is uninhabited @@ -36,7 +36,7 @@ LL | while let Some(_x) = uninhabited_struct() { = note: to learn more about uninhabited types, see https://doc.rust-lang.org/nomicon/exotic-sizes.html#empty-types error: unreachable pattern - --> $DIR/patterns_same_crate.rs:67:15 + --> $DIR/patterns_same_crate.rs:68:15 | LL | while let Some(_x) = uninhabited_tuple_struct() { | ^^^^^^^^ matches no values because `UninhabitedTupleStruct` is uninhabited