rust-lang / rust-lang/rust-clippy
New lint: Suggest `zip_eq` over `zip` or explicitly opt out
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
When a user uses the .zip() method on Iterator, it will "silently fail" if the two iterators are of unequal length. A majority of the time, (my hunch is that) users intend to .zip() iterators of equal length, and when they aren't, it may cause silent failures in other parts of the program.
Categories (optional)
- Kind:
clippy::suspicious, maybeclippy::pedantic(and implicitlyclippy::nursery)
Advantages
- Forces the user to explicitly annotate when they want the behavior of
zip - Makes silent failures due to unequal
ziplengths far less common
Drawbacks
- Recommends a third party library,
itertools, to getzip_eq(perhaps this could be put into the standard library in the future) - Mildlly annoying if you do want the behavior of
zip, of which you would then want an explicit annotation
Example
fn main() {
let users = vec!["John", "Mary", "Kevin"];
let balances = vec![10.0, 20.0];
println!("These are the users in our system:");
for (name, balance) in users.iter().zip(balances.iter()) {
println!("{} - ${}", name, balance);
}
}
Could be written as:
use itertools::Itertools;
fn main() {
let users = vec!["John", "Mary", "Kevin"];
let balances = vec![10.0, 20.0];
println!("These are the users in our system:");
for (name, balance) in users.iter().zip_eq(balances.iter()) {
println!("{} - ${}", name, balance);
}
}
Or, if you want zip's behavior,
fn main() {
let users = vec!["John", "Mary", "Kevin"];
let balances = vec![10.0, 20.0];
println!("These are the users in our system:");
#[allow(prefer_zip)] // specific lint name requires bikeshedding
for (name, balance) in users.iter().zip(balances.iter()) {
println!("{} - ${}", name, balance);
}
}
Reasoning
On a project I'm working on, the fact that zip silently failed caused me to get mildly annoyed enough to force ensuring that the iterators are the same length a contributing guideline/codestyle, and I figured that I could suggest a lint over here to possibly do something about it. I'm sure the standard library folks had their reasoning for making zip behave the way it does, but I would say that a majority of the time, the two iterators are intended to be the same length. Having the lengths be unequal is similar to silent failure, where different parts of the system go broken, silently. Hopefully the appeal of such a lint is clear.
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 issue's examples and its proposed zip_eq and opt-out behavior, then determine the appropriate lint name and category. Done would mean an agreed design for detecting Iterator::zip uses and handling intentional truncation, but the issue does not name implementation files or tests.
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
- Needs clarification
- Newbie friendliness
- 25/100