-
Notifications
You must be signed in to change notification settings - Fork 1.9k
Description
What it does
Inspired by the bug report in rust-lang/rust#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.