Make the match checking configurable
This commit is contained in:
parent
173a8e0480
commit
9bd70dbb88
@ -604,7 +604,8 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf:
|
||||
))
|
||||
});
|
||||
store.register_late_pass(move |_| Box::new(matches::Matches::new(msrv)));
|
||||
store.register_late_pass(move |_| Box::new(manual_let_else::ManualLetElse::new(msrv)));
|
||||
let matches_for_let_else = conf.matches_for_let_else;
|
||||
store.register_late_pass(move |_| Box::new(manual_let_else::ManualLetElse::new(msrv, matches_for_let_else)));
|
||||
store.register_early_pass(move || Box::new(manual_non_exhaustive::ManualNonExhaustiveStruct::new(msrv)));
|
||||
store.register_late_pass(move |_| Box::new(manual_non_exhaustive::ManualNonExhaustiveEnum::new(msrv)));
|
||||
store.register_late_pass(move |_| Box::new(manual_strip::ManualStrip::new(msrv)));
|
||||
|
@ -11,6 +11,7 @@
|
||||
use rustc_semver::RustcVersion;
|
||||
use rustc_session::{declare_tool_lint, impl_lint_pass};
|
||||
use rustc_span::symbol::sym;
|
||||
use serde::Deserialize;
|
||||
use std::ops::ControlFlow;
|
||||
|
||||
declare_clippy_lint! {
|
||||
@ -47,12 +48,16 @@
|
||||
|
||||
pub struct ManualLetElse {
|
||||
msrv: Option<RustcVersion>,
|
||||
matches_behaviour: MatchLintBehaviour,
|
||||
}
|
||||
|
||||
impl ManualLetElse {
|
||||
#[must_use]
|
||||
pub fn new(msrv: Option<RustcVersion>) -> Self {
|
||||
Self { msrv }
|
||||
pub fn new(msrv: Option<RustcVersion>, matches_behaviour: MatchLintBehaviour) -> Self {
|
||||
Self {
|
||||
msrv,
|
||||
matches_behaviour,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -89,6 +94,9 @@ fn check_stmt(&mut self, cx: &LateContext<'_>, stmt: &'tcx Stmt<'tcx>) {
|
||||
}
|
||||
},
|
||||
IfLetOrMatch::Match(_match_expr, arms, source) => {
|
||||
if self.matches_behaviour == MatchLintBehaviour::Never {
|
||||
return;
|
||||
}
|
||||
if source != MatchSource::Normal {
|
||||
return;
|
||||
}
|
||||
@ -97,6 +105,7 @@ fn check_stmt(&mut self, cx: &LateContext<'_>, stmt: &'tcx Stmt<'tcx>) {
|
||||
if arms.len() != 2 {
|
||||
return;
|
||||
}
|
||||
let check_types = self.matches_behaviour == MatchLintBehaviour::WellKnownTypes;
|
||||
// We iterate over both arms, trying to find one that is an identity,
|
||||
// one that diverges. Our check needs to work regardless of the order
|
||||
// of both arms.
|
||||
@ -109,7 +118,7 @@ fn check_stmt(&mut self, cx: &LateContext<'_>, stmt: &'tcx Stmt<'tcx>) {
|
||||
}
|
||||
if expr_is_simple_identity(arm.pat, arm.body) {
|
||||
found_identity_arm = true;
|
||||
} else if expr_diverges(cx, arm.body) && pat_allowed_for_else(cx, arm.pat) {
|
||||
} else if expr_diverges(cx, arm.body) && pat_allowed_for_else(cx, arm.pat, check_types) {
|
||||
found_diverging_arm = true;
|
||||
}
|
||||
}
|
||||
@ -178,7 +187,7 @@ fn is_never(cx: &LateContext<'_>, expr: &'_ Expr<'_>) -> bool {
|
||||
.is_some()
|
||||
}
|
||||
|
||||
fn pat_allowed_for_else(cx: &LateContext<'_>, pat: &'_ Pat<'_>) -> bool {
|
||||
fn pat_allowed_for_else(cx: &LateContext<'_>, pat: &'_ Pat<'_>, check_types: bool) -> bool {
|
||||
// Check whether the pattern contains any bindings, as the
|
||||
// binding might potentially be used in the body.
|
||||
// TODO: only look for *used* bindings.
|
||||
@ -188,6 +197,11 @@ fn pat_allowed_for_else(cx: &LateContext<'_>, pat: &'_ Pat<'_>) -> bool {
|
||||
return false;
|
||||
}
|
||||
|
||||
// If we shouldn't check the types, exit early.
|
||||
if !check_types {
|
||||
return true;
|
||||
}
|
||||
|
||||
// Check whether any possibly "unknown" patterns are included,
|
||||
// because users might not know which values some enum has.
|
||||
// Well-known enums are excepted, as we assume people know them.
|
||||
@ -245,3 +259,10 @@ fn expr_is_simple_identity(pat: &'_ Pat<'_>, expr: &'_ Expr<'_>) -> bool {
|
||||
}
|
||||
true
|
||||
}
|
||||
|
||||
#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, Deserialize)]
|
||||
pub enum MatchLintBehaviour {
|
||||
AllTypes,
|
||||
WellKnownTypes,
|
||||
Never,
|
||||
}
|
||||
|
@ -335,6 +335,12 @@ pub(crate) fn get_configuration_metadata() -> Vec<ClippyConfiguration> {
|
||||
///
|
||||
/// Enables verbose mode. Triggers if there is more than one uppercase char next to each other
|
||||
(upper_case_acronyms_aggressive: bool = false),
|
||||
/// Lint: MANUAL_LET_ELSE.
|
||||
///
|
||||
/// Whether the matches should be considered by the lint, and whether there should
|
||||
/// be filtering for common types.
|
||||
(matches_for_let_else: crate::manual_let_else::MatchLintBehaviour =
|
||||
crate::manual_let_else::MatchLintBehaviour::WellKnownTypes),
|
||||
/// Lint: _CARGO_COMMON_METADATA.
|
||||
///
|
||||
/// For internal testing only, ignores the current `publish` settings in the Cargo manifest.
|
||||
|
@ -22,6 +22,7 @@ error: error reading Clippy's configuration file `$DIR/clippy.toml`: unknown fie
|
||||
enum-variant-size-threshold
|
||||
large-error-threshold
|
||||
literal-representation-threshold
|
||||
matches-for-let-else
|
||||
max-fn-params-bools
|
||||
max-include-file-size
|
||||
max-struct-bools
|
||||
|
Loading…
Reference in New Issue
Block a user