about summary refs log tree commit diff
diff options
context:
space:
mode:
authory21 <30553356+y21@users.noreply.github.com>2024-05-02 04:45:45 +0200
committery21 <30553356+y21@users.noreply.github.com>2024-05-02 04:45:45 +0200
commit272413f458151978d7e2185e20d7d23ce81bf6e6 (patch)
tree799c2b2e189a8ed7f4ff84f896890f6af51e746a
parent852a64f8759c23b3ecf2ab975d3f652cffbc27cf (diff)
downloadrust-272413f458151978d7e2185e20d7d23ce81bf6e6.tar.gz
rust-272413f458151978d7e2185e20d7d23ce81bf6e6.zip
allow or patterns for a high enough MSRV in `collapsible_match`
-rw-r--r--clippy_lints/src/matches/collapsible_match.rs23
-rw-r--r--clippy_lints/src/matches/mod.rs23
-rw-r--r--clippy_lints/src/matches/redundant_guards.rs7
-rw-r--r--tests/ui/collapsible_match.rs16
-rw-r--r--tests/ui/collapsible_match.stderr68
5 files changed, 88 insertions, 49 deletions
diff --git a/clippy_lints/src/matches/collapsible_match.rs b/clippy_lints/src/matches/collapsible_match.rs
index 6746920edc5..90cfdecc199 100644
--- a/clippy_lints/src/matches/collapsible_match.rs
+++ b/clippy_lints/src/matches/collapsible_match.rs
@@ -1,3 +1,4 @@
+use clippy_config::msrvs::Msrv;
 use clippy_utils::diagnostics::span_lint_and_then;
 use clippy_utils::higher::IfLetOrMatch;
 use clippy_utils::source::snippet;
@@ -11,12 +12,12 @@ use rustc_hir::{Arm, Expr, HirId, Pat, PatKind};
 use rustc_lint::LateContext;
 use rustc_span::Span;
 
-use super::COLLAPSIBLE_MATCH;
+use super::{pat_contains_disallowed_or, COLLAPSIBLE_MATCH};
 
-pub(super) fn check_match<'tcx>(cx: &LateContext<'tcx>, arms: &'tcx [Arm<'_>]) {
+pub(super) fn check_match<'tcx>(cx: &LateContext<'tcx>, arms: &'tcx [Arm<'_>], msrv: &Msrv) {
     if let Some(els_arm) = arms.iter().rfind(|arm| arm_is_wild_like(cx, arm)) {
         for arm in arms {
-            check_arm(cx, true, arm.pat, arm.body, arm.guard, Some(els_arm.body));
+            check_arm(cx, true, arm.pat, arm.body, arm.guard, Some(els_arm.body), msrv);
         }
     }
 }
@@ -26,8 +27,9 @@ pub(super) fn check_if_let<'tcx>(
     pat: &'tcx Pat<'_>,
     body: &'tcx Expr<'_>,
     else_expr: Option<&'tcx Expr<'_>>,
+    msrv: &Msrv,
 ) {
-    check_arm(cx, false, pat, body, None, else_expr);
+    check_arm(cx, false, pat, body, None, else_expr, msrv);
 }
 
 fn check_arm<'tcx>(
@@ -37,6 +39,7 @@ fn check_arm<'tcx>(
     outer_then_body: &'tcx Expr<'tcx>,
     outer_guard: Option<&'tcx Expr<'tcx>>,
     outer_else_body: Option<&'tcx Expr<'tcx>>,
+    msrv: &Msrv,
 ) {
     let inner_expr = peel_blocks_with_stmt(outer_then_body);
     if let Some(inner) = IfLetOrMatch::parse(cx, inner_expr)
@@ -57,7 +60,7 @@ fn check_arm<'tcx>(
         // match expression must be a local binding
         // match <local> { .. }
         && let Some(binding_id) = path_to_local(peel_ref_operators(cx, inner_scrutinee))
-        && !pat_contains_or(inner_then_pat)
+        && !pat_contains_disallowed_or(inner_then_pat, msrv)
         // the binding must come from the pattern of the containing match arm
         // ..<local>.. => match <local> { .. }
         && let (Some(binding_span), is_innermost_parent_pat_struct)
@@ -142,13 +145,3 @@ fn find_pat_binding_and_is_innermost_parent_pat_struct(pat: &Pat<'_>, hir_id: Hi
     });
     (span, is_innermost_parent_pat_struct)
 }
-
-fn pat_contains_or(pat: &Pat<'_>) -> bool {
-    let mut result = false;
-    pat.walk(|p| {
-        let is_or = matches!(p.kind, PatKind::Or(_));
-        result |= is_or;
-        !is_or
-    });
-    result
-}
diff --git a/clippy_lints/src/matches/mod.rs b/clippy_lints/src/matches/mod.rs
index fae2c4e4af9..ee9f48d71ad 100644
--- a/clippy_lints/src/matches/mod.rs
+++ b/clippy_lints/src/matches/mod.rs
@@ -27,7 +27,7 @@ mod wild_in_or_pats;
 use clippy_config::msrvs::{self, Msrv};
 use clippy_utils::source::walk_span_to_context;
 use clippy_utils::{higher, in_constant, is_direct_expn_of, is_span_match, span_contains_cfg};
-use rustc_hir::{Arm, Expr, ExprKind, LetStmt, MatchSource, Pat};
+use rustc_hir::{Arm, Expr, ExprKind, LetStmt, MatchSource, Pat, PatKind};
 use rustc_lint::{LateContext, LateLintPass, LintContext};
 use rustc_middle::lint::in_external_macro;
 use rustc_session::impl_lint_pass;
@@ -1040,7 +1040,7 @@ impl<'tcx> LateLintPass<'tcx> for Matches {
                 significant_drop_in_scrutinee::check(cx, expr, ex, arms, source);
             }
 
-            collapsible_match::check_match(cx, arms);
+            collapsible_match::check_match(cx, arms, &self.msrv);
             if !from_expansion {
                 // These don't depend on a relationship between multiple arms
                 match_wild_err_arm::check(cx, ex, arms);
@@ -1066,7 +1066,7 @@ impl<'tcx> LateLintPass<'tcx> for Matches {
                     needless_match::check_match(cx, ex, arms, expr);
                     match_on_vec_items::check(cx, ex);
                     match_str_case_mismatch::check(cx, ex, arms);
-                    redundant_guards::check(cx, arms);
+                    redundant_guards::check(cx, arms, &self.msrv);
 
                     if !in_constant(cx, expr.hir_id) {
                         manual_unwrap_or::check(cx, expr, ex, arms);
@@ -1083,7 +1083,7 @@ impl<'tcx> LateLintPass<'tcx> for Matches {
                 match_ref_pats::check(cx, ex, arms.iter().map(|el| el.pat), expr);
             }
         } else if let Some(if_let) = higher::IfLet::hir(cx, expr) {
-            collapsible_match::check_if_let(cx, if_let.let_pat, if_let.if_then, if_let.if_else);
+            collapsible_match::check_if_let(cx, if_let.let_pat, if_let.if_then, if_let.if_else, &self.msrv);
             if !from_expansion {
                 if let Some(else_expr) = if_let.if_else {
                     if self.msrv.meets(msrvs::MATCHES_MACRO) {
@@ -1195,3 +1195,18 @@ fn contains_cfg_arm(cx: &LateContext<'_>, e: &Expr<'_>, scrutinee: &Expr<'_>, ar
         Err(()) => true,
     }
 }
+
+/// Checks if `pat` contains OR patterns that cannot be nested due to a too low MSRV.
+fn pat_contains_disallowed_or(pat: &Pat<'_>, msrv: &Msrv) -> bool {
+    if msrv.meets(msrvs::OR_PATTERNS) {
+        return false;
+    }
+
+    let mut result = false;
+    pat.walk(|p| {
+        let is_or = matches!(p.kind, PatKind::Or(_));
+        result |= is_or;
+        !is_or
+    });
+    result
+}
diff --git a/clippy_lints/src/matches/redundant_guards.rs b/clippy_lints/src/matches/redundant_guards.rs
index 50cbccc3968..984aa3d7370 100644
--- a/clippy_lints/src/matches/redundant_guards.rs
+++ b/clippy_lints/src/matches/redundant_guards.rs
@@ -1,3 +1,4 @@
+use clippy_config::msrvs::Msrv;
 use clippy_utils::diagnostics::span_lint_and_then;
 use clippy_utils::source::snippet;
 use clippy_utils::visitors::{for_each_expr, is_local_used};
@@ -12,9 +13,9 @@ use rustc_span::{Span, Symbol};
 use std::borrow::Cow;
 use std::ops::ControlFlow;
 
-use super::REDUNDANT_GUARDS;
+use super::{pat_contains_disallowed_or, REDUNDANT_GUARDS};
 
-pub(super) fn check<'tcx>(cx: &LateContext<'tcx>, arms: &'tcx [Arm<'tcx>]) {
+pub(super) fn check<'tcx>(cx: &LateContext<'tcx>, arms: &'tcx [Arm<'tcx>], msrv: &Msrv) {
     for outer_arm in arms {
         let Some(guard) = outer_arm.guard else {
             continue;
@@ -35,6 +36,7 @@ pub(super) fn check<'tcx>(cx: &LateContext<'tcx>, arms: &'tcx [Arm<'tcx>]) {
             MatchSource::Normal,
         ) = guard.kind
             && let Some(binding) = get_pat_binding(cx, scrutinee, outer_arm)
+            && !pat_contains_disallowed_or(&arm.pat, msrv)
         {
             let pat_span = match (arm.pat.kind, binding.byref_ident) {
                 (PatKind::Ref(pat, _), Some(_)) => pat.span,
@@ -53,6 +55,7 @@ pub(super) fn check<'tcx>(cx: &LateContext<'tcx>, arms: &'tcx [Arm<'tcx>]) {
         // `Some(x) if let Some(2) = x`
         else if let ExprKind::Let(let_expr) = guard.kind
             && let Some(binding) = get_pat_binding(cx, let_expr.init, outer_arm)
+            && !pat_contains_disallowed_or(&let_expr.pat, msrv)
         {
             let pat_span = match (let_expr.pat.kind, binding.byref_ident) {
                 (PatKind::Ref(pat, _), Some(_)) => pat.span,
diff --git a/tests/ui/collapsible_match.rs b/tests/ui/collapsible_match.rs
index 7501fd2b0bd..2264b560791 100644
--- a/tests/ui/collapsible_match.rs
+++ b/tests/ui/collapsible_match.rs
@@ -4,7 +4,8 @@
     clippy::needless_return,
     clippy::no_effect,
     clippy::single_match,
-    clippy::uninlined_format_args
+    clippy::uninlined_format_args,
+    clippy::let_unit_value
 )]
 
 fn lint_cases(opt_opt: Option<Option<u32>>, res_opt: Result<Option<u32>, String>) {
@@ -238,13 +239,22 @@ fn negative_cases(res_opt: Result<Option<u32>, String>, res_res: Result<Result<u
         },
         _ => return,
     }
-    match make::<Option<E<u32>>>() {
+    #[clippy::msrv = "1.52.0"]
+    let _ = match make::<Option<E<u32>>>() {
         Some(val) => match val {
             E::A(val) | E::B(val) => foo(val),
             _ => return,
         },
         _ => return,
-    }
+    };
+    #[clippy::msrv = "1.53.0"]
+    let _ = match make::<Option<E<u32>>>() {
+        Some(val) => match val {
+            E::A(val) | E::B(val) => foo(val),
+            _ => return,
+        },
+        _ => return,
+    };
     if let Ok(val) = res_opt {
         if let Some(n) = val {
             let _ = || {
diff --git a/tests/ui/collapsible_match.stderr b/tests/ui/collapsible_match.stderr
index 46b484ab05c..01944baee79 100644
--- a/tests/ui/collapsible_match.stderr
+++ b/tests/ui/collapsible_match.stderr
@@ -1,5 +1,5 @@
 error: this `match` can be collapsed into the outer `match`
-  --> tests/ui/collapsible_match.rs:13:20
+  --> tests/ui/collapsible_match.rs:14:20
    |
 LL |           Ok(val) => match val {
    |  ____________________^
@@ -10,7 +10,7 @@ LL | |         },
    | |_________^
    |
 help: the outer pattern can be modified to include the inner pattern
-  --> tests/ui/collapsible_match.rs:13:12
+  --> tests/ui/collapsible_match.rs:14:12
    |
 LL |         Ok(val) => match val {
    |            ^^^ replace this binding
@@ -21,7 +21,7 @@ LL |             Some(n) => foo(n),
    = help: to override `-D warnings` add `#[allow(clippy::collapsible_match)]`
 
 error: this `match` can be collapsed into the outer `match`
-  --> tests/ui/collapsible_match.rs:23:20
+  --> tests/ui/collapsible_match.rs:24:20
    |
 LL |           Ok(val) => match val {
    |  ____________________^
@@ -32,7 +32,7 @@ LL | |         },
    | |_________^
    |
 help: the outer pattern can be modified to include the inner pattern
-  --> tests/ui/collapsible_match.rs:23:12
+  --> tests/ui/collapsible_match.rs:24:12
    |
 LL |         Ok(val) => match val {
    |            ^^^ replace this binding
@@ -41,7 +41,7 @@ LL |             Some(n) => foo(n),
    |             ^^^^^^^ with this pattern
 
 error: this `if let` can be collapsed into the outer `if let`
-  --> tests/ui/collapsible_match.rs:33:9
+  --> tests/ui/collapsible_match.rs:34:9
    |
 LL | /         if let Some(n) = val {
 LL | |
@@ -50,7 +50,7 @@ LL | |         }
    | |_________^
    |
 help: the outer pattern can be modified to include the inner pattern
-  --> tests/ui/collapsible_match.rs:32:15
+  --> tests/ui/collapsible_match.rs:33:15
    |
 LL |     if let Ok(val) = res_opt {
    |               ^^^ replace this binding
@@ -58,7 +58,7 @@ LL |         if let Some(n) = val {
    |                ^^^^^^^ with this pattern
 
 error: this `if let` can be collapsed into the outer `if let`
-  --> tests/ui/collapsible_match.rs:41:9
+  --> tests/ui/collapsible_match.rs:42:9
    |
 LL | /         if let Some(n) = val {
 LL | |
@@ -69,7 +69,7 @@ LL | |         }
    | |_________^
    |
 help: the outer pattern can be modified to include the inner pattern
-  --> tests/ui/collapsible_match.rs:40:15
+  --> tests/ui/collapsible_match.rs:41:15
    |
 LL |     if let Ok(val) = res_opt {
    |               ^^^ replace this binding
@@ -77,7 +77,7 @@ LL |         if let Some(n) = val {
    |                ^^^^^^^ with this pattern
 
 error: this `match` can be collapsed into the outer `if let`
-  --> tests/ui/collapsible_match.rs:53:9
+  --> tests/ui/collapsible_match.rs:54:9
    |
 LL | /         match val {
 LL | |
@@ -87,7 +87,7 @@ LL | |         }
    | |_________^
    |
 help: the outer pattern can be modified to include the inner pattern
-  --> tests/ui/collapsible_match.rs:52:15
+  --> tests/ui/collapsible_match.rs:53:15
    |
 LL |     if let Ok(val) = res_opt {
    |               ^^^ replace this binding
@@ -96,7 +96,7 @@ LL |             Some(n) => foo(n),
    |             ^^^^^^^ with this pattern
 
 error: this `if let` can be collapsed into the outer `match`
-  --> tests/ui/collapsible_match.rs:63:13
+  --> tests/ui/collapsible_match.rs:64:13
    |
 LL | /             if let Some(n) = val {
 LL | |
@@ -105,7 +105,7 @@ LL | |             }
    | |_____________^
    |
 help: the outer pattern can be modified to include the inner pattern
-  --> tests/ui/collapsible_match.rs:62:12
+  --> tests/ui/collapsible_match.rs:63:12
    |
 LL |         Ok(val) => {
    |            ^^^ replace this binding
@@ -113,7 +113,7 @@ LL |             if let Some(n) = val {
    |                    ^^^^^^^ with this pattern
 
 error: this `match` can be collapsed into the outer `if let`
-  --> tests/ui/collapsible_match.rs:73:9
+  --> tests/ui/collapsible_match.rs:74:9
    |
 LL | /         match val {
 LL | |
@@ -123,7 +123,7 @@ LL | |         }
    | |_________^
    |
 help: the outer pattern can be modified to include the inner pattern
-  --> tests/ui/collapsible_match.rs:72:15
+  --> tests/ui/collapsible_match.rs:73:15
    |
 LL |     if let Ok(val) = res_opt {
    |               ^^^ replace this binding
@@ -132,7 +132,7 @@ LL |             Some(n) => foo(n),
    |             ^^^^^^^ with this pattern
 
 error: this `if let` can be collapsed into the outer `match`
-  --> tests/ui/collapsible_match.rs:85:13
+  --> tests/ui/collapsible_match.rs:86:13
    |
 LL | /             if let Some(n) = val {
 LL | |
@@ -143,7 +143,7 @@ LL | |             }
    | |_____________^
    |
 help: the outer pattern can be modified to include the inner pattern
-  --> tests/ui/collapsible_match.rs:84:12
+  --> tests/ui/collapsible_match.rs:85:12
    |
 LL |         Ok(val) => {
    |            ^^^ replace this binding
@@ -151,7 +151,7 @@ LL |             if let Some(n) = val {
    |                    ^^^^^^^ with this pattern
 
 error: this `match` can be collapsed into the outer `match`
-  --> tests/ui/collapsible_match.rs:97:20
+  --> tests/ui/collapsible_match.rs:98:20
    |
 LL |           Ok(val) => match val {
    |  ____________________^
@@ -162,7 +162,7 @@ LL | |         },
    | |_________^
    |
 help: the outer pattern can be modified to include the inner pattern
-  --> tests/ui/collapsible_match.rs:97:12
+  --> tests/ui/collapsible_match.rs:98:12
    |
 LL |         Ok(val) => match val {
    |            ^^^ replace this binding
@@ -171,7 +171,7 @@ LL |             Some(n) => foo(n),
    |             ^^^^^^^ with this pattern
 
 error: this `match` can be collapsed into the outer `match`
-  --> tests/ui/collapsible_match.rs:107:22
+  --> tests/ui/collapsible_match.rs:108:22
    |
 LL |           Some(val) => match val {
    |  ______________________^
@@ -182,7 +182,7 @@ LL | |         },
    | |_________^
    |
 help: the outer pattern can be modified to include the inner pattern
-  --> tests/ui/collapsible_match.rs:107:14
+  --> tests/ui/collapsible_match.rs:108:14
    |
 LL |         Some(val) => match val {
    |              ^^^ replace this binding
@@ -190,8 +190,26 @@ LL |
 LL |             Some(n) => foo(n),
    |             ^^^^^^^ with this pattern
 
+error: this `match` can be collapsed into the outer `match`
+  --> tests/ui/collapsible_match.rs:252:22
+   |
+LL |           Some(val) => match val {
+   |  ______________________^
+LL | |             E::A(val) | E::B(val) => foo(val),
+LL | |             _ => return,
+LL | |         },
+   | |_________^
+   |
+help: the outer pattern can be modified to include the inner pattern
+  --> tests/ui/collapsible_match.rs:252:14
+   |
+LL |         Some(val) => match val {
+   |              ^^^ replace this binding
+LL |             E::A(val) | E::B(val) => foo(val),
+   |             ^^^^^^^^^^^^^^^^^^^^^ with this pattern
+
 error: this `if let` can be collapsed into the outer `if let`
-  --> tests/ui/collapsible_match.rs:273:9
+  --> tests/ui/collapsible_match.rs:283:9
    |
 LL | /         if let Some(u) = a {
 LL | |
@@ -200,7 +218,7 @@ LL | |         }
    | |_________^
    |
 help: the outer pattern can be modified to include the inner pattern
-  --> tests/ui/collapsible_match.rs:272:27
+  --> tests/ui/collapsible_match.rs:282:27
    |
 LL |     if let Issue9647::A { a, .. } = x {
    |                           ^ replace this binding
@@ -208,7 +226,7 @@ LL |         if let Some(u) = a {
    |                ^^^^^^^ with this pattern, prefixed by a:
 
 error: this `if let` can be collapsed into the outer `if let`
-  --> tests/ui/collapsible_match.rs:282:9
+  --> tests/ui/collapsible_match.rs:292:9
    |
 LL | /         if let Some(u) = a {
 LL | |
@@ -217,12 +235,12 @@ LL | |         }
    | |_________^
    |
 help: the outer pattern can be modified to include the inner pattern
-  --> tests/ui/collapsible_match.rs:281:35
+  --> tests/ui/collapsible_match.rs:291:35
    |
 LL |     if let Issue9647::A { a: Some(a), .. } = x {
    |                                   ^ replace this binding
 LL |         if let Some(u) = a {
    |                ^^^^^^^ with this pattern
 
-error: aborting due to 12 previous errors
+error: aborting due to 13 previous errors