rust-lang / rust-lang/rust-clippy
On slices and vectors, encourage slice operations instead of iterator methods like `nth` or `skip`
Nobody has claimed this yet.
- Dominant language
- Rust
- Stars
- 13.5k
- Forks
- 2.2k
- Avg merge
- 2d 10h
- Merged PRs (30d)
- 32
Description
What it does
Inspired by the bug report in https://github.com/rust-lang/rust/issues/150235, tell people to just use slices when they make transient iterators to do things that are easier to just stay on slices.
For example, that issue is doing (where s.stack is a Vec)
let mut iter = s.stack.iter_mut();
let parent = iter.nth(s.depth - 1).unwrap();
let current = iter.next().unwrap();
then never using the iterator again.
It would be simpler to never make the iterator in the first place, and use different slice methods instead.
For example, it could use
let (parent, current) = s.stack.get_disjoint_mut([s.depth - 1, s.depth]).unwrap();
or because they're adjacent it could use one of
let [parent, current] = s.stack[s.depth - 1..].first_chunk_mut().unwrap();
let [parent, current] = s.stack[..=s.depth].last_chunk_mut().unwrap();
Advantage
- Less complicated code, because you as the human don't need to think about the state of the mutable iterator
- Easier for the compiler to optimize, because the slice methods can directly check against the length
Drawbacks
The slice code only works on slices (or things that deref to slices) so it would make it harder to change the Vec<T> into SomeFancyNonContiguousContainer<T> later. (That said, you can still easily move to ThinVec<T> or SmallVec<T> or ... since they all still deref to slices.)
This can probably get arbitrarily-complicated to lint in clippy.
Example
pub fn foo(x: &mut [String]) {
let mut it = x.iter_mut().skip(2);
let a = it.next().unwrap();
let b = it.next().unwrap();
do_something_with((a, b));
}
Could be written as:
pub fn foo(x: &mut [String]) {
let [a, b] = x[2..].first_chunk_mut::<2>().unwrap();
do_something_with((a, b));
}
Comparison with existing lints
This doesn't lint today.
It's similar to clippy::iter_nth, but is about going further to look at more complex situations and other possible methods.
Additional Context
This is a large bucket of possible things, far more than just the examples listed.
In some sense, it's possible that anything making a slice iterator then not actually looping nor using any of the looping methods (nor passing it to something that needs an iterator) could want to be re-written to avoid the iterator.
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 reviewing the existing clippy::iter_nth lint and the slice-operation examples in this issue. Define which transient iterator patterns are in scope, how the lint should handle the listed alternatives and limitations, and what cases must be covered before the work is considered complete.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- rust
- Domain
- tooling
- Issue type
- Feature
- Difficulty
- 5/5
- Estimated time
- Over a week
- Activity status
- Stale
- Clarity
- Mostly clear
- Newbie friendliness
- 35/100