Auto merge of #90358 - DevinR528:omitted-field-fix, r=jackh726
Fix exposing fields marked unstable or doc hidden Closes https://github.com/rust-lang/rust/issues/89837 Work towards https://github.com/rust-lang/rust/issues/89554 Filter fields that are marked `doc(hidden)` or are unstable with that feature turned off. This brings structs and enums into alignment behavior-wise when emitting warning/errors about pattern exhaustiveness/reachability. cc `@Nadrieril`
This commit is contained in:
commit
bbbd48fa6d
@ -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
|
||||
}
|
||||
|
@ -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();
|
||||
|
||||
|
@ -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,
|
||||
}
|
||||
|
@ -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,
|
||||
}
|
||||
|
26
src/test/ui/pattern/usefulness/doc-hidden-fields.rs
Normal file
26
src/test/ui/pattern/usefulness/doc-hidden-fields.rs
Normal file
@ -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`
|
||||
}
|
59
src/test/ui/pattern/usefulness/doc-hidden-fields.stderr
Normal file
59
src/test/ui/pattern/usefulness/doc-hidden-fields.stderr
Normal file
@ -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`.
|
@ -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
|
||||
}
|
||||
|
@ -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<Foo>` defined here
|
||||
note: `Option<HiddenEnum>` defined here
|
||||
--> $SRC_DIR/core/src/option.rs:LL:COL
|
||||
|
|
||||
LL | / pub enum Option<T> {
|
||||
@ -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<Foo>`
|
||||
= note: the matched value is of type `Option<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 ~ 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`.
|
||||
|
16
src/test/ui/pattern/usefulness/stable-gated-fields.rs
Normal file
16
src/test/ui/pattern/usefulness/stable-gated-fields.rs
Normal file
@ -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();
|
||||
}
|
29
src/test/ui/pattern/usefulness/stable-gated-fields.stderr
Normal file
29
src/test/ui/pattern/usefulness/stable-gated-fields.stderr
Normal file
@ -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`.
|
@ -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
|
||||
}
|
||||
|
@ -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!()
|
||||
|
|
||||
|
||||
|
18
src/test/ui/pattern/usefulness/unstable-gated-fields.rs
Normal file
18
src/test/ui/pattern/usefulness/unstable-gated-fields.rs
Normal file
@ -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();
|
||||
}
|
33
src/test/ui/pattern/usefulness/unstable-gated-fields.stderr
Normal file
33
src/test/ui/pattern/usefulness/unstable-gated-fields.stderr
Normal file
@ -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`.
|
@ -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 => {}
|
||||
}
|
||||
}
|
||||
|
@ -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!()
|
||||
|
|
||||
|
||||
|
@ -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,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -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();
|
||||
}
|
||||
|
@ -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
|
||||
|
||||
|
@ -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();
|
||||
}
|
||||
|
@ -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
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user