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 ()
?
When you omit a function's return type, the function actually returns
()
. That is,is equivalent to:
An
if let
expression that is used as a statement must return()
, unless it is the last expression in the function's body, in which case its type must match the function's return type. Since yourif let
doesn't have anelse
clause, its type must be()
.According to the Rust Book (emphasis mine):
This gives a constraint on the expression value inside the curly braces.
This is correct since the expression type matches
()
:This is correct since there's an
else
statement (and the types between the branches match):But this is wrong:
This answer was inspired by this comment.