about summary refs log tree commit diff
diff options
context:
space:
mode:
authorAlex Macleod <alex@macleod.io>2025-05-26 21:03:39 +0000
committerGitHub <noreply@github.com>2025-05-26 21:03:39 +0000
commit3927a61a546b0f134b3790d66ef73f1960e8bc8b (patch)
tree99b96b97d22dd70e5ca3e825784a1f7d9042f2fc
parentb719f99090dd1472feba81bf52b6ac2e67bb0b30 (diff)
parent816fa0a9234f8e369542d949db74258e43ea10b9 (diff)
downloadrust-3927a61a546b0f134b3790d66ef73f1960e8bc8b.tar.gz
rust-3927a61a546b0f134b3790d66ef73f1960e8bc8b.zip
[`manual_flatten`]: Fix with nested `Some` or `Ok` pattern (#14846)
changelog: [`manual_flatten`]: fix with nested `Some` or `Ok` pattern
fixes rust-lang/rust-clippy#6776
-rw-r--r--clippy_lints/src/loops/manual_flatten.rs5
-rw-r--r--tests/ui/manual_flatten.rs7
-rw-r--r--tests/ui/manual_flatten.stderr4
3 files changed, 12 insertions, 4 deletions
diff --git a/clippy_lints/src/loops/manual_flatten.rs b/clippy_lints/src/loops/manual_flatten.rs
index 9b6f97b9a2e..81f14b7b2b0 100644
--- a/clippy_lints/src/loops/manual_flatten.rs
+++ b/clippy_lints/src/loops/manual_flatten.rs
@@ -3,7 +3,7 @@ use super::utils::make_iterator_snippet;
 use clippy_utils::diagnostics::span_lint_and_then;
 use clippy_utils::msrvs::{self, Msrv};
 use clippy_utils::visitors::is_local_used;
-use clippy_utils::{higher, path_to_local_id, peel_blocks_with_stmt};
+use clippy_utils::{higher, is_refutable, path_to_local_id, peel_blocks_with_stmt};
 use rustc_errors::Applicability;
 use rustc_hir::def::{DefKind, Res};
 use rustc_hir::{Expr, Pat, PatKind};
@@ -28,7 +28,7 @@ pub(super) fn check<'tcx>(
         && let PatKind::Binding(_, pat_hir_id, _, _) = pat.kind
         && path_to_local_id(let_expr, pat_hir_id)
         // Ensure the `if let` statement is for the `Some` variant of `Option` or the `Ok` variant of `Result`
-        && let PatKind::TupleStruct(ref qpath, _, _) = let_pat.kind
+        && let PatKind::TupleStruct(ref qpath, [inner_pat], _) = let_pat.kind
         && let Res::Def(DefKind::Ctor(..), ctor_id) = cx.qpath_res(qpath, let_pat.hir_id)
         && let Some(variant_id) = cx.tcx.opt_parent(ctor_id)
         && let some_ctor = cx.tcx.lang_items().option_some_variant() == Some(variant_id)
@@ -37,6 +37,7 @@ pub(super) fn check<'tcx>(
         // Ensure expr in `if let` is not used afterwards
         && !is_local_used(cx, if_then, pat_hir_id)
         && msrv.meets(cx, msrvs::ITER_FLATTEN)
+        && !is_refutable(cx, inner_pat)
     {
         let if_let_type = if some_ctor { "Some" } else { "Ok" };
         // Prepare the error message
diff --git a/tests/ui/manual_flatten.rs b/tests/ui/manual_flatten.rs
index 97f35c36e24..f1a0053ef38 100644
--- a/tests/ui/manual_flatten.rs
+++ b/tests/ui/manual_flatten.rs
@@ -123,6 +123,13 @@ fn main() {
         println!("{}", n);
     }
 
+    // Using nested `Some` pattern should not trigger the lint
+    for n in vec![Some((1, Some(2)))] {
+        if let Some((_, Some(n))) = n {
+            println!("{}", n);
+        }
+    }
+
     run_unformatted_tests();
 }
 
diff --git a/tests/ui/manual_flatten.stderr b/tests/ui/manual_flatten.stderr
index 5ab25658017..9a846fe17f3 100644
--- a/tests/ui/manual_flatten.stderr
+++ b/tests/ui/manual_flatten.stderr
@@ -178,7 +178,7 @@ LL | |         }
    | |_________^
 
 error: unnecessary `if let` since only the `Some` variant of the iterator element is used
-  --> tests/ui/manual_flatten.rs:132:5
+  --> tests/ui/manual_flatten.rs:139:5
    |
 LL | /     for n in vec![
 LL | |
@@ -189,7 +189,7 @@ LL | |     }
    | |_____^
    |
 help: remove the `if let` statement in the for loop and then...
-  --> tests/ui/manual_flatten.rs:139:9
+  --> tests/ui/manual_flatten.rs:146:9
    |
 LL | /         if let Some(n) = n {
 LL | |             println!("{:?}", n);