rust-lang / rust-lang/rust-clippy
`collapsible_if` should handle multiple nested if statements
Nobody has claimed this yet.
- Dominant language
- Rust
- Stars
- 13.5k
- Forks
- 2.2k
- Avg merge
- 2d 10h
- Merged PRs (30d)
- 32
Description
Summary
The collapsible_if lint can now detect opportunities for let-chains. Unfortunately, when there is more than one nested if in the chain, this is presented as N separate warnings, instead of one "if chain" that can be improved. Since let-chains bring the most value when the chains are long (and the nesting is deep), this hides the potential benefit.
Reproducer
I tried this code:
pub fn inner_type(ty: &Type) -> &Type {
if let Type::Path(TypePath { path, .. }) = ty {
if let Some(segment) = path.segments.last() {
if let PathArguments::AngleBracketed(args) = &segment.arguments {
if let Some(GenericArgument::Type(ty)) = args.args.first() {
return ty;
}
}
}
}
panic!("Expected inner type");
}
I expected to see this happen:
Clippy should suggest collapsing the entire chain of if statements:
if let Type::Path(TypePath { path, .. }) = ty
&& let Some(segment) = path.segments.last()
&& let PathArguments::AngleBracketed(args) = &segment.arguments
&& let Some(GenericArgument::Type(ty)) = args.args.first()
{
return ty;
}
Instead, this happened:
It prints a separate warning for each of the 3 possible nested ifs. This seems needlessly verbose, and I find it much harder to comprehend:
warning: this `if` statement can be collapsed
--> src/lib.rs:4:5
|
4 | / if let Type::Path(TypePath { path, .. }) = ty {
5 | | if let Some(segment) = path.segments.last() {
6 | | if let PathArguments::AngleBracketed(args) = &segment.arguments {
7 | | if let Some(GenericArgument::Type(ty)) = args.args.first() {
... |
12 | | }
| |_____^
|
= help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#collapsible_if
= note: `#[warn(clippy::collapsible_if)]` on by default
help: collapse nested if block
|
4 ~ if let Type::Path(TypePath { path, .. }) = ty
5 ~ && let Some(segment) = path.segments.last() {
6 | if let PathArguments::AngleBracketed(args) = &segment.arguments {
...
10 | }
11 ~ }
|
warning: this `if` statement can be collapsed
--> src/lib.rs:5:9
|
5 | / if let Some(segment) = path.segments.last() {
6 | | if let PathArguments::AngleBracketed(args) = &segment.arguments {
7 | | if let Some(GenericArgument::Type(ty)) = args.args.first() {
8 | | return ty;
... |
11 | | }
| |_________^
|
= help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#collapsible_if
help: collapse nested if block
|
5 ~ if let Some(segment) = path.segments.last()
6 ~ && let PathArguments::AngleBracketed(args) = &segment.arguments {
7 | if let Some(GenericArgument::Type(ty)) = args.args.first() {
8 | return ty;
9 | }
10 ~ }
|
warning: this `if` statement can be collapsed
--> src/lib.rs:6:13
|
6 | / if let PathArguments::AngleBracketed(args) = &segment.arguments {
7 | | if let Some(GenericArgument::Type(ty)) = args.args.first() {
8 | | return ty;
9 | | }
10 | | }
| |_____________^
|
= help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#collapsible_if
help: collapse nested if block
|
6 ~ if let PathArguments::AngleBracketed(args) = &segment.arguments
7 ~ && let Some(GenericArgument::Type(ty)) = args.args.first() {
8 | return ty;
9 ~ }
|
Note this does produce the exact same output, but it's hard to tell that that will be the case because it's spread out among the three different help blocks.
Version
rustc 1.89.0-nightly (e703dff8f 2025-06-11)
binary: rustc
commit-hash: e703dff8fe220b78195c53478e83fb2f68d8499c
commit-date: 2025-06-11
host: x86_64-unknown-linux-gnu
release: 1.89.0-nightly
LLVM version: 20.1.5
Additional Labels
No response
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 at the collapsible_if lint entry point and reproduce the supplied nested-Rust example. Trace how nested opportunities are collected and warnings are emitted, then add a regression case that expects one suggestion for the full chain and run the relevant Clippy tests.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- rust
- Domain
- tooling
- Issue type
- Bug
- Difficulty
- 3/5
- Estimated time
- 1-2 days
- Activity status
- Stale
- Clarity
- Mostly clear
- Newbie friendliness
- 52/100