about summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--clippy_lints/src/lib.rs3
-rw-r--r--clippy_lints/src/manual_let_else.rs29
-rw-r--r--clippy_lints/src/utils/conf.rs6
-rw-r--r--tests/ui-toml/toml_unknown_key/conf_unknown_key.stderr1
4 files changed, 34 insertions, 5 deletions
diff --git a/clippy_lints/src/lib.rs b/clippy_lints/src/lib.rs
index b261beab793..5716ef71641 100644
--- a/clippy_lints/src/lib.rs
+++ b/clippy_lints/src/lib.rs
@@ -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)));
diff --git a/clippy_lints/src/manual_let_else.rs b/clippy_lints/src/manual_let_else.rs
index e366d6db774..13a734818a7 100644
--- a/clippy_lints/src/manual_let_else.rs
+++ b/clippy_lints/src/manual_let_else.rs
@@ -11,6 +11,7 @@ use rustc_middle::lint::in_external_macro;
 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 @@ declare_clippy_lint! {
 
 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 @@ impl<'tcx> LateLintPass<'tcx> for ManualLetElse {
                 }
             },
             IfLetOrMatch::Match(_match_expr, arms, source) => {
+                if self.matches_behaviour == MatchLintBehaviour::Never {
+                    return;
+                }
                 if source != MatchSource::Normal {
                     return;
                 }
@@ -97,6 +105,7 @@ impl<'tcx> LateLintPass<'tcx> for ManualLetElse {
                 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 @@ impl<'tcx> LateLintPass<'tcx> for ManualLetElse {
                     }
                     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 expr_diverges(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,
+}
diff --git a/clippy_lints/src/utils/conf.rs b/clippy_lints/src/utils/conf.rs
index 1aa86efd38f..ef6de7d333d 100644
--- a/clippy_lints/src/utils/conf.rs
+++ b/clippy_lints/src/utils/conf.rs
@@ -335,6 +335,12 @@ define_Conf! {
     ///
     /// 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.
diff --git a/tests/ui-toml/toml_unknown_key/conf_unknown_key.stderr b/tests/ui-toml/toml_unknown_key/conf_unknown_key.stderr
index 82ee8054132..7db2e11225b 100644
--- a/tests/ui-toml/toml_unknown_key/conf_unknown_key.stderr
+++ b/tests/ui-toml/toml_unknown_key/conf_unknown_key.stderr
@@ -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