8000 Lint nested and independent `if let` clauses · Issue #5218 · rust-lang/rust-clippy · GitHub
[go: up one dir, main page]

Skip to content
Lint nested and independent if let clauses #5218
@Luro02

Description

@Luro02

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?

5DF6

Metadata

Metadata

Assignees

No one assigned

    Labels

    A-lintArea: New lintsE-mediumCall for participation: Medium difficulty level problem and requires some initial experience.L-complexityLint: Belongs in the complexity lint groupS-needs-discussionStatus: Needs further discussion before merging or work can be started

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions

      0