Skip to content

Commit 753bce3

Browse files
committed
Auto merge of #7407 - m-ou-se:doc-hidden-variants, r=flip1995
Don't suggest doc(hidden) or unstable variants in wildcard lint Clippy's wildcard lint would suggest doc(hidden) and unstable variants for non_exhaustive enums, even though those aren't part of the public interface (yet) and should only be matched on using a `_`, just like potential future additions to the enum. There was already some logic to exclude a *single* doc(hidden) variant. This extends that to all hidden variants, and also hides `#[unstable]` variants. See rust-lang/rust#85746 (comment) This PR includes rust-lang/rust-clippy#7406 as the first commit. Here's the diff that this PR adds on top of that PR: m-ou-se/fork@std-errorkind...m-ou-se:doc-hidden-variants --- *Please write a short comment explaining your change (or "none" for internal only changes)* changelog: No longer suggest unstable and doc(hidden) variants in wildcard lint. wildcard_enum_match_arm, match_wildcard_for_single_variants
2 parents cadb93b + fae7a09 commit 753bce3

8 files changed

+84
-52
lines changed

clippy_lints/src/matches.rs

+6-5
Original file line numberDiff line numberDiff line change
@@ -992,9 +992,9 @@ impl CommonPrefixSearcher<'a> {
992992
}
993993
}
994994

995-
fn is_doc_hidden(cx: &LateContext<'_>, variant_def: &VariantDef) -> bool {
995+
fn is_hidden(cx: &LateContext<'_>, variant_def: &VariantDef) -> bool {
996996
let attrs = cx.tcx.get_attrs(variant_def.def_id);
997-
clippy_utils::attrs::is_doc_hidden(attrs)
997+
clippy_utils::attrs::is_doc_hidden(attrs) || clippy_utils::attrs::is_unstable(attrs)
998998
}
999999

10001000
#[allow(clippy::too_many_lines)]
@@ -1033,7 +1033,8 @@ fn check_wild_enum_match(cx: &LateContext<'_>, ex: &Expr<'_>, arms: &[Arm<'_>])
10331033

10341034
// Accumulate the variants which should be put in place of the wildcard because they're not
10351035
// already covered.
1036-
let mut missing_variants: Vec<_> = adt_def.variants.iter().collect();
1036+
let has_hidden = adt_def.variants.iter().any(|x| is_hidden(cx, x));
1037+
let mut missing_variants: Vec<_> = adt_def.variants.iter().filter(|x| !is_hidden(cx, x)).collect();
10371038

10381039
let mut path_prefix = CommonPrefixSearcher::None;
10391040
for arm in arms {
@@ -1118,7 +1119,7 @@ fn check_wild_enum_match(cx: &LateContext<'_>, ex: &Expr<'_>, arms: &[Arm<'_>])
11181119

11191120
match missing_variants.as_slice() {
11201121
[] => (),
1121-
[x] if !adt_def.is_variant_list_non_exhaustive() && !is_doc_hidden(cx, x) => span_lint_and_sugg(
1122+
[x] if !adt_def.is_variant_list_non_exhaustive() && !has_hidden => span_lint_and_sugg(
11221123
cx,
11231124
MATCH_WILDCARD_FOR_SINGLE_VARIANTS,
11241125
wildcard_span,
@@ -1129,7 +1130,7 @@ fn check_wild_enum_match(cx: &LateContext<'_>, ex: &Expr<'_>, arms: &[Arm<'_>])
11291130
),
11301131
variants => {
11311132
let mut suggestions: Vec<_> = variants.iter().copied().map(format_suggestion).collect();
1132-
let message = if adt_def.is_variant_list_non_exhaustive() {
1133+
let message = if adt_def.is_variant_list_non_exhaustive() || has_hidden {
11331134
suggestions.push("_".into());
11341135
"wildcard matches known variants and will also match future added variants"
11351136
} else {

clippy_utils/src/attrs.rs

+5
Original file line numberDiff line numberDiff line change
@@ -157,3 +157,8 @@ pub fn is_doc_hidden(attrs: &[ast::Attribute]) -> bool {
157157
.filter_map(ast::Attribute::meta_item_list)
158158
.any(|l| attr::list_contains_name(&l, sym::hidden))
159159
}
160+
161+
/// Return true if the attributes contain `#[unstable]`
162+
pub fn is_unstable(attrs: &[ast::Attribute]) -> bool {
163+
attrs.iter().any(|attr| attr.has_name(sym::unstable))
164+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
// Stripped down version of the ErrorKind enum of std
2+
#[non_exhaustive]
3+
pub enum ErrorKind {
4+
NotFound,
5+
PermissionDenied,
6+
#[doc(hidden)]
7+
Uncategorized,
8+
}

tests/ui/match_wildcard_for_single_variants.fixed

+7
Original file line numberDiff line numberDiff line change
@@ -115,9 +115,16 @@ fn main() {
115115
pub enum Enum {
116116
A,
117117
B,
118+
C,
118119
#[doc(hidden)]
119120
__Private,
120121
}
122+
match Enum::A {
123+
Enum::A => (),
124+
Enum::B => (),
125+
Enum::C => (),
126+
_ => (),
127+
}
121128
match Enum::A {
122129
Enum::A => (),
123130
Enum::B => (),

tests/ui/match_wildcard_for_single_variants.rs

+7
Original file line numberDiff line numberDiff line change
@@ -115,9 +115,16 @@ fn main() {
115115
pub enum Enum {
116116
A,
117117
B,
118+
C,
118119
#[doc(hidden)]
119120
__Private,
120121
}
122+
match Enum::A {
123+
Enum::A => (),
124+
Enum::B => (),
125+
Enum::C => (),
126+
_ => (),
127+
}
121128
match Enum::A {
122129
Enum::A => (),
123130
Enum::B => (),

tests/ui/wildcard_enum_match_arm.fixed

+19-20
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
// run-rustfix
2+
// aux-build:non-exhaustive-enum.rs
23

34
#![deny(clippy::wildcard_enum_match_arm)]
45
#![allow(
@@ -11,7 +12,9 @@
1112
clippy::diverging_sub_expression
1213
)]
1314

14-
use std::io::ErrorKind;
15+
extern crate non_exhaustive_enum;
16+
17+
use non_exhaustive_enum::ErrorKind;
1518

1619
#[derive(Clone, Copy, Debug, Eq, PartialEq)]
1720
enum Color {
@@ -77,29 +80,25 @@ fn main() {
7780
let error_kind = ErrorKind::NotFound;
7881
match error_kind {
7982
ErrorKind::NotFound => {},
80-
ErrorKind::PermissionDenied | ErrorKind::ConnectionRefused | ErrorKind::ConnectionReset | ErrorKind::ConnectionAborted | ErrorKind::NotConnected | ErrorKind::AddrInUse | ErrorKind::AddrNotAvailable | ErrorKind::BrokenPipe | ErrorKind::AlreadyExists | ErrorKind::WouldBlock | ErrorKind::InvalidInput | ErrorKind::InvalidData | ErrorKind::TimedOut | ErrorKind::WriteZero | ErrorKind::Interrupted | ErrorKind::Other | ErrorKind::UnexpectedEof | ErrorKind::Unsupported | ErrorKind::OutOfMemory | _ => {},
83+
ErrorKind::PermissionDenied | _ => {},
8184
}
8285
match error_kind {
8386
ErrorKind::NotFound => {},
8487
ErrorKind::PermissionDenied => {},
85-
ErrorKind::ConnectionRefused => {},
86-
ErrorKind::ConnectionReset => {},
87-
ErrorKind::ConnectionAborted => {},
88-
ErrorKind::NotConnected => {},
89-
ErrorKind::AddrInUse => {},
90-
ErrorKind::AddrNotAvailable => {},
91-
ErrorKind::BrokenPipe => {},
92-
ErrorKind::AlreadyExists => {},
93-
ErrorKind::WouldBlock => {},
94-
ErrorKind::InvalidInput => {},
95-
ErrorKind::InvalidData => {},
96-
ErrorKind::TimedOut => {},
97-
ErrorKind::WriteZero => {},
98-
ErrorKind::Interrupted => {},
99-
ErrorKind::Other => {},
100-
ErrorKind::UnexpectedEof => {},
101-
ErrorKind::Unsupported => {},
102-
ErrorKind::OutOfMemory => {},
10388
_ => {},
10489
}
90+
91+
{
92+
#![allow(clippy::manual_non_exhaustive)]
93+
pub enum Enum {
94+
A,
95+
B,
96+
#[doc(hidden)]
97+
__Private,
98+
}
99+
match Enum::A {
100+
Enum::A => (),
101+
Enum::B | _ => (),
102+
}
103+
}
105104
}

tests/ui/wildcard_enum_match_arm.rs

+18-19
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
// run-rustfix
2+
// aux-build:non-exhaustive-enum.rs
23

34
#![deny(clippy::wildcard_enum_match_arm)]
45
#![allow(
@@ -11,7 +12,9 @@
1112
clippy::diverging_sub_expression
1213
)]
1314

14-
use std::io::ErrorKind;
15+
extern crate non_exhaustive_enum;
16+
17+
use non_exhaustive_enum::ErrorKind;
1518

1619
#[derive(Clone, Copy, Debug, Eq, PartialEq)]
1720
enum Color {
@@ -82,24 +85,20 @@ fn main() {
8285
match error_kind {
8386
ErrorKind::NotFound => {},
8487
ErrorKind::PermissionDenied => {},
85-
ErrorKind::ConnectionRefused => {},
86-
ErrorKind::ConnectionReset => {},
87-
ErrorKind::ConnectionAborted => {},
88-
ErrorKind::NotConnected => {},
89-
ErrorKind::AddrInUse => {},
90-
ErrorKind::AddrNotAvailable => {},
91-
ErrorKind::BrokenPipe => {},
92-
ErrorKind::AlreadyExists => {},
93-
ErrorKind::WouldBlock => {},
94-
ErrorKind::InvalidInput => {},
95-
ErrorKind::InvalidData => {},
96-
ErrorKind::TimedOut => {},
97-
ErrorKind::WriteZero => {},
98-
ErrorKind::Interrupted => {},
99-
ErrorKind::Other => {},
100-
ErrorKind::UnexpectedEof => {},
101-
ErrorKind::Unsupported => {},
102-
ErrorKind::OutOfMemory => {},
10388
_ => {},
10489
}
90+
91+
{
92+
#![allow(clippy::manual_non_exhaustive)]
93+
pub enum Enum {
94+
A,
95+
B,
96+
#[doc(hidden)]
97+
__Private,
98+
}
99+
match Enum::A {
100+
Enum::A => (),
101+
_ => (),
102+
}
103+
}
105104
}
+14-8
Original file line numberDiff line numberDiff line change
@@ -1,38 +1,44 @@
11
error: wildcard match will also match any future added variants
2-
--> $DIR/wildcard_enum_match_arm.rs:39:9
2+
--> $DIR/wildcard_enum_match_arm.rs:42:9
33
|
44
LL | _ => eprintln!("Not red"),
55
| ^ help: try this: `Color::Green | Color::Blue | Color::Rgb(..) | Color::Cyan`
66
|
77
note: the lint level is defined here
8-
--> $DIR/wildcard_enum_match_arm.rs:3:9
8+
--> $DIR/wildcard_enum_match_arm.rs:4:9
99
|
1010
LL | #![deny(clippy::wildcard_enum_match_arm)]
1111
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
1212

1313
error: wildcard match will also match any future added variants
14-
--> $DIR/wildcard_enum_match_arm.rs:43:9
14+
--> $DIR/wildcard_enum_match_arm.rs:46:9
1515
|
1616
LL | _not_red => eprintln!("Not red"),
1717
| ^^^^^^^^ help: try this: `_not_red @ Color::Green | _not_red @ Color::Blue | _not_red @ Color::Rgb(..) | _not_red @ Color::Cyan`
1818

1919
error: wildcard match will also match any future added variants
20-
--> $DIR/wildcard_enum_match_arm.rs:47:9
20+
--> $DIR/wildcard_enum_match_arm.rs:50:9
2121
|
2222
LL | not_red => format!("{:?}", not_red),
2323
| ^^^^^^^ help: try this: `not_red @ Color::Green | not_red @ Color::Blue | not_red @ Color::Rgb(..) | not_red @ Color::Cyan`
2424

2525
error: wildcard match will also match any future added variants
26-
--> $DIR/wildcard_enum_match_arm.rs:63:9
26+
--> $DIR/wildcard_enum_match_arm.rs:66:9
2727
|
2828
LL | _ => "No red",
2929
| ^ help: try this: `Color::Red | Color::Green | Color::Blue | Color::Rgb(..) | Color::Cyan`
3030

3131
error: wildcard matches known variants and will also match future added variants
32-
--> $DIR/wildcard_enum_match_arm.rs:80:9
32+
--> $DIR/wildcard_enum_match_arm.rs:83:9
3333
|
3434
LL | _ => {},
35-
| ^ help: try this: `ErrorKind::PermissionDenied | ErrorKind::ConnectionRefused | ErrorKind::ConnectionReset | ErrorKind::ConnectionAborted | ErrorKind::NotConnected | ErrorKind::AddrInUse | ErrorKind::AddrNotAvailable | ErrorKind::BrokenPipe | ErrorKind::AlreadyExists | ErrorKind::WouldBlock | ErrorKind::InvalidInput | ErrorKind::InvalidData | ErrorKind::TimedOut | ErrorKind::WriteZero | ErrorKind::Interrupted | ErrorKind::Other | ErrorKind::UnexpectedEof | ErrorKind::Unsupported | ErrorKind::OutOfMemory | _`
35+
| ^ help: try this: `ErrorKind::PermissionDenied | _`
3636

37-
error: aborting due to 5 previous errors
37+
error: wildcard matches known variants and will also match future added variants
38+
--> $DIR/wildcard_enum_match_arm.rs:101:13
39+
|
40+
LL | _ => (),
41+
| ^ help: try this: `Enum::B | _`
42+
43+
error: aborting due to 6 previous errors
3844

0 commit comments

Comments
 (0)