Add the redundant_wildcard_enum_match lint

This commit is contained in:
Vardan Margaryan 2020-05-10 00:08:41 +03:00
parent e1842b0cac
commit 94e4b5ec31
7 changed files with 104 additions and 0 deletions

View File

@ -1439,6 +1439,7 @@ Released 2018-09-13
[`match_same_arms`]: https://rust-lang.github.io/rust-clippy/master/index.html#match_same_arms [`match_same_arms`]: https://rust-lang.github.io/rust-clippy/master/index.html#match_same_arms
[`match_single_binding`]: https://rust-lang.github.io/rust-clippy/master/index.html#match_single_binding [`match_single_binding`]: https://rust-lang.github.io/rust-clippy/master/index.html#match_single_binding
[`match_wild_err_arm`]: https://rust-lang.github.io/rust-clippy/master/index.html#match_wild_err_arm [`match_wild_err_arm`]: https://rust-lang.github.io/rust-clippy/master/index.html#match_wild_err_arm
[`match_wildcard_for_single_variants`]: https://rust-lang.github.io/rust-clippy/master/index.html#match_wildcard_for_single_variants
[`maybe_infinite_iter`]: https://rust-lang.github.io/rust-clippy/master/index.html#maybe_infinite_iter [`maybe_infinite_iter`]: https://rust-lang.github.io/rust-clippy/master/index.html#maybe_infinite_iter
[`mem_discriminant_non_enum`]: https://rust-lang.github.io/rust-clippy/master/index.html#mem_discriminant_non_enum [`mem_discriminant_non_enum`]: https://rust-lang.github.io/rust-clippy/master/index.html#mem_discriminant_non_enum
[`mem_forget`]: https://rust-lang.github.io/rust-clippy/master/index.html#mem_forget [`mem_forget`]: https://rust-lang.github.io/rust-clippy/master/index.html#mem_forget

View File

@ -641,6 +641,7 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf:
&matches::MATCH_OVERLAPPING_ARM, &matches::MATCH_OVERLAPPING_ARM,
&matches::MATCH_REF_PATS, &matches::MATCH_REF_PATS,
&matches::MATCH_SINGLE_BINDING, &matches::MATCH_SINGLE_BINDING,
&matches::MATCH_WILDCARD_FOR_SINGLE_VARIANTS,
&matches::MATCH_WILD_ERR_ARM, &matches::MATCH_WILD_ERR_ARM,
&matches::REST_PAT_IN_FULLY_BOUND_STRUCTS, &matches::REST_PAT_IN_FULLY_BOUND_STRUCTS,
&matches::SINGLE_MATCH, &matches::SINGLE_MATCH,
@ -1147,6 +1148,7 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf:
LintId::of(&macro_use::MACRO_USE_IMPORTS), LintId::of(&macro_use::MACRO_USE_IMPORTS),
LintId::of(&match_on_vec_items::MATCH_ON_VEC_ITEMS), LintId::of(&match_on_vec_items::MATCH_ON_VEC_ITEMS),
LintId::of(&matches::MATCH_BOOL), LintId::of(&matches::MATCH_BOOL),
LintId::of(&matches::MATCH_WILDCARD_FOR_SINGLE_VARIANTS),
LintId::of(&matches::SINGLE_MATCH_ELSE), LintId::of(&matches::SINGLE_MATCH_ELSE),
LintId::of(&methods::FILTER_MAP), LintId::of(&methods::FILTER_MAP),
LintId::of(&methods::FILTER_MAP_NEXT), LintId::of(&methods::FILTER_MAP_NEXT),

View File

@ -229,6 +229,40 @@
"a wildcard enum match arm using `_`" "a wildcard enum match arm using `_`"
} }
declare_clippy_lint! {
/// **What it does:** Checks for wildcard enum matches for a single variant.
///
/// **Why is this bad?** New enum variants added by library updates can be missed.
///
/// **Known problems:** Suggested replacements may not use correct path to enum
/// if it's not present in the current scope.
///
/// **Example:**
///
/// ```rust
/// # enum Foo { A, B, C }
/// # let x = Foo::B;
/// match x {
/// Foo::A => {},
/// Foo::B => {},
/// _ => {},
/// }
/// ```
/// Use instead:
/// ```rust
/// # enum Foo { A, B, C }
/// # let x = Foo::B;
/// match x {
/// Foo::A => {},
/// Foo::B => {},
/// Foo::C => {},
/// }
/// ```
pub MATCH_WILDCARD_FOR_SINGLE_VARIANTS,
pedantic,
"a wildcard enum match for a single variant"
}
declare_clippy_lint! { declare_clippy_lint! {
/// **What it does:** Checks for wildcard pattern used with others patterns in same match arm. /// **What it does:** Checks for wildcard pattern used with others patterns in same match arm.
/// ///
@ -356,6 +390,7 @@ pub struct Matches {
MATCH_WILD_ERR_ARM, MATCH_WILD_ERR_ARM,
MATCH_AS_REF, MATCH_AS_REF,
WILDCARD_ENUM_MATCH_ARM, WILDCARD_ENUM_MATCH_ARM,
MATCH_WILDCARD_FOR_SINGLE_VARIANTS,
WILDCARD_IN_OR_PATTERNS, WILDCARD_IN_OR_PATTERNS,
MATCH_SINGLE_BINDING, MATCH_SINGLE_BINDING,
INFALLIBLE_DESTRUCTURING_MATCH, INFALLIBLE_DESTRUCTURING_MATCH,
@ -766,6 +801,19 @@ fn check_wild_enum_match(cx: &LateContext<'_, '_>, ex: &Expr<'_>, arms: &[Arm<'_
} }
} }
if suggestion.len() == 1 {
// No need to check for non-exhaustive enum as in that case len would be greater than 1
span_lint_and_sugg(
cx,
MATCH_WILDCARD_FOR_SINGLE_VARIANTS,
wildcard_span,
message,
"try this",
suggestion[0].clone(),
Applicability::MachineApplicable,
)
};
span_lint_and_sugg( span_lint_and_sugg(
cx, cx,
WILDCARD_ENUM_MATCH_ARM, WILDCARD_ENUM_MATCH_ARM,

View File

@ -1200,6 +1200,13 @@
deprecation: None, deprecation: None,
module: "matches", module: "matches",
}, },
Lint {
name: "match_wildcard_for_single_variants",
group: "pedantic",
desc: "a wildcard enum match for a single variant",
deprecation: None,
module: "matches",
},
Lint { Lint {
name: "maybe_infinite_iter", name: "maybe_infinite_iter",
group: "pedantic", group: "pedantic",

View File

@ -0,0 +1,18 @@
// run-rustfix
#![warn(clippy::match_wildcard_for_single_variants)]
#![allow(dead_code)]
enum Foo {
A,
B,
C,
}
fn main() {
match Foo::A {
Foo::A => {},
Foo::B => {},
Foo::C => {},
}
}

View File

@ -0,0 +1,18 @@
// run-rustfix
#![warn(clippy::match_wildcard_for_single_variants)]
#![allow(dead_code)]
enum Foo {
A,
B,
C,
}
fn main() {
match Foo::A {
Foo::A => {},
Foo::B => {},
_ => {},
}
}

View File

@ -0,0 +1,10 @@
error: wildcard match will miss any future added variants
--> $DIR/match_wildcard_for_single_variants.rs:16:9
|
LL | _ => {},
| ^ help: try this: `Foo::C`
|
= note: `-D clippy::match-wildcard-for-single-variants` implied by `-D warnings`
error: aborting due to previous error