about summary refs log tree commit diff
diff options
context:
space:
mode:
authorSamuel Tardieu <sam@rfc1149.net>2025-04-16 20:43:23 +0200
committerSamuel Tardieu <sam@rfc1149.net>2025-05-20 00:48:19 +0200
commit8224956dffb1b296841c2e31c5496ab1a53b2d83 (patch)
treef4901b6ecc91ff565768fff0d848ef8faa9f9f67
parentb87e90b28f474c64a753e65b81a973f7b1a15d52 (diff)
downloadrust-8224956dffb1b296841c2e31c5496ab1a53b2d83.tar.gz
rust-8224956dffb1b296841c2e31c5496ab1a53b2d83.zip
Various macro fixes for loop lints
The `explicit_into_iter_loop`, `explicit_iter_loop` and `iter_next_loop`
will now:

- trigger only when the triggering expression is not located into macro
  code;
- properly expose code rewrite proposal with code coming from the root
  context.
-rw-r--r--clippy_lints/src/loops/explicit_into_iter_loop.rs4
-rw-r--r--clippy_lints/src/loops/explicit_iter_loop.rs4
-rw-r--r--clippy_lints/src/loops/mod.rs4
-rw-r--r--tests/ui/explicit_into_iter_loop.fixed13
-rw-r--r--tests/ui/explicit_into_iter_loop.rs13
-rw-r--r--tests/ui/explicit_into_iter_loop.stderr8
-rw-r--r--tests/ui/explicit_iter_loop.fixed13
-rw-r--r--tests/ui/explicit_iter_loop.rs13
-rw-r--r--tests/ui/explicit_iter_loop.stderr8
-rw-r--r--tests/ui/iter_next_loop.rs13
-rw-r--r--tests/ui/iter_next_loop.stderr8
11 files changed, 93 insertions, 8 deletions
diff --git a/clippy_lints/src/loops/explicit_into_iter_loop.rs b/clippy_lints/src/loops/explicit_into_iter_loop.rs
index d5ddc33e928..4aa1c2e211d 100644
--- a/clippy_lints/src/loops/explicit_into_iter_loop.rs
+++ b/clippy_lints/src/loops/explicit_into_iter_loop.rs
@@ -1,7 +1,7 @@
 use super::EXPLICIT_INTO_ITER_LOOP;
 use clippy_utils::diagnostics::span_lint_and_sugg;
 use clippy_utils::is_trait_method;
-use clippy_utils::source::snippet_with_applicability;
+use clippy_utils::source::snippet_with_context;
 use rustc_errors::Applicability;
 use rustc_hir::Expr;
 use rustc_lint::LateContext;
@@ -76,7 +76,7 @@ pub(super) fn check(cx: &LateContext<'_>, self_arg: &Expr<'_>, call_expr: &Expr<
     };
 
     let mut applicability = Applicability::MachineApplicable;
-    let object = snippet_with_applicability(cx, self_arg.span, "_", &mut applicability);
+    let object = snippet_with_context(cx, self_arg.span, call_expr.span.ctxt(), "_", &mut applicability).0;
     span_lint_and_sugg(
         cx,
         EXPLICIT_INTO_ITER_LOOP,
diff --git a/clippy_lints/src/loops/explicit_iter_loop.rs b/clippy_lints/src/loops/explicit_iter_loop.rs
index d0b26c91ffa..010652e1cb9 100644
--- a/clippy_lints/src/loops/explicit_iter_loop.rs
+++ b/clippy_lints/src/loops/explicit_iter_loop.rs
@@ -1,7 +1,7 @@
 use super::EXPLICIT_ITER_LOOP;
 use clippy_utils::diagnostics::span_lint_and_sugg;
 use clippy_utils::msrvs::{self, Msrv};
-use clippy_utils::source::snippet_with_applicability;
+use clippy_utils::source::snippet_with_context;
 use clippy_utils::sym;
 use clippy_utils::ty::{
     implements_trait, implements_trait_with_env, is_copy, is_type_lang_item, make_normalized_projection,
@@ -36,7 +36,7 @@ pub(super) fn check(
     }
 
     let mut applicability = Applicability::MachineApplicable;
-    let object = snippet_with_applicability(cx, self_arg.span, "_", &mut applicability);
+    let object = snippet_with_context(cx, self_arg.span, call_expr.span.ctxt(), "_", &mut applicability).0;
     span_lint_and_sugg(
         cx,
         EXPLICIT_ITER_LOOP,
diff --git a/clippy_lints/src/loops/mod.rs b/clippy_lints/src/loops/mod.rs
index 22cab317e3d..01c36b8cb12 100644
--- a/clippy_lints/src/loops/mod.rs
+++ b/clippy_lints/src/loops/mod.rs
@@ -909,7 +909,9 @@ impl Loops {
     }
 
     fn check_for_loop_arg(&self, cx: &LateContext<'_>, _: &Pat<'_>, arg: &Expr<'_>) {
-        if let ExprKind::MethodCall(method, self_arg, [], _) = arg.kind {
+        if !arg.span.from_expansion()
+            && let ExprKind::MethodCall(method, self_arg, [], _) = arg.kind
+        {
             match method.ident.name {
                 sym::iter | sym::iter_mut => {
                     explicit_iter_loop::check(cx, self_arg, arg, self.msrv, self.enforce_iter_loop_reborrow);
diff --git a/tests/ui/explicit_into_iter_loop.fixed b/tests/ui/explicit_into_iter_loop.fixed
index 2b68906ae39..c1b3c478eeb 100644
--- a/tests/ui/explicit_into_iter_loop.fixed
+++ b/tests/ui/explicit_into_iter_loop.fixed
@@ -73,3 +73,16 @@ fn main() {
 
     for _ in S.into_iter::<u32>() {}
 }
+
+fn issue14630() {
+    macro_rules! mac {
+        (into_iter $e:expr) => {
+            $e.into_iter()
+        };
+    }
+
+    for _ in dbg!([1, 2]) {}
+    //~^ explicit_into_iter_loop
+
+    for _ in mac!(into_iter [1, 2]) {}
+}
diff --git a/tests/ui/explicit_into_iter_loop.rs b/tests/ui/explicit_into_iter_loop.rs
index ca335b62d90..581e0dadcec 100644
--- a/tests/ui/explicit_into_iter_loop.rs
+++ b/tests/ui/explicit_into_iter_loop.rs
@@ -73,3 +73,16 @@ fn main() {
 
     for _ in S.into_iter::<u32>() {}
 }
+
+fn issue14630() {
+    macro_rules! mac {
+        (into_iter $e:expr) => {
+            $e.into_iter()
+        };
+    }
+
+    for _ in dbg!([1, 2]).into_iter() {}
+    //~^ explicit_into_iter_loop
+
+    for _ in mac!(into_iter [1, 2]) {}
+}
diff --git a/tests/ui/explicit_into_iter_loop.stderr b/tests/ui/explicit_into_iter_loop.stderr
index 1c3156755d4..26fb11e0048 100644
--- a/tests/ui/explicit_into_iter_loop.stderr
+++ b/tests/ui/explicit_into_iter_loop.stderr
@@ -37,5 +37,11 @@ error: it is more concise to loop over containers instead of using explicit iter
 LL |     for _ in mr.into_iter() {}
    |              ^^^^^^^^^^^^^^ help: to write this more concisely, try: `&mut *mr`
 
-error: aborting due to 6 previous errors
+error: it is more concise to loop over containers instead of using explicit iteration methods
+  --> tests/ui/explicit_into_iter_loop.rs:84:14
+   |
+LL |     for _ in dbg!([1, 2]).into_iter() {}
+   |              ^^^^^^^^^^^^^^^^^^^^^^^^ help: to write this more concisely, try: `dbg!([1, 2])`
+
+error: aborting due to 7 previous errors
 
diff --git a/tests/ui/explicit_iter_loop.fixed b/tests/ui/explicit_iter_loop.fixed
index cd0898dfc36..f246ec61800 100644
--- a/tests/ui/explicit_iter_loop.fixed
+++ b/tests/ui/explicit_iter_loop.fixed
@@ -183,3 +183,16 @@ pub fn issue_13184() {
     let rvalues = &values;
     for _ in rvalues.iter() {}
 }
+
+fn issue14630() {
+    macro_rules! mac {
+        (iter $e:expr) => {
+            $e.into_iter()
+        };
+    }
+
+    for _ in &dbg!([1, 2]) {}
+    //~^ explicit_iter_loop
+
+    for _ in mac!(iter [1, 2]) {}
+}
diff --git a/tests/ui/explicit_iter_loop.rs b/tests/ui/explicit_iter_loop.rs
index 02405280ce4..35f4fb7097d 100644
--- a/tests/ui/explicit_iter_loop.rs
+++ b/tests/ui/explicit_iter_loop.rs
@@ -183,3 +183,16 @@ pub fn issue_13184() {
     let rvalues = &values;
     for _ in rvalues.iter() {}
 }
+
+fn issue14630() {
+    macro_rules! mac {
+        (iter $e:expr) => {
+            $e.into_iter()
+        };
+    }
+
+    for _ in dbg!([1, 2]).iter() {}
+    //~^ explicit_iter_loop
+
+    for _ in mac!(iter [1, 2]) {}
+}
diff --git a/tests/ui/explicit_iter_loop.stderr b/tests/ui/explicit_iter_loop.stderr
index 3816bb4db98..575dbe7813d 100644
--- a/tests/ui/explicit_iter_loop.stderr
+++ b/tests/ui/explicit_iter_loop.stderr
@@ -112,5 +112,11 @@ error: it is more concise to loop over references to containers instead of using
 LL |     for _ in r.iter() {}
    |              ^^^^^^^^ help: to write this more concisely, try: `r`
 
-error: aborting due to 18 previous errors
+error: it is more concise to loop over references to containers instead of using explicit iteration methods
+  --> tests/ui/explicit_iter_loop.rs:194:14
+   |
+LL |     for _ in dbg!([1, 2]).iter() {}
+   |              ^^^^^^^^^^^^^^^^^^^ help: to write this more concisely, try: `&dbg!([1, 2])`
+
+error: aborting due to 19 previous errors
 
diff --git a/tests/ui/iter_next_loop.rs b/tests/ui/iter_next_loop.rs
index 32711c7ef62..8e62ed963b9 100644
--- a/tests/ui/iter_next_loop.rs
+++ b/tests/ui/iter_next_loop.rs
@@ -15,3 +15,16 @@ fn main() {
     let u = Unrelated(&[0]);
     for _v in u.next() {} // no error
 }
+
+fn issue14630() {
+    macro_rules! mac {
+        (next $e:expr) => {
+            $e.iter().next()
+        };
+    }
+
+    for _ in dbg!([1, 2].iter()).next() {}
+    //~^ iter_next_loop
+
+    for _ in mac!(next [1, 2]) {}
+}
diff --git a/tests/ui/iter_next_loop.stderr b/tests/ui/iter_next_loop.stderr
index acc55031c3b..c076e86db93 100644
--- a/tests/ui/iter_next_loop.stderr
+++ b/tests/ui/iter_next_loop.stderr
@@ -7,5 +7,11 @@ LL |     for _ in x.iter().next() {}
    = note: `-D clippy::iter-next-loop` implied by `-D warnings`
    = help: to override `-D warnings` add `#[allow(clippy::iter_next_loop)]`
 
-error: aborting due to 1 previous error
+error: you are iterating over `Iterator::next()` which is an Option; this will compile but is probably not what you want
+  --> tests/ui/iter_next_loop.rs:26:14
+   |
+LL |     for _ in dbg!([1, 2].iter()).next() {}
+   |              ^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: aborting due to 2 previous errors