rust-lang / rust-lang/rust-clippy
Integer range pattern clarity
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
This lint discourages potentially-confusing integer range patterns. I'm opening an issue instead of a pull request because I'm not sure exactly what the rules should be, but here's my first pass:
- If a wildcard pattern can be replaced with a pattern in the form
z.., do so. - If two consecutive patterns leave a gap of width exactly 1 between them, and the first one is an exclusive range, suggest an inclusive range instead.
- Alternatively, if there's a wildcard pattern figure out exactly what explicit pattern would replace it and suggest that.
Lint Name
range_pattern_readability
Category
suspicious, style
Advantage
This lint idea is inspired by concerns brought up in rust#37854. I've come to believe that using wildcard patterns alongside integer range patterns leads to poor diagnostics. For instance I would suggest that a match like in foo1 below is probably a mistake, but it doesn't trigger an incomplete-match error the way foo2 does because of the wildcard pattern. foo0 doesn't look like a mistake, but I think replacing the wildcard with a half-open range pattern leads to better readability and better confidence that an incomplete-match error isn't being incorrectly suppressed. Having a lint like this would alleviate some of the concerns about stabilizing the exclusive_range_pattern feature.
Drawbacks
There are several problems that need to be overcome with this lint. First is the issue of figuring out exactly what the rules should be: when should the lint trigger, and how complex of a final pattern should it suggest before it gets ridiculous? How can we make sure this lint improves readability instead of degrading it? Then there's the problem with signed integers: specifically that ..z patterns are still unstable and will likely be stabilized separately from a..b patterns. That's not such a problem because ..=z patterns are already stable, but it complicates things. Finally there's the fact that match exhaustiveness is currently broken for point-sized integer types (rust#56354). As far as I can tell rustc currently requires any match involving a pointer-sized integer to have a wildcard pattern, so we won't be able to apply this lint to those types until that issue is resolved.
Example
#![feature(exclusive_range_pattern)]
fn foo0(x: u32) -> u32 {
match x {
0..10 => 0,
10..20 => 10,
_ => 20,
}
}
fn foo1(x: u32) -> u32 {
match x {
0..9 => 0,
10..19 => 10,
_ => 20,
}
}
fn foo2(x: u32) -> u32 {
match x {
0..9 => 0, // }
10..19 => 10, // }-- this is already an error
20.. => 20, // }
}
}
Could be written as:
#![feature(exclusive_range_pattern)]
fn foo0(x: u32) -> u32 {
match x {
0..10 => 0,
10..20 => 10,
20.. => 20,
}
}
fn foo1a(x: u32) -> u32 {
match x {
0..=9 => 0,
10..=19 => 10,
20.. => 20,
}
}
fn foo1b(x: u32) -> u32 {
match x {
0..9 => 0,
10..19 => 10,
9 | 19.. => 20,
}
}
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
The issue names no implementation files or tests; start with the proposed range_pattern_readability rules and the foo0, foo1, and foo2 examples. Resolve the open design questions around wildcard replacement, signed integers, and pointer-sized integers before implementation. Done means agreed lint behavior and diagnostics that address the examples without the stated exhaustiveness limitations.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- rust
- Domain
- compilers, tooling
- Issue type
- Feature
- Difficulty
- 5/5
- Estimated time
- Over a week
- Activity status
- Stale
- Clarity
- Needs clarification
- Newbie friendliness
- 25/100