about summary refs log tree commit diff
diff options
context:
space:
mode:
authorBoot0x7c00 <boot0x7c00@outlook.com>2025-07-15 03:02:06 +0000
committerBoot0x7c00 <boot0x7c00@outlook.com>2025-07-15 03:02:06 +0000
commitc20faa051284fa17ac2b67685129edf518d46ad8 (patch)
treefffff6b04d1e3979a29e45ef7702a43459b0fbce
parentfdf37fc7e715e23f27ddb804082209b39a5061fa (diff)
downloadrust-c20faa051284fa17ac2b67685129edf518d46ad8.tar.gz
rust-c20faa051284fa17ac2b67685129edf518d46ad8.zip
fix `needless_for_each` suggests wrongly for macros
-rw-r--r--clippy_lints/src/needless_for_each.rs21
-rw-r--r--tests/ui/needless_for_each_fixable.fixed6
-rw-r--r--tests/ui/needless_for_each_fixable.rs6
-rw-r--r--tests/ui/needless_for_each_fixable.stderr8
4 files changed, 32 insertions, 9 deletions
diff --git a/clippy_lints/src/needless_for_each.rs b/clippy_lints/src/needless_for_each.rs
index 6a7c8436bad..a67545e419c 100644
--- a/clippy_lints/src/needless_for_each.rs
+++ b/clippy_lints/src/needless_for_each.rs
@@ -6,7 +6,7 @@ use rustc_session::declare_lint_pass;
 use rustc_span::Span;
 
 use clippy_utils::diagnostics::span_lint_and_then;
-use clippy_utils::source::snippet_with_applicability;
+use clippy_utils::source::{snippet_with_applicability, snippet_with_context};
 use clippy_utils::ty::has_iter_method;
 use clippy_utils::{is_trait_method, sym};
 
@@ -101,18 +101,23 @@ impl<'tcx> LateLintPass<'tcx> for NeedlessForEach {
 
             let body_param_sugg = snippet_with_applicability(cx, body.params[0].pat.span, "..", &mut applicability);
             let for_each_rev_sugg = snippet_with_applicability(cx, for_each_recv.span, "..", &mut applicability);
-            let body_value_sugg = snippet_with_applicability(cx, body.value.span, "..", &mut applicability);
+            let (body_value_sugg, is_macro_call) =
+                snippet_with_context(cx, body.value.span, for_each_recv.span.ctxt(), "..", &mut applicability);
 
             let sugg = format!(
                 "for {} in {} {}",
                 body_param_sugg,
                 for_each_rev_sugg,
-                match body.value.kind {
-                    ExprKind::Block(block, _) if is_let_desugar(block) => {
-                        format!("{{ {body_value_sugg} }}")
-                    },
-                    ExprKind::Block(_, _) => body_value_sugg.to_string(),
-                    _ => format!("{{ {body_value_sugg}; }}"),
+                if is_macro_call {
+                    format!("{{ {body_value_sugg}; }}")
+                } else {
+                    match body.value.kind {
+                        ExprKind::Block(block, _) if is_let_desugar(block) => {
+                            format!("{{ {body_value_sugg} }}")
+                        },
+                        ExprKind::Block(_, _) => body_value_sugg.to_string(),
+                        _ => format!("{{ {body_value_sugg}; }}"),
+                    }
                 }
             );
 
diff --git a/tests/ui/needless_for_each_fixable.fixed b/tests/ui/needless_for_each_fixable.fixed
index a73aff55639..a6d64d9afc1 100644
--- a/tests/ui/needless_for_each_fixable.fixed
+++ b/tests/ui/needless_for_each_fixable.fixed
@@ -143,3 +143,9 @@ mod issue14734 {
         //~^ needless_for_each
     }
 }
+
+fn issue15256() {
+    let vec: Vec<i32> = Vec::new();
+    for v in vec.iter() { println!("{v}"); }
+    //~^ needless_for_each
+}
diff --git a/tests/ui/needless_for_each_fixable.rs b/tests/ui/needless_for_each_fixable.rs
index d92f055d3f4..7e74d2b428f 100644
--- a/tests/ui/needless_for_each_fixable.rs
+++ b/tests/ui/needless_for_each_fixable.rs
@@ -143,3 +143,9 @@ mod issue14734 {
         //~^ needless_for_each
     }
 }
+
+fn issue15256() {
+    let vec: Vec<i32> = Vec::new();
+    vec.iter().for_each(|v| println!("{v}"));
+    //~^ needless_for_each
+}
diff --git a/tests/ui/needless_for_each_fixable.stderr b/tests/ui/needless_for_each_fixable.stderr
index f8014456097..204cfa36b02 100644
--- a/tests/ui/needless_for_each_fixable.stderr
+++ b/tests/ui/needless_for_each_fixable.stderr
@@ -148,5 +148,11 @@ error: needless use of `for_each`
 LL |         rows.iter().for_each(|x| do_something(x, 1u8));
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `for x in rows.iter() { do_something(x, 1u8); }`
 
-error: aborting due to 10 previous errors
+error: needless use of `for_each`
+  --> tests/ui/needless_for_each_fixable.rs:149:5
+   |
+LL |     vec.iter().for_each(|v| println!("{v}"));
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `for v in vec.iter() { println!("{v}"); }`
+
+error: aborting due to 11 previous errors