Skip to content

Commit 94e4b5e

Browse files
committed
Add the redundant_wildcard_enum_match lint
1 parent e1842b0 commit 94e4b5e

File tree

7 files changed

+104
-0
lines changed

7 files changed

+104
-0
lines changed

CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1439,6 +1439,7 @@ Released 2018-09-13
14391439
[`match_same_arms`]: https://rust-lang.github.io/rust-clippy/master/index.html#match_same_arms
14401440
[`match_single_binding`]: https://rust-lang.github.io/rust-clippy/master/index.html#match_single_binding
14411441
[`match_wild_err_arm`]: https://rust-lang.github.io/rust-clippy/master/index.html#match_wild_err_arm
1442+
[`match_wildcard_for_single_variants`]: https://rust-lang.github.io/rust-clippy/master/index.html#match_wildcard_for_single_variants
14421443
[`maybe_infinite_iter`]: https://rust-lang.github.io/rust-clippy/master/index.html#maybe_infinite_iter
14431444
[`mem_discriminant_non_enum`]: https://rust-lang.github.io/rust-clippy/master/index.html#mem_discriminant_non_enum
14441445
[`mem_forget`]: https://rust-lang.github.io/rust-clippy/master/index.html#mem_forget

clippy_lints/src/lib.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -641,6 +641,7 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf:
641641
&matches::MATCH_OVERLAPPING_ARM,
642642
&matches::MATCH_REF_PATS,
643643
&matches::MATCH_SINGLE_BINDING,
644+
&matches::MATCH_WILDCARD_FOR_SINGLE_VARIANTS,
644645
&matches::MATCH_WILD_ERR_ARM,
645646
&matches::REST_PAT_IN_FULLY_BOUND_STRUCTS,
646647
&matches::SINGLE_MATCH,
@@ -1147,6 +1148,7 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf:
11471148
LintId::of(&macro_use::MACRO_USE_IMPORTS),
11481149
LintId::of(&match_on_vec_items::MATCH_ON_VEC_ITEMS),
11491150
LintId::of(&matches::MATCH_BOOL),
1151+
LintId::of(&matches::MATCH_WILDCARD_FOR_SINGLE_VARIANTS),
11501152
LintId::of(&matches::SINGLE_MATCH_ELSE),
11511153
LintId::of(&methods::FILTER_MAP),
11521154
LintId::of(&methods::FILTER_MAP_NEXT),

clippy_lints/src/matches.rs

Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -229,6 +229,40 @@ declare_clippy_lint! {
229229
"a wildcard enum match arm using `_`"
230230
}
231231

232+
declare_clippy_lint! {
233+
/// **What it does:** Checks for wildcard enum matches for a single variant.
234+
///
235+
/// **Why is this bad?** New enum variants added by library updates can be missed.
236+
///
237+
/// **Known problems:** Suggested replacements may not use correct path to enum
238+
/// if it's not present in the current scope.
239+
///
240+
/// **Example:**
241+
///
242+
/// ```rust
243+
/// # enum Foo { A, B, C }
244+
/// # let x = Foo::B;
245+
/// match x {
246+
/// Foo::A => {},
247+
/// Foo::B => {},
248+
/// _ => {},
249+
/// }
250+
/// ```
251+
/// Use instead:
252+
/// ```rust
253+
/// # enum Foo { A, B, C }
254+
/// # let x = Foo::B;
255+
/// match x {
256+
/// Foo::A => {},
257+
/// Foo::B => {},
258+
/// Foo::C => {},
259+
/// }
260+
/// ```
261+
pub MATCH_WILDCARD_FOR_SINGLE_VARIANTS,
262+
pedantic,
263+
"a wildcard enum match for a single variant"
264+
}
265+
232266
declare_clippy_lint! {
233267
/// **What it does:** Checks for wildcard pattern used with others patterns in same match arm.
234268
///
@@ -356,6 +390,7 @@ impl_lint_pass!(Matches => [
356390
MATCH_WILD_ERR_ARM,
357391
MATCH_AS_REF,
358392
WILDCARD_ENUM_MATCH_ARM,
393+
MATCH_WILDCARD_FOR_SINGLE_VARIANTS,
359394
WILDCARD_IN_OR_PATTERNS,
360395
MATCH_SINGLE_BINDING,
361396
INFALLIBLE_DESTRUCTURING_MATCH,
@@ -766,6 +801,19 @@ fn check_wild_enum_match(cx: &LateContext<'_, '_>, ex: &Expr<'_>, arms: &[Arm<'_
766801
}
767802
}
768803

804+
if suggestion.len() == 1 {
805+
// No need to check for non-exhaustive enum as in that case len would be greater than 1
806+
span_lint_and_sugg(
807+
cx,
808+
MATCH_WILDCARD_FOR_SINGLE_VARIANTS,
809+
wildcard_span,
810+
message,
811+
"try this",
812+
suggestion[0].clone(),
813+
Applicability::MachineApplicable,
814+
)
815+
};
816+
769817
span_lint_and_sugg(
770818
cx,
771819
WILDCARD_ENUM_MATCH_ARM,

src/lintlist/mod.rs

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1200,6 +1200,13 @@ pub static ref ALL_LINTS: Vec<Lint> = vec![
12001200
deprecation: None,
12011201
module: "matches",
12021202
},
1203+
Lint {
1204+
name: "match_wildcard_for_single_variants",
1205+
group: "pedantic",
1206+
desc: "a wildcard enum match for a single variant",
1207+
deprecation: None,
1208+
module: "matches",
1209+
},
12031210
Lint {
12041211
name: "maybe_infinite_iter",
12051212
group: "pedantic",
Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
// run-rustfix
2+
3+
#![warn(clippy::match_wildcard_for_single_variants)]
4+
#![allow(dead_code)]
5+
6+
enum Foo {
7+
A,
8+
B,
9+
C,
10+
}
11+
12+
fn main() {
13+
match Foo::A {
14+
Foo::A => {},
15+
Foo::B => {},
16+
Foo::C => {},
17+
}
18+
}
Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
// run-rustfix
2+
3+
#![warn(clippy::match_wildcard_for_single_variants)]
4+
#![allow(dead_code)]
5+
6+
enum Foo {
7+
A,
8+
B,
9+
C,
10+
}
11+
12+
fn main() {
13+
match Foo::A {
14+
Foo::A => {},
15+
Foo::B => {},
16+
_ => {},
17+
}
18+
}
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
error: wildcard match will miss any future added variants
2+
--> $DIR/match_wildcard_for_single_variants.rs:16:9
3+
|
4+
LL | _ => {},
5+
| ^ help: try this: `Foo::C`
6+
|
7+
= note: `-D clippy::match-wildcard-for-single-variants` implied by `-D warnings`
8+
9+
error: aborting due to previous error
10+

0 commit comments

Comments
 (0)