Skip to content

Commit 75e8019

Browse files
committed
Only suggest .iter() when chunks_exact is not in a for loop
1 parent e509232 commit 75e8019

File tree

4 files changed

+44
-14
lines changed

4 files changed

+44
-14
lines changed

clippy_lints/src/methods/chunks_exact_with_const_size.rs

Lines changed: 20 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,10 @@
11
use super::CHUNKS_EXACT_WITH_CONST_SIZE;
22
use clippy_utils::diagnostics::span_lint_and_then;
3+
use clippy_utils::higher::ForLoop;
34
use clippy_utils::msrvs::{self, Msrv};
45
use clippy_utils::source::snippet_with_applicability;
5-
use clippy_utils::sym;
66
use clippy_utils::visitors::is_const_evaluatable;
7+
use clippy_utils::{get_parent_expr, sym};
78
use rustc_errors::Applicability;
89
use rustc_hir::{Expr, Node, PatKind};
910
use rustc_lint::LateContext;
@@ -75,10 +76,27 @@ pub(super) fn check<'tcx>(
7576
));
7677
}
7778
} else {
79+
let in_for_loop = {
80+
let mut cur_expr = expr;
81+
loop {
82+
if let Some(parent_expr) = get_parent_expr(cx, cur_expr) {
83+
if let Some(for_loop) = ForLoop::hir(parent_expr)
84+
&& for_loop.arg.hir_id == expr.hir_id
85+
{
86+
break true;
87+
}
88+
cur_expr = parent_expr;
89+
} else {
90+
break false;
91+
}
92+
}
93+
};
94+
95+
let suffix = if in_for_loop { ".0" } else { ".0.iter()" };
7896
diag.span_suggestion(
7997
call_span,
8098
"consider using `as_chunks` instead",
81-
format!("{as_chunks}.0.iter()"),
99+
format!("{as_chunks}{suffix}"),
82100
applicability,
83101
);
84102
}

tests/ui/chunks_exact_with_const_size.fixed

Lines changed: 8 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -10,23 +10,26 @@ fn main() {
1010
for chunk in it {}
1111

1212
// Should trigger - direct iteration without binding (gets suggestion)
13-
for chunk in slice.as_chunks::<4>().0.iter() {
13+
for chunk in slice.as_chunks::<4>().0 {
1414
//~^ chunks_exact_with_const_size
1515
let _ = chunk;
1616
}
1717

1818
// Should trigger - direct iteration with const
1919
const CHUNK_SIZE: usize = 4;
20-
for chunk in slice.as_chunks::<CHUNK_SIZE>().0.iter() {
20+
for chunk in slice.as_chunks::<CHUNK_SIZE>().0 {
2121
//~^ chunks_exact_with_const_size
2222
let _ = chunk;
2323
}
2424

25-
// Should trigger - chunks_exact_mut with direct iteration (gets suggestion)
26-
// Note: The suggestion uses .iter() but should use .iter_mut() - this is a known limitation
25+
// Should trigger - chunks_exact_mut with direct iteration (gets suggestion without .iter())
2726
let mut arr = [1, 2, 3, 4, 5, 6, 7, 8];
28-
for chunk in arr.as_chunks_mut::<4>().0.iter() {
27+
for chunk in arr.as_chunks_mut::<4>().0 {
2928
//~^ chunks_exact_with_const_size
3029
let _ = chunk;
3130
}
31+
32+
// Should trigger - used with iterator method (not for loop, so needs .iter())
33+
let _: Vec<_> = slice.as_chunks::<4>().0.iter().collect();
34+
//~^ chunks_exact_with_const_size
3235
}

tests/ui/chunks_exact_with_const_size.rs

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -22,11 +22,14 @@ fn main() {
2222
let _ = chunk;
2323
}
2424

25-
// Should trigger - chunks_exact_mut with direct iteration (gets suggestion)
26-
// Note: The suggestion uses .iter() but should use .iter_mut() - this is a known limitation
25+
// Should trigger - chunks_exact_mut with direct iteration (gets suggestion without .iter())
2726
let mut arr = [1, 2, 3, 4, 5, 6, 7, 8];
2827
for chunk in arr.chunks_exact_mut(4) {
2928
//~^ chunks_exact_with_const_size
3029
let _ = chunk;
3130
}
31+
32+
// Should trigger - used with iterator method (not for loop, so needs .iter())
33+
let _: Vec<_> = slice.chunks_exact(4).collect();
34+
//~^ chunks_exact_with_const_size
3235
}

tests/ui/chunks_exact_with_const_size.stderr

Lines changed: 11 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ error: using `chunks_exact` with a constant chunk size
22
--> tests/ui/chunks_exact_with_const_size.rs:13:24
33
|
44
LL | for chunk in slice.chunks_exact(4) {
5-
| ^^^^^^^^^^^^^^^ help: consider using `as_chunks` instead: `as_chunks::<4>().0.iter()`
5+
| ^^^^^^^^^^^^^^^ help: consider using `as_chunks` instead: `as_chunks::<4>().0`
66
|
77
= note: `-D clippy::chunks-exact-with-const-size` implied by `-D warnings`
88
= help: to override `-D warnings` add `#[allow(clippy::chunks_exact_with_const_size)]`
@@ -11,13 +11,19 @@ error: using `chunks_exact` with a constant chunk size
1111
--> tests/ui/chunks_exact_with_const_size.rs:20:24
1212
|
1313
LL | for chunk in slice.chunks_exact(CHUNK_SIZE) {
14-
| ^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using `as_chunks` instead: `as_chunks::<CHUNK_SIZE>().0.iter()`
14+
| ^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using `as_chunks` instead: `as_chunks::<CHUNK_SIZE>().0`
1515

1616
error: using `chunks_exact_mut` with a constant chunk size
17-
--> tests/ui/chunks_exact_with_const_size.rs:28:22
17+
--> tests/ui/chunks_exact_with_const_size.rs:27:22
1818
|
1919
LL | for chunk in arr.chunks_exact_mut(4) {
20-
| ^^^^^^^^^^^^^^^^^^^ help: consider using `as_chunks` instead: `as_chunks_mut::<4>().0.iter()`
20+
| ^^^^^^^^^^^^^^^^^^^ help: consider using `as_chunks` instead: `as_chunks_mut::<4>().0`
2121

22-
error: aborting due to 3 previous errors
22+
error: using `chunks_exact` with a constant chunk size
23+
--> tests/ui/chunks_exact_with_const_size.rs:33:27
24+
|
25+
LL | let _: Vec<_> = slice.chunks_exact(4).collect();
26+
| ^^^^^^^^^^^^^^^ help: consider using `as_chunks` instead: `as_chunks::<4>().0.iter()`
27+
28+
error: aborting due to 4 previous errors
2329

0 commit comments

Comments
 (0)