What if I reverse the order of expression and pattern in `if let`?

    let some_u8_value = Some(0u8);

    if let Some(3u8) = some_u8_value {
        // print nothing
        println!("Three!");
    };

    if let some_u8_value = Some(3u8) {
        // print "Three!"
        println!("Three!");
    };

In the second if let, pattern is some_u8_value and expression is Some(3u8), they do not match(because some_u8_value = Some(0u8)), but why the code still executed?

Pattern matching defines the value of any identifier on the left side; this is shadowing your original some_u8_value variable with a new one that only exists within the if let block.

So some_u8_value as a pattern is a new variable? What value is in it? Seems this variable is never used, and this would explain why the latter code executed.

Some(3u8), just the same as if you'd had the statement let some_u8_value = Some(3u8);

In general, if let a = b { something() } acts the same as { let a = b; something() }, except that it doesn't error when the value b doesn't match the pattern a.


This is indeed the case. In fact, the compiler warns you about it by default:

warning: unused variable: `some_u8_value`
 --> src/main.rs:9:12
  |
9 |     if let some_u8_value = Some(3u8) {
  |            ^^^^^^^^^^^^^ help: if this is intentional, prefix it with an underscore: `_some_u8_value`
  |
  = note: `#[warn(unused_variables)]` on by default

It also warns that you're using a pattern in if let that can't ever fail:

warning: irrefutable `if let` pattern
  --> src/main.rs:9:5
   |
9  | /     if let some_u8_value = Some(3u8) {
10 | |         // print "Three!"
11 | |         println!("Three!");
12 | |     };
   | |_____^
   |
   = note: `#[warn(irrefutable_let_patterns)]` on by default
   = note: this pattern will always match, so the `if let` is useless
   = help: consider replacing the `if let` with a `let`
5 Likes

Thank you very much. I will pay close attention and distinguish pattern and expression when using if let.

Note that rustc puts a bunch of work into not having false positives from its warnings, so if you've gotten used to ignoring them (perhaps from other tools that are less strict) then generally the best way to not have to pay too close attention is to just keep the codebase warning-clean. (And to never just #[allow(warnings)] -- though you can consider allowing some stylistic ones if you prefer.)

7 Likes

Thank you so much for your advice.