Various macro fixes for loop lints (#14631)

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.

changelog: [`explicit_into_iter_loop`, `explicit_iter_loop`,
`iter_next_loop`]: behave in macro context

Fixes rust-lang/rust-clippy#14630
This commit is contained in:
Timo
2025-05-20 22:17:38 +00:00
committed by GitHub
11 changed files with 93 additions and 8 deletions
@@ -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,
+2 -2
View File
@@ -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,
+3 -1
View File
@@ -909,7 +909,9 @@ fn check_for_loop<'tcx>(
}
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);
+13
View File
@@ -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]) {}
}
+13
View File
@@ -73,3 +73,16 @@ fn next(&mut self) -> Option<Self::Item> {
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]) {}
}
+7 -1
View File
@@ -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
+13
View File
@@ -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]) {}
}
+13
View File
@@ -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]) {}
}
+7 -1
View File
@@ -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
+13
View File
@@ -15,3 +15,16 @@ fn next(&self) -> std::slice::Iter<u8> {
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]) {}
}
+7 -1
View File
@@ -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