Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Simplify if-let-Some-else-None using question mark operator #13626

Open
qsantos opened this issue Oct 29, 2024 · 1 comment · May be fixed by #13772
Open

Simplify if-let-Some-else-None using question mark operator #13626

qsantos opened this issue Oct 29, 2024 · 1 comment · May be fixed by #13772
Assignees
Labels
C-enhancement Category: Enhancement of lints, like adding more cases or adding help messages

Comments

@qsantos
Copy link

qsantos commented Oct 29, 2024

Consider the code below.

pub fn f(x: Option<u32>) -> Option<u32> {
    if let Some(x) = x {
        dbg!(x);
        Some(x * 2)
    } else {
        None
    }
}

Standard Clippy produces no warning. More exhaustive options suggest code that is no significantly better:

$ cargo clippy --all -- -W clippy::all -W clippy::nursery
error: use Option::map_or instead of an if let/else
 --> src/lib.rs:2:5
  |
2 | /     if let Some(x) = x {
3 | |         dbg!(x);
4 | |         Some(x * 2)
5 | |     } else {
6 | |         None
7 | |     }
  | |_____^
  |
  = help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#option_if_let_else
  = note: `-D clippy::option-if-let-else` implied by `-D warnings`
  = help: to override `-D warnings` add `#[allow(clippy::option_if_let_else)]`
help: try
  |
2 ~     x.map_or(None, |x| {
3 +         dbg!(x);
4 +         Some(x * 2)
5 +     })
  |

However, the code can be written with less nesting, using the question mark operator:

pub fn f(x: Option<u32>) -> Option<u32> {
    let x = x?;
    dbg!(x);
    Some(x * 2)
}

Note that Clippy does suggest that for the code below:

pub fn f(x: Option<u32>) -> Option<u32> {
    let Some(x) = x else {
        return None;
    };
    dbg!(x);
    Some(x * 2)
}
error: this `let...else` may be rewritten with the `?` operator
 --> src/lib.rs:2:5
  |
2 | /     let Some(x) = x else {
3 | |         return None;
4 | |     };
  | |______^ help: replace it with: `let x = x?;`
  |
  = help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#question_mark
  = note: `-D clippy::question-mark` implied by `-D warnings`
  = help: to override `-D warnings` add `#[allow(clippy::question_mark)]`

This pattern is particularly frequent when implementing iterators.

@samueltardieu samueltardieu added the C-enhancement Category: Enhancement of lints, like adding more cases or adding help messages label Oct 30, 2024
@DylanBulfin
Copy link

I'd like to try this one out, @rustbot claim

@DylanBulfin DylanBulfin linked a pull request Dec 2, 2024 that will close this issue
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
C-enhancement Category: Enhancement of lints, like adding more cases or adding help messages
Projects
None yet
Development

Successfully merging a pull request may close this issue.

3 participants