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 · 2 comments
Open

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

qsantos opened this issue Oct 29, 2024 · 2 comments
Labels
C-enhancement Category: Enhancement of lints, like adding more cases or adding help messages

Comments

@qsantos
Copy link
Contributor

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
Copy link

The linked PR has some basic implementation code and a lot of very useful comments, but personal matters have been taking up my time and it'll be a while before I have time to continue working on it. So in case someone else is interested, @rustbot release-assignment

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