rust-lang / rust-lang/rust-clippy
A lint for diverging expressions in else-case to encourage early retuns (and similar)
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
If you have a return/continue/break/panic or similar in an else case, it's often cleaner to use an early return/continue/break.
This also applies to turning if-let-else into let-else, if the else case always returns/continues/breaks.
I think it might even be one which can be enabled by default. I don't see any cases where it would be difficult to discover this, nor do I see any real drawbacks.
Advantage
- less indentation/nesting
- decreased complexity since else cases are closed
- often considered better style
Drawbacks
Not everybody might prefer early returns.
At least a completely functional style might be preferable.
(but probably almost never a "return" in an else case only)
Maybe the if_not_else lint might be confusing when not handled in a good way.
Example
fn sum_smaller_than(numbers: &[usize], max: usize) -> Option<usize> {
let mut sum = 0;
for &num in numbers {
if sum < max {
sum += num;
} else {
return None;
}
}
Some(sum)
}
Here's a diverging expression (return) in an else case.
The suggestion would usually be to negate the expression and switch the branches like this:
fn sum_smaller_than(numbers: &[usize], max: usize) -> Option<usize> {
let mut sum = 0;
for &num in numbers {
if !(sum < max) {
return None;
} else {
sum += num;
}
}
Some(sum)
}
Then when following the other lints nonminimal_bool and redundant_else lints, we get this:
fn sum_smaller_than(numbers: &[usize], max: usize) -> Option<usize> {
let mut sum = 0;
for &num in numbers {
if sum >= max {
return None;
}
sum += num;
}
Some(sum)
}
Following the if_not_else lint would just revert it back, so it should be disabled if a redundant_else lint is discovered for the same lint (probably a separate issue, which is useful by itself).
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 with the examples in the issue and review the existing if_not_else, nonminimal_bool, and redundant_else lint behavior. Determine the intended scope for diverging expressions in else branches, including if-let-else, and how overlapping suggestions should interact. Done means the lint's behavior and default configuration are settled and its interactions do not produce conflicting transformations.
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