fix(explicit_counter_loop): suggest .take(n) for for _ in 0..n counter loops

fix(explicit_counter_loop): suggest `.take(n)` for `for _ in 0..n` counter loops
This commit is contained in:
zayutaha
2026-03-03 18:08:44 +05:30
parent e492d02285
commit daad0fb356
3 changed files with 77 additions and 1 deletions
@@ -2,6 +2,7 @@
use super::{EXPLICIT_COUNTER_LOOP, IncrementVisitor, InitializeVisitor, make_iterator_snippet};
use clippy_utils::diagnostics::span_lint_and_then;
use clippy_utils::higher::Range;
use clippy_utils::source::snippet_with_applicability;
use clippy_utils::sugg::{EMPTY, Sugg};
use clippy_utils::{get_enclosing_block, is_integer_const, is_integer_literal_untyped};
@@ -83,6 +84,26 @@ pub(super) fn check<'tcx>(
snippet
});
// If the loop variable is unused and the range is `0..n`, suggest `(init..).take(n)`.
if pat_snippet == "_"
&& let Some(range) = Range::hir(cx, arg)
&& range.limits == RangeLimits::HalfOpen
&& range.start.is_some_and(|start| is_integer_const(cx, start, 0))
&& let Some(end) = range.end
{
let end = snippet_with_applicability(cx, end.span, "..", &mut applicability);
diag.span_suggestion(
span,
"consider using",
format!(
"{loop_label}for {name} in ({}).take({end})",
initializer.range(&EMPTY, RangeLimits::HalfOpen)
),
applicability,
);
return;
}
diag.span_suggestion(
span,
"consider using",
+31
View File
@@ -332,3 +332,34 @@ fn add_assign(&mut self, rhs: u8) {
priority += 1;
}
}
pub fn issue_16642() {
let mut base = 100;
const MAX: usize = 10;
for _ in 0..MAX {
//~^ explicit_counter_loop
base += 1;
}
let mut base = 100;
let nums = vec![1, 2, 3, 4];
for _ in nums {
//~^ explicit_counter_loop
base += 1;
}
// inclusive range: should not suggest .take()
let mut base = 100;
for _ in 0..=MAX {
//~^ explicit_counter_loop
base += 1;
}
// non-zero start: should not suggest .take(), falls through to zip
let mut base = 100;
for _ in 5..MAX {
//~^ explicit_counter_loop
base += 1;
}
}
+25 -1
View File
@@ -81,5 +81,29 @@ error: the variable `j` is used as a loop counter
LL | for item in &v {
| ^^^^^^^^^^^^^^ help: consider using: `for (j, item) in (s + 1..).zip(v.iter())`
error: aborting due to 13 previous errors
error: the variable `base` is used as a loop counter
--> tests/ui/explicit_counter_loop.rs:339:5
|
LL | for _ in 0..MAX {
| ^^^^^^^^^^^^^^^ help: consider using: `for base in (100..).take(MAX)`
error: the variable `base` is used as a loop counter
--> tests/ui/explicit_counter_loop.rs:347:5
|
LL | for _ in nums {
| ^^^^^^^^^^^^^ help: consider using: `for (base, _) in (100..).zip(nums.into_iter())`
error: the variable `base` is used as a loop counter
--> tests/ui/explicit_counter_loop.rs:354:5
|
LL | for _ in 0..=MAX {
| ^^^^^^^^^^^^^^^^ help: consider using: `for (base, _) in (100..).zip((0..=MAX))`
error: the variable `base` is used as a loop counter
--> tests/ui/explicit_counter_loop.rs:361:5
|
LL | for _ in 5..MAX {
| ^^^^^^^^^^^^^^^ help: consider using: `for (base, _) in (100..).zip((5..MAX))`
error: aborting due to 17 previous errors