Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why does the compiler assume that the value of if let should be `()`?

Tags:

rust

I have the following code:

use std::collections::HashSet;

fn translate() -> Option<String> {
    None
}

fn main() {
    let mut found = HashSet::new();

    if let Some(tr) = translate() {
        found.insert(tr);
    }
}

It works properly, but when I remove the semicolon after found.insert(tr), I get a compiler error:

error[E0308]: mismatched types
  --> src/main.rs:11:9
   |
7  | fn main() {
   |           - expected `()` because of default return type
...
11 |         found.insert(tr)
   |         ^^^^^^^^^^^^^^^^- help: try adding a semicolon: `;`
   |         |
   |         expected (), found bool
   |
   = note: expected type `()`
              found type `bool`

It doesn't matter where this code is located or whether it is the last expression of the function.

Why does the compiler assume that the expression inside the curly braces should be ()?

like image 322
Iakov Davydov Avatar asked Dec 07 '25 14:12

Iakov Davydov


1 Answers

According to the Rust Book (emphasis mine):

The value of the expression is the value of the last expression in whichever branch was chosen. An if without an else always results in () as the value.

This gives a constraint on the expression value inside the curly braces.

This is correct since the expression type matches ():

if let Some(_) = some() {
    ()
};

This is correct since there's an else statement (and the types between the branches match):

if let Some(_) = some() {
    true
} else {
    false
};

But this is wrong:

if let Some(_) = some() {
    true
};

This answer was inspired by this comment.

like image 142
Iakov Davydov Avatar answered Dec 12 '25 03:12

Iakov Davydov