rust-lang / rust-lang/rust-clippy
needless_range_loop suggests loop that stops earlier
Nobody has claimed this yet.
- Dominant language
- Rust
- Stars
- 13.5k
- Forks
- 2.2k
- Avg merge
- 2d 10h
- Merged PRs (30d)
- 32
Description
Summary
I ran clippy on some code that included a loop over a range of the form for i in start ..= end, which indexed into a slice of bytes, (bytes[i]) where end happened to be the length of the slice. Note that the original code includes an iteration of the loop where i is equal to bytes.len(), but that there was an additional condition checking for that case, preventing the out of bounds indexing.
In that case, clippy suggested an iterator expression that included calling .take(end + 1) on an iterator over bytes. Since end == bytes.len(), the take call does not actually do anything meaningful, since the iterator will run out before then. More worrying though is the fact that the previous behaviour of running the loop an additional time with i having a value of end was removed if the suggestion was used.
The example below has been reduced from the actual code, to remove irrelevant details.
See related, but non-identical https://github.com/rust-lang/rust-clippy/issues/6930
Lint Name
needless_range_loop
Reproducer
I tried this code:
fn foo(bytes: &[u8], in_i: usize) -> bool {
let len = bytes.len();
for i in in_i + 1..=len {
if i == len || bytes[i].is_ascii_whitespace() {
return true
}
}
false
}
I saw this happen:
warning: the loop variable `i` is used to index `bytes`
--> src/main.rs:4:14
|
4 | for i in in_i + 1..=len {
| ^^^^^^^^^^^^^^
|
= note: `#[warn(clippy::needless_range_loop)]` on by default
= help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#needless_range_loop
help: consider using an iterator
|
4 | for (i, <item>) in bytes.iter().enumerate().take(len + 1).skip(in_i + 1) {
| ~~~~~~~~~~~ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
I expected to see this happen:
Either no lint emitted, or a suggestion that had identical observed behaviour.
Version
rustc 1.62.0 (a8314ef7d 2022-06-27)
binary: rustc
commit-hash: a8314ef7d0ec7b75c336af2c9857bfaf43002bfc
commit-date: 2022-06-27
host: x86_64-unknown-linux-gnu
release: 1.62.0
LLVM version: 14.0.5
I was also able to replicate this on the playground with clippy 0.1.65 (2022-08-16 86c6ebe)
Additional Labels
No response
Contributor guide
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
Research direction
Start by reproducing the needless_range_loop warning with the provided Rust example and compare the suggested iterator's behavior with the original loop. Inspect the lint's implementation and tests, then ensure the lint is suppressed or its suggestion preserves the extra i == len iteration, with regression coverage for the reproducer.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- rust
- Domain
- devtools
- Issue type
- Bug
- Difficulty
- 3/5
- Estimated time
- 1-2 days
- Activity status
- Stale
- Clarity
- Clearly specified
- Newbie friendliness
- 45/100