diff --git a/compiler/rustc_mir_build/src/thir/pattern/deconstruct_pat.rs b/compiler/rustc_mir_build/src/thir/pattern/deconstruct_pat.rs index 61f1069d5716b..612bed639bfb1 100644 --- a/compiler/rustc_mir_build/src/thir/pattern/deconstruct_pat.rs +++ b/compiler/rustc_mir_build/src/thir/pattern/deconstruct_pat.rs @@ -692,11 +692,11 @@ impl<'tcx> Constructor<'tcx> { } /// Checks if the `Constructor` is a `Constructor::Variant` with a `#[doc(hidden)]` - /// attribute. + /// attribute from a type not local to the current crate. pub(super) fn is_doc_hidden_variant(&self, pcx: PatCtxt<'_, '_, 'tcx>) -> bool { if let Constructor::Variant(idx) = self && let ty::Adt(adt, _) = pcx.ty.kind() { - let variant_def_id = adt.variant(*idx).def_id; - return pcx.cx.tcx.is_doc_hidden(variant_def_id); + let variant_def_id = adt.variants()[*idx].def_id; + return pcx.cx.tcx.is_doc_hidden(variant_def_id) && !variant_def_id.is_local(); } false } diff --git a/compiler/rustc_typeck/src/check/pat.rs b/compiler/rustc_typeck/src/check/pat.rs index 26a1d0c473c60..a264ee5d1475d 100644 --- a/compiler/rustc_typeck/src/check/pat.rs +++ b/compiler/rustc_typeck/src/check/pat.rs @@ -11,6 +11,7 @@ use rustc_hir::pat_util::EnumerateAndAdjustIterator; use rustc_hir::{HirId, Pat, PatKind}; use rustc_infer::infer; use rustc_infer::infer::type_variable::{TypeVariableOrigin, TypeVariableOriginKind}; +use rustc_middle::middle::stability::EvalResult; use rustc_middle::ty::{self, Adt, BindingMode, Ty, TypeFoldable}; use rustc_session::lint::builtin::NON_EXHAUSTIVE_OMITTED_PATTERNS; use rustc_span::hygiene::DesugaringKind; @@ -1308,6 +1309,12 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { .copied() .filter(|(field, _)| { field.vis.is_accessible_from(tcx.parent_module(pat.hir_id).to_def_id(), tcx) + && !matches!( + tcx.eval_stability(field.did, None, DUMMY_SP, None), + EvalResult::Deny { .. } + ) + // We only want to report the error if it is hidden and not local + && !(tcx.is_doc_hidden(field.did) && !field.did.is_local()) }) .collect(); diff --git a/src/test/ui/pattern/usefulness/auxiliary/hidden.rs b/src/test/ui/pattern/usefulness/auxiliary/hidden.rs index 742b7e82c16b0..364514ba1d3b0 100644 --- a/src/test/ui/pattern/usefulness/auxiliary/hidden.rs +++ b/src/test/ui/pattern/usefulness/auxiliary/hidden.rs @@ -1,6 +1,14 @@ -pub enum Foo { +pub enum HiddenEnum { A, B, #[doc(hidden)] C, } + +#[derive(Default)] +pub struct HiddenStruct { + pub one: u8, + pub two: bool, + #[doc(hidden)] + pub hide: usize, +} diff --git a/src/test/ui/pattern/usefulness/auxiliary/unstable.rs b/src/test/ui/pattern/usefulness/auxiliary/unstable.rs index 3142489c86103..a06b3a6e4e5ab 100644 --- a/src/test/ui/pattern/usefulness/auxiliary/unstable.rs +++ b/src/test/ui/pattern/usefulness/auxiliary/unstable.rs @@ -2,7 +2,7 @@ #![stable(feature = "stable_test_feature", since = "1.0.0")] #[stable(feature = "stable_test_feature", since = "1.0.0")] -pub enum Foo { +pub enum UnstableEnum { #[stable(feature = "stable_test_feature", since = "1.0.0")] Stable, #[stable(feature = "stable_test_feature", since = "1.0.0")] @@ -10,3 +10,14 @@ pub enum Foo { #[unstable(feature = "unstable_test_feature", issue = "none")] Unstable, } + +#[derive(Default)] +#[stable(feature = "stable_test_feature", since = "1.0.0")] +pub struct UnstableStruct { + #[stable(feature = "stable_test_feature", since = "1.0.0")] + pub stable: bool, + #[stable(feature = "stable_test_feature", since = "1.0.0")] + pub stable2: usize, + #[unstable(feature = "unstable_test_feature", issue = "none")] + pub unstable: u8, +} diff --git a/src/test/ui/pattern/usefulness/doc-hidden-fields.rs b/src/test/ui/pattern/usefulness/doc-hidden-fields.rs new file mode 100644 index 0000000000000..4163b87dc8597 --- /dev/null +++ b/src/test/ui/pattern/usefulness/doc-hidden-fields.rs @@ -0,0 +1,26 @@ +// aux-build:hidden.rs + +extern crate hidden; + +use hidden::HiddenStruct; + +struct InCrate { + a: usize, + b: bool, + #[doc(hidden)] + im_hidden: u8 +} + +fn main() { + let HiddenStruct { one, two } = HiddenStruct::default(); + //~^ pattern requires `..` due to inaccessible fields + + let HiddenStruct { one } = HiddenStruct::default(); + //~^ pattern does not mention field `two` and inaccessible fields + + let HiddenStruct { one, hide } = HiddenStruct::default(); + //~^ pattern does not mention field `two` + + let InCrate { a, b } = InCrate { a: 0, b: false, im_hidden: 0 }; + //~^ pattern does not mention field `im_hidden` +} diff --git a/src/test/ui/pattern/usefulness/doc-hidden-fields.stderr b/src/test/ui/pattern/usefulness/doc-hidden-fields.stderr new file mode 100644 index 0000000000000..f277bfbc884fb --- /dev/null +++ b/src/test/ui/pattern/usefulness/doc-hidden-fields.stderr @@ -0,0 +1,59 @@ +error: pattern requires `..` due to inaccessible fields + --> $DIR/doc-hidden-fields.rs:15:9 + | +LL | let HiddenStruct { one, two } = HiddenStruct::default(); + | ^^^^^^^^^^^^^^^^^^^^^^^^^ + | +help: ignore the inaccessible and unused fields + | +LL | let HiddenStruct { one, two, .. } = HiddenStruct::default(); + | ++++ + +error[E0027]: pattern does not mention field `two` and inaccessible fields + --> $DIR/doc-hidden-fields.rs:18:9 + | +LL | let HiddenStruct { one } = HiddenStruct::default(); + | ^^^^^^^^^^^^^^^^^^^^ missing field `two` and inaccessible fields + | +help: include the missing field in the pattern and ignore the inaccessible fields + | +LL | let HiddenStruct { one, two, .. } = HiddenStruct::default(); + | ~~~~~~~~~~~ +help: if you don't care about this missing field, you can explicitly ignore it + | +LL | let HiddenStruct { one, .. } = HiddenStruct::default(); + | ~~~~~~ + +error[E0027]: pattern does not mention field `two` + --> $DIR/doc-hidden-fields.rs:21:9 + | +LL | let HiddenStruct { one, hide } = HiddenStruct::default(); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ missing field `two` + | +help: include the missing field in the pattern + | +LL | let HiddenStruct { one, hide, two } = HiddenStruct::default(); + | ~~~~~~~ +help: if you don't care about this missing field, you can explicitly ignore it + | +LL | let HiddenStruct { one, hide, .. } = HiddenStruct::default(); + | ~~~~~~ + +error[E0027]: pattern does not mention field `im_hidden` + --> $DIR/doc-hidden-fields.rs:24:9 + | +LL | let InCrate { a, b } = InCrate { a: 0, b: false, im_hidden: 0 }; + | ^^^^^^^^^^^^^^^^ missing field `im_hidden` + | +help: include the missing field in the pattern + | +LL | let InCrate { a, b, im_hidden } = InCrate { a: 0, b: false, im_hidden: 0 }; + | ~~~~~~~~~~~~~ +help: if you don't care about this missing field, you can explicitly ignore it + | +LL | let InCrate { a, b, .. } = InCrate { a: 0, b: false, im_hidden: 0 }; + | ~~~~~~ + +error: aborting due to 4 previous errors + +For more information about this error, try `rustc --explain E0027`. diff --git a/src/test/ui/pattern/usefulness/doc-hidden-non-exhaustive.rs b/src/test/ui/pattern/usefulness/doc-hidden-non-exhaustive.rs index a1dcab0931423..d968c48fb1ab7 100644 --- a/src/test/ui/pattern/usefulness/doc-hidden-non-exhaustive.rs +++ b/src/test/ui/pattern/usefulness/doc-hidden-non-exhaustive.rs @@ -2,29 +2,42 @@ extern crate hidden; -use hidden::Foo; +use hidden::HiddenEnum; + +enum InCrate { + A, + B, + #[doc(hidden)] + C, +} fn main() { - match Foo::A { - Foo::A => {} - Foo::B => {} + match HiddenEnum::A { + HiddenEnum::A => {} + HiddenEnum::B => {} } //~^^^^ non-exhaustive patterns: `_` not covered - match Foo::A { - Foo::A => {} - Foo::C => {} + match HiddenEnum::A { + HiddenEnum::A => {} + HiddenEnum::C => {} } //~^^^^ non-exhaustive patterns: `B` not covered - match Foo::A { - Foo::A => {} + match HiddenEnum::A { + HiddenEnum::A => {} } //~^^^ non-exhaustive patterns: `B` and `_` not covered match None { None => {} - Some(Foo::A) => {} + Some(HiddenEnum::A) => {} } //~^^^^ non-exhaustive patterns: `Some(B)` and `Some(_)` not covered + + match InCrate::A { + InCrate::A => {} + InCrate::B => {} + } + //~^^^^ non-exhaustive patterns: `C` not covered } diff --git a/src/test/ui/pattern/usefulness/doc-hidden-non-exhaustive.stderr b/src/test/ui/pattern/usefulness/doc-hidden-non-exhaustive.stderr index 7d0b71a497ec2..296465eb81838 100644 --- a/src/test/ui/pattern/usefulness/doc-hidden-non-exhaustive.stderr +++ b/src/test/ui/pattern/usefulness/doc-hidden-non-exhaustive.stderr @@ -1,36 +1,36 @@ error[E0004]: non-exhaustive patterns: `_` not covered - --> $DIR/doc-hidden-non-exhaustive.rs:8:11 + --> $DIR/doc-hidden-non-exhaustive.rs:15:11 | -LL | match Foo::A { - | ^^^^^^ pattern `_` not covered +LL | match HiddenEnum::A { + | ^^^^^^^^^^^^^ pattern `_` not covered | -note: `Foo` defined here +note: `HiddenEnum` defined here --> $DIR/auxiliary/hidden.rs:1:1 | -LL | / pub enum Foo { +LL | / pub enum HiddenEnum { LL | | A, LL | | B, LL | | #[doc(hidden)] LL | | C, LL | | } | |_^ - = note: the matched value is of type `Foo` + = note: the matched value is of type `HiddenEnum` help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern or an explicit pattern as shown | -LL ~ Foo::B => {} +LL ~ HiddenEnum::B => {} LL + _ => todo!() | error[E0004]: non-exhaustive patterns: `B` not covered - --> $DIR/doc-hidden-non-exhaustive.rs:14:11 + --> $DIR/doc-hidden-non-exhaustive.rs:21:11 | -LL | match Foo::A { - | ^^^^^^ pattern `B` not covered +LL | match HiddenEnum::A { + | ^^^^^^^^^^^^^ pattern `B` not covered | -note: `Foo` defined here +note: `HiddenEnum` defined here --> $DIR/auxiliary/hidden.rs:3:5 | -LL | / pub enum Foo { +LL | / pub enum HiddenEnum { LL | | A, LL | | B, | | ^ not covered @@ -38,23 +38,23 @@ LL | | #[doc(hidden)] LL | | C, LL | | } | |_- - = note: the matched value is of type `Foo` + = note: the matched value is of type `HiddenEnum` help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern or an explicit pattern as shown | -LL ~ Foo::C => {} +LL ~ HiddenEnum::C => {} LL + B => todo!() | error[E0004]: non-exhaustive patterns: `B` and `_` not covered - --> $DIR/doc-hidden-non-exhaustive.rs:20:11 + --> $DIR/doc-hidden-non-exhaustive.rs:27:11 | -LL | match Foo::A { - | ^^^^^^ patterns `B` and `_` not covered +LL | match HiddenEnum::A { + | ^^^^^^^^^^^^^ patterns `B` and `_` not covered | -note: `Foo` defined here +note: `HiddenEnum` defined here --> $DIR/auxiliary/hidden.rs:3:5 | -LL | / pub enum Foo { +LL | / pub enum HiddenEnum { LL | | A, LL | | B, | | ^ not covered @@ -62,20 +62,20 @@ LL | | #[doc(hidden)] LL | | C, LL | | } | |_- - = note: the matched value is of type `Foo` + = note: the matched value is of type `HiddenEnum` 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 ~ Foo::A => {} +LL ~ HiddenEnum::A => {} LL + B | _ => todo!() | error[E0004]: non-exhaustive patterns: `Some(B)` and `Some(_)` not covered - --> $DIR/doc-hidden-non-exhaustive.rs:25:11 + --> $DIR/doc-hidden-non-exhaustive.rs:32:11 | LL | match None { | ^^^^ patterns `Some(B)` and `Some(_)` not covered | -note: `Option` defined here +note: `Option` defined here --> $SRC_DIR/core/src/option.rs:LL:COL | LL | / pub enum Option { @@ -87,13 +87,34 @@ LL | | Some(#[stable(feature = "rust1", since = "1.0.0")] T), | | ^^^^ not covered LL | | } | |_- - = note: the matched value is of type `Option` + = note: the matched value is of type `Option` 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 ~ Some(Foo::A) => {} +LL ~ Some(HiddenEnum::A) => {} LL + Some(B) | Some(_) => todo!() | -error: aborting due to 4 previous errors +error[E0004]: non-exhaustive patterns: `C` not covered + --> $DIR/doc-hidden-non-exhaustive.rs:38:11 + | +LL | match InCrate::A { + | ^^^^^^^^^^ pattern `C` not covered + | +note: `InCrate` defined here + --> $DIR/doc-hidden-non-exhaustive.rs:11:5 + | +LL | enum InCrate { + | ------- +... +LL | C, + | ^ not covered + = note: the matched value is of type `InCrate` +help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern or an explicit pattern as shown + | +LL ~ InCrate::B => {} +LL + C => todo!() + | + +error: aborting due to 5 previous errors For more information about this error, try `rustc --explain E0004`. diff --git a/src/test/ui/pattern/usefulness/stable-gated-fields.rs b/src/test/ui/pattern/usefulness/stable-gated-fields.rs new file mode 100644 index 0000000000000..90f40a8d62962 --- /dev/null +++ b/src/test/ui/pattern/usefulness/stable-gated-fields.rs @@ -0,0 +1,16 @@ +// aux-build:unstable.rs + +extern crate unstable; + +use unstable::UnstableStruct; + +fn main() { + let UnstableStruct { stable } = UnstableStruct::default(); + //~^ pattern does not mention field `stable2` and inaccessible fields + + let UnstableStruct { stable, stable2 } = UnstableStruct::default(); + //~^ pattern requires `..` due to inaccessible fields + + // OK: stable field is matched + let UnstableStruct { stable, stable2, .. } = UnstableStruct::default(); +} diff --git a/src/test/ui/pattern/usefulness/stable-gated-fields.stderr b/src/test/ui/pattern/usefulness/stable-gated-fields.stderr new file mode 100644 index 0000000000000..cf98c51a2b41e --- /dev/null +++ b/src/test/ui/pattern/usefulness/stable-gated-fields.stderr @@ -0,0 +1,29 @@ +error[E0027]: pattern does not mention field `stable2` and inaccessible fields + --> $DIR/stable-gated-fields.rs:8:9 + | +LL | let UnstableStruct { stable } = UnstableStruct::default(); + | ^^^^^^^^^^^^^^^^^^^^^^^^^ missing field `stable2` and inaccessible fields + | +help: include the missing field in the pattern and ignore the inaccessible fields + | +LL | let UnstableStruct { stable, stable2, .. } = UnstableStruct::default(); + | ~~~~~~~~~~~~~~~ +help: if you don't care about this missing field, you can explicitly ignore it + | +LL | let UnstableStruct { stable, .. } = UnstableStruct::default(); + | ~~~~~~ + +error: pattern requires `..` due to inaccessible fields + --> $DIR/stable-gated-fields.rs:11:9 + | +LL | let UnstableStruct { stable, stable2 } = UnstableStruct::default(); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +help: ignore the inaccessible and unused fields + | +LL | let UnstableStruct { stable, stable2, .. } = UnstableStruct::default(); + | ++++ + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0027`. diff --git a/src/test/ui/pattern/usefulness/stable-gated-patterns.rs b/src/test/ui/pattern/usefulness/stable-gated-patterns.rs index 2e023a3be4a5e..ff1c472e24fd6 100644 --- a/src/test/ui/pattern/usefulness/stable-gated-patterns.rs +++ b/src/test/ui/pattern/usefulness/stable-gated-patterns.rs @@ -2,17 +2,17 @@ extern crate unstable; -use unstable::Foo; +use unstable::UnstableEnum; fn main() { - match Foo::Stable { - Foo::Stable => {} + match UnstableEnum::Stable { + UnstableEnum::Stable => {} } //~^^^ non-exhaustive patterns: `Stable2` and `_` not covered - match Foo::Stable { - Foo::Stable => {} - Foo::Stable2 => {} + match UnstableEnum::Stable { + UnstableEnum::Stable => {} + UnstableEnum::Stable2 => {} } //~^^^^ non-exhaustive patterns: `_` not covered } diff --git a/src/test/ui/pattern/usefulness/stable-gated-patterns.stderr b/src/test/ui/pattern/usefulness/stable-gated-patterns.stderr index 696ef9d8de936..559539178cbe3 100644 --- a/src/test/ui/pattern/usefulness/stable-gated-patterns.stderr +++ b/src/test/ui/pattern/usefulness/stable-gated-patterns.stderr @@ -1,13 +1,13 @@ error[E0004]: non-exhaustive patterns: `Stable2` and `_` not covered --> $DIR/stable-gated-patterns.rs:8:11 | -LL | match Foo::Stable { - | ^^^^^^^^^^^ patterns `Stable2` and `_` not covered +LL | match UnstableEnum::Stable { + | ^^^^^^^^^^^^^^^^^^^^ patterns `Stable2` and `_` not covered | -note: `Foo` defined here +note: `UnstableEnum` defined here --> $DIR/auxiliary/unstable.rs:9:5 | -LL | / pub enum Foo { +LL | / pub enum UnstableEnum { LL | | #[stable(feature = "stable_test_feature", since = "1.0.0")] LL | | Stable, LL | | #[stable(feature = "stable_test_feature", since = "1.0.0")] @@ -17,23 +17,23 @@ LL | | #[unstable(feature = "unstable_test_feature", issue = "none")] LL | | Unstable, LL | | } | |_- - = note: the matched value is of type `Foo` + = note: the matched value is of type `UnstableEnum` 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 ~ Foo::Stable => {} +LL ~ UnstableEnum::Stable => {} LL + Stable2 | _ => todo!() | error[E0004]: non-exhaustive patterns: `_` not covered --> $DIR/stable-gated-patterns.rs:13:11 | -LL | match Foo::Stable { - | ^^^^^^^^^^^ pattern `_` not covered +LL | match UnstableEnum::Stable { + | ^^^^^^^^^^^^^^^^^^^^ pattern `_` not covered | -note: `Foo` defined here +note: `UnstableEnum` defined here --> $DIR/auxiliary/unstable.rs:5:1 | -LL | / pub enum Foo { +LL | / pub enum UnstableEnum { LL | | #[stable(feature = "stable_test_feature", since = "1.0.0")] LL | | Stable, LL | | #[stable(feature = "stable_test_feature", since = "1.0.0")] @@ -41,10 +41,10 @@ LL | | #[stable(feature = "stable_test_feature", since = "1.0.0")] LL | | Unstable, LL | | } | |_^ - = note: the matched value is of type `Foo` + = note: the matched value is of type `UnstableEnum` help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern or an explicit pattern as shown | -LL ~ Foo::Stable2 => {} +LL ~ UnstableEnum::Stable2 => {} LL + _ => todo!() | diff --git a/src/test/ui/pattern/usefulness/unstable-gated-fields.rs b/src/test/ui/pattern/usefulness/unstable-gated-fields.rs new file mode 100644 index 0000000000000..2b473ae989bbe --- /dev/null +++ b/src/test/ui/pattern/usefulness/unstable-gated-fields.rs @@ -0,0 +1,18 @@ +#![feature(unstable_test_feature)] + +// aux-build:unstable.rs + +extern crate unstable; + +use unstable::UnstableStruct; + +fn main() { + let UnstableStruct { stable, stable2, } = UnstableStruct::default(); + //~^ pattern does not mention field `unstable` + + let UnstableStruct { stable, unstable, } = UnstableStruct::default(); + //~^ pattern does not mention field `stable2` + + // OK: stable field is matched + let UnstableStruct { stable, stable2, unstable } = UnstableStruct::default(); +} diff --git a/src/test/ui/pattern/usefulness/unstable-gated-fields.stderr b/src/test/ui/pattern/usefulness/unstable-gated-fields.stderr new file mode 100644 index 0000000000000..e4f5fa06b3ff5 --- /dev/null +++ b/src/test/ui/pattern/usefulness/unstable-gated-fields.stderr @@ -0,0 +1,33 @@ +error[E0027]: pattern does not mention field `unstable` + --> $DIR/unstable-gated-fields.rs:10:9 + | +LL | let UnstableStruct { stable, stable2, } = UnstableStruct::default(); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ missing field `unstable` + | +help: include the missing field in the pattern + | +LL | let UnstableStruct { stable, stable2, unstable } = UnstableStruct::default(); + | ~~~~~~~~~~~~ +help: if you don't care about this missing field, you can explicitly ignore it + | +LL | let UnstableStruct { stable, stable2, .. } = UnstableStruct::default(); + | ~~~~~~ + +error[E0027]: pattern does not mention field `stable2` + --> $DIR/unstable-gated-fields.rs:13:9 + | +LL | let UnstableStruct { stable, unstable, } = UnstableStruct::default(); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ missing field `stable2` + | +help: include the missing field in the pattern + | +LL | let UnstableStruct { stable, unstable, stable2 } = UnstableStruct::default(); + | ~~~~~~~~~~~ +help: if you don't care about this missing field, you can explicitly ignore it + | +LL | let UnstableStruct { stable, unstable, .. } = UnstableStruct::default(); + | ~~~~~~ + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0027`. diff --git a/src/test/ui/pattern/usefulness/unstable-gated-patterns.rs b/src/test/ui/pattern/usefulness/unstable-gated-patterns.rs index b9804b0ffe77a..bdab327fd57ac 100644 --- a/src/test/ui/pattern/usefulness/unstable-gated-patterns.rs +++ b/src/test/ui/pattern/usefulness/unstable-gated-patterns.rs @@ -4,19 +4,19 @@ extern crate unstable; -use unstable::Foo; +use unstable::UnstableEnum; fn main() { - match Foo::Stable { - Foo::Stable => {} - Foo::Stable2 => {} + match UnstableEnum::Stable { + UnstableEnum::Stable => {} + UnstableEnum::Stable2 => {} } //~^^^^ non-exhaustive patterns: `Unstable` not covered // Ok: all variants are explicitly matched - match Foo::Stable { - Foo::Stable => {} - Foo::Stable2 => {} - Foo::Unstable => {} + match UnstableEnum::Stable { + UnstableEnum::Stable => {} + UnstableEnum::Stable2 => {} + UnstableEnum::Unstable => {} } } diff --git a/src/test/ui/pattern/usefulness/unstable-gated-patterns.stderr b/src/test/ui/pattern/usefulness/unstable-gated-patterns.stderr index 8487c9725da83..b5f1805deef11 100644 --- a/src/test/ui/pattern/usefulness/unstable-gated-patterns.stderr +++ b/src/test/ui/pattern/usefulness/unstable-gated-patterns.stderr @@ -1,13 +1,13 @@ error[E0004]: non-exhaustive patterns: `Unstable` not covered --> $DIR/unstable-gated-patterns.rs:10:11 | -LL | match Foo::Stable { - | ^^^^^^^^^^^ pattern `Unstable` not covered +LL | match UnstableEnum::Stable { + | ^^^^^^^^^^^^^^^^^^^^ pattern `Unstable` not covered | -note: `Foo` defined here +note: `UnstableEnum` defined here --> $DIR/auxiliary/unstable.rs:11:5 | -LL | / pub enum Foo { +LL | / pub enum UnstableEnum { LL | | #[stable(feature = "stable_test_feature", since = "1.0.0")] LL | | Stable, LL | | #[stable(feature = "stable_test_feature", since = "1.0.0")] @@ -16,10 +16,10 @@ LL | | Unstable, | | ^^^^^^^^ not covered LL | | } | |_- - = note: the matched value is of type `Foo` + = note: the matched value is of type `UnstableEnum` help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern or an explicit pattern as shown | -LL ~ Foo::Stable2 => {} +LL ~ UnstableEnum::Stable2 => {} LL + Unstable => todo!() | diff --git a/src/test/ui/rfc-2008-non-exhaustive/auxiliary/unstable.rs b/src/test/ui/rfc-2008-non-exhaustive/auxiliary/unstable.rs index de9d6f65945cd..11df44461e36b 100644 --- a/src/test/ui/rfc-2008-non-exhaustive/auxiliary/unstable.rs +++ b/src/test/ui/rfc-2008-non-exhaustive/auxiliary/unstable.rs @@ -27,3 +27,34 @@ impl OnlyUnstableEnum { Self::Unstable } } + +#[derive(Default)] +#[stable(feature = "stable_test_feature", since = "1.0.0")] +#[non_exhaustive] +pub struct UnstableStruct { + #[stable(feature = "stable_test_feature", since = "1.0.0")] + pub stable: bool, + #[stable(feature = "stable_test_feature", since = "1.0.0")] + pub stable2: usize, + #[unstable(feature = "unstable_test_feature", issue = "none")] + pub unstable: u8, +} + +#[stable(feature = "stable_test_feature", since = "1.0.0")] +#[non_exhaustive] +pub struct OnlyUnstableStruct { + #[unstable(feature = "unstable_test_feature", issue = "none")] + pub unstable: u8, + #[unstable(feature = "unstable_test_feature", issue = "none")] + pub unstable2: bool, +} + +impl OnlyUnstableStruct { + #[stable(feature = "stable_test_feature", since = "1.0.0")] + pub fn new() -> Self { + Self { + unstable: 0, + unstable2: false, + } + } +} diff --git a/src/test/ui/rfc-2008-non-exhaustive/omitted-patterns.rs b/src/test/ui/rfc-2008-non-exhaustive/omitted-patterns.rs index fe9734fdc08f6..d8f07bb8f24d1 100644 --- a/src/test/ui/rfc-2008-non-exhaustive/omitted-patterns.rs +++ b/src/test/ui/rfc-2008-non-exhaustive/omitted-patterns.rs @@ -13,7 +13,7 @@ use enums::{ EmptyNonExhaustiveEnum, NestedNonExhaustive, NonExhaustiveEnum, NonExhaustiveSingleVariant, VariantNonExhaustive, }; -use unstable::{UnstableEnum, OnlyUnstableEnum}; +use unstable::{UnstableEnum, OnlyUnstableEnum, UnstableStruct, OnlyUnstableStruct}; use structs::{FunctionalRecord, MixedVisFields, NestedStruct, NormalStruct}; #[non_exhaustive] @@ -145,6 +145,7 @@ fn main() { } //~^^ some variants are not matched explicitly + // Ok: the feature is on and all variants are matched #[deny(non_exhaustive_omitted_patterns)] match UnstableEnum::Stable { UnstableEnum::Stable => {} @@ -167,4 +168,20 @@ fn main() { _ => {} } //~^^ some variants are not matched explicitly + + #[warn(non_exhaustive_omitted_patterns)] + let OnlyUnstableStruct { unstable, .. } = OnlyUnstableStruct::new(); + //~^ some fields are not explicitly listed + + // OK: both unstable fields are matched with feature on + #[warn(non_exhaustive_omitted_patterns)] + let OnlyUnstableStruct { unstable, unstable2, .. } = OnlyUnstableStruct::new(); + + #[warn(non_exhaustive_omitted_patterns)] + let UnstableStruct { stable, stable2, .. } = UnstableStruct::default(); + //~^ some fields are not explicitly listed + + // OK: both unstable and stable fields are matched with feature on + #[warn(non_exhaustive_omitted_patterns)] + let UnstableStruct { stable, stable2, unstable, .. } = UnstableStruct::default(); } diff --git a/src/test/ui/rfc-2008-non-exhaustive/omitted-patterns.stderr b/src/test/ui/rfc-2008-non-exhaustive/omitted-patterns.stderr index 30f3f88ad9161..a9885449f3f02 100644 --- a/src/test/ui/rfc-2008-non-exhaustive/omitted-patterns.stderr +++ b/src/test/ui/rfc-2008-non-exhaustive/omitted-patterns.stderr @@ -49,6 +49,34 @@ LL | let NestedStruct { bar: NormalStruct { first_field, .. }, .. } = Nested = help: ensure that all fields are mentioned explicitly by adding the suggested fields = note: the pattern is of type `NestedStruct` and the `non_exhaustive_omitted_patterns` attribute was found +warning: some fields are not explicitly listed + --> $DIR/omitted-patterns.rs:173:9 + | +LL | let OnlyUnstableStruct { unstable, .. } = OnlyUnstableStruct::new(); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ field `unstable2` not listed + | +note: the lint level is defined here + --> $DIR/omitted-patterns.rs:172:12 + | +LL | #[warn(non_exhaustive_omitted_patterns)] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + = help: ensure that all fields are mentioned explicitly by adding the suggested fields + = note: the pattern is of type `OnlyUnstableStruct` and the `non_exhaustive_omitted_patterns` attribute was found + +warning: some fields are not explicitly listed + --> $DIR/omitted-patterns.rs:181:9 + | +LL | let UnstableStruct { stable, stable2, .. } = UnstableStruct::default(); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ field `unstable` not listed + | +note: the lint level is defined here + --> $DIR/omitted-patterns.rs:180:12 + | +LL | #[warn(non_exhaustive_omitted_patterns)] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + = help: ensure that all fields are mentioned explicitly by adding the suggested fields + = note: the pattern is of type `UnstableStruct` and the `non_exhaustive_omitted_patterns` attribute was found + error: some variants are not matched explicitly --> $DIR/omitted-patterns.rs:58:9 | @@ -143,18 +171,18 @@ LL | #[deny(non_exhaustive_omitted_patterns)] = note: the matched value is of type `UnstableEnum` and the `non_exhaustive_omitted_patterns` attribute was found error: some variants are not matched explicitly - --> $DIR/omitted-patterns.rs:167:9 + --> $DIR/omitted-patterns.rs:168:9 | LL | _ => {} | ^ pattern `Unstable2` not covered | note: the lint level is defined here - --> $DIR/omitted-patterns.rs:164:12 + --> $DIR/omitted-patterns.rs:165:12 | LL | #[deny(non_exhaustive_omitted_patterns)] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ = help: ensure that all variants are matched explicitly by adding the suggested match arms = note: the matched value is of type `OnlyUnstableEnum` and the `non_exhaustive_omitted_patterns` attribute was found -error: aborting due to 8 previous errors; 4 warnings emitted +error: aborting due to 8 previous errors; 6 warnings emitted diff --git a/src/test/ui/rfc-2008-non-exhaustive/stable-omitted-patterns.rs b/src/test/ui/rfc-2008-non-exhaustive/stable-omitted-patterns.rs index 9621d28f8e22b..82ee68687ed00 100644 --- a/src/test/ui/rfc-2008-non-exhaustive/stable-omitted-patterns.rs +++ b/src/test/ui/rfc-2008-non-exhaustive/stable-omitted-patterns.rs @@ -6,7 +6,7 @@ // aux-build:unstable.rs extern crate unstable; -use unstable::{UnstableEnum, OnlyUnstableEnum}; +use unstable::{UnstableEnum, OnlyUnstableEnum, UnstableStruct, OnlyUnstableStruct}; fn main() { // OK: this matches all the stable variants @@ -30,4 +30,16 @@ fn main() { match OnlyUnstableEnum::new() { _ => {} } + + // Ok: Same as the above enum (no fields can be matched on) + #[warn(non_exhaustive_omitted_patterns)] + let OnlyUnstableStruct { .. } = OnlyUnstableStruct::new(); + + #[warn(non_exhaustive_omitted_patterns)] + let UnstableStruct { stable, .. } = UnstableStruct::default(); + //~^ some fields are not explicitly listed + + // OK: stable field is matched + #[warn(non_exhaustive_omitted_patterns)] + let UnstableStruct { stable, stable2, .. } = UnstableStruct::default(); } diff --git a/src/test/ui/rfc-2008-non-exhaustive/stable-omitted-patterns.stderr b/src/test/ui/rfc-2008-non-exhaustive/stable-omitted-patterns.stderr index b9a281974faf4..7cce178988aa9 100644 --- a/src/test/ui/rfc-2008-non-exhaustive/stable-omitted-patterns.stderr +++ b/src/test/ui/rfc-2008-non-exhaustive/stable-omitted-patterns.stderr @@ -1,3 +1,17 @@ +warning: some fields are not explicitly listed + --> $DIR/stable-omitted-patterns.rs:39:9 + | +LL | let UnstableStruct { stable, .. } = UnstableStruct::default(); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ field `stable2` not listed + | +note: the lint level is defined here + --> $DIR/stable-omitted-patterns.rs:38:12 + | +LL | #[warn(non_exhaustive_omitted_patterns)] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + = help: ensure that all fields are mentioned explicitly by adding the suggested fields + = note: the pattern is of type `UnstableStruct` and the `non_exhaustive_omitted_patterns` attribute was found + error: some variants are not matched explicitly --> $DIR/stable-omitted-patterns.rs:23:9 | @@ -12,5 +26,5 @@ LL | #[deny(non_exhaustive_omitted_patterns)] = help: ensure that all variants are matched explicitly by adding the suggested match arms = note: the matched value is of type `UnstableEnum` and the `non_exhaustive_omitted_patterns` attribute was found -error: aborting due to previous error +error: aborting due to previous error; 1 warning emitted