rust-lang / rust-lang/rust-clippy
Lint nested and independent `if let` clauses
Nobody has claimed this yet.
- Dominant language
- Rust
- Stars
- 13.5k
- Forks
- 2.2k
- Avg merge
- 2d 10h
- Merged PRs (30d)
- 32
Description
This code
if let Some(start) = (1_usize).checked_add(5) {
if let Some(end) = (2_usize).checked_add(5) {
// ...
}
}
could be written like this
if let (Some(start), Some(end)) = ((1_usize).checked_add(5), (2_usize).checked_add(5)) {
// ...
}
which would remove a layer of nesting.
The lint should only lint nested if let clauses, that are independent of each other.
For example this must be ignored (or handled like in #2521):
if let Some(start) = (1_usize).checked_add(5) {
if let Some(end) = call_fn(start) {
// ...
}
}
but it should not matter, if there is code in between the if let clauses, as long as it does not influence the other if let clause(s):
if let Some(start) = (1_usize).checked_add(5) {
let x = 13_usize;
if let Some(end) = (2_usize).checked_add(5) {
// ...
}
let y = 15_usize;
}
I think that there should not be a limit on how many nested if let clauses should be linted, because it would improve the readability either way.
Another thing to consider would be else clauses. I think this lint should only trigger, if the nested else clauses have the same body:
if let Some(start) = (1_usize).checked_add(5) {
if let Some(end) = (2_usize).checked_add(5) {
// ...
} else {
call_x();
}
} else {
call_x();
}
would become
if let (Some(start), Some(end)) = ((1_usize).checked_add(5), (2_usize).checked_add(5)) {
// ...
} else {
call_x();
}
It might be too difficult (for clippy), but it would be possible to refactor nested if let-clauses with different else-clauses too
if let Some(start) = (1_usize).checked_add(5) {
if let Some(end) = (2_usize).checked_add(5) {
// ...
} else {
call_z(start);
}
} else {
call_y();
}
->
match ((1_usize).checked_add(5), (2_usize).checked_add(5)) {
(Some(start), Some(end)) => {
// ...
}
(Some(start), None) => {
call_z(start);
}
(None, None) => {
call_y();
}
_ => {
// this was not reachable in the original code (end would only be matched if Some(start))
}
}
Should I move this issue in to several smaller ones?
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 independent and dependent nested if let examples in the issue, along with the existing handling referenced in #2521. Define the lint's scope, including intervening code, multiple clauses, and matching or differing else bodies; done requires a decided behavior for these cases and corresponding coverage.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- rust
- Domain
- devtools, tooling
- Issue type
- Feature
- Difficulty
- 5/5
- Estimated time
- Over a week
- Activity status
- Stale
- Clarity
- Mostly clear
- Newbie friendliness
- 25/100