A case where clippy suggests to use Some instead of unwrap

The following main.rs demonstrates a construct that I use and that clippy complains about:

fn divide(x : usize, y : usize) -> Option<usize> {
    if y == 0 { None } else { Some( x / y ) }
}
fn main() {
    let option = divide(4, 2);
    let value  = if option.is_some() { option.unwrap() } else { usize::MAX };
    println!("4 / 2 = {}", value);
}

The actual clippy error message for this case is

warning: called `unwrap` on `option` after checking its variant with `is_some`
 --> src/main.rs:6:40
  |
6 |     let value  = if option.is_some() { option.unwrap() } else { usize::MAX };
  |                  -------------------   ^^^^^^^^^^^^^^^
  |                  |
  |                  help: try: `if let Some(<item>) = option`
  |
  = help: for further information visit https://rust-lang.github.io/rust-clippy/rust-1.92.0/index.html#unnecessary_unwrap
  = note: `#[warn(clippy::unnecessary_unwrap)]` on by default

It is not clear to me what clippy is suggesting ?

That's the important part.

1 Like

Expanding a bit, it's suggesting that you write something like this instead:

    let value = if let Some(x) = option { x } else { usize::MAX };

This makes it easier to verify both for the compiler and human readers that the code won't panic during the unwrap, because it isn't used in the alternate version.


In this specific case, I'd probably write this instead because it's such a common case:

    let value = option.unwrap_or(usize::MAX);
6 Likes

I like your second suggestion above, but I am confused by the text that clippy suggested; i.e.,

let value = if let Some(x) = option { x } else { usize::MAX };

Does the assignment let Some(x) = option have a true or false return value ?
Do all let assignment have a return value ?

An if let else expression is not the same as an if else expression. They are semantically similar, but the former allows you to destructure using patterns, making your code more robust.

Here's some good reading if you want to know more: Why Did Rust Pick the 'If Let' Syntax? - Joe Clay

Thanks for the link above. For may actual application the else branch creates an empty vector, so I am using unwrap_or_else (I am not sure if that will be less work).

In that case, you might want to use unwrap_or_default instead.

I write an article about Rust programmers those programming style evolves with time of using Rust, starting from a blind unwrap, to the OP solution, Clippy suggestion and finally to [quote="firebits.io, post:7, topic:137629"]
unwrap_or_default
[/quote].

You also reinvented checked_div().

fn main() {
    let value = 4usize.checked_div(2).unwrap_or(usize::MAX);
    println!("4 / 2 = {}", value);
}
1 Like