Consider the following Rust code:
fn f() -> i32 {
loop {
println!("Infinite loop!");
}
println!("Unreachable");
}
This compiles (with a warning) and runs, despite the fact that the return type is wrong.
It would seem that the compiler is OK with the return type of ()
in the last line because it detects that this code is unreachable.
However, if we remove the last semicolon:
fn f() -> i32 {
loop {
println!("Infinite loop!");
}
println!("Unreachable")
}
Then the code no longer compiles, giving a type error:
error[E0308]: mismatched types
--> src/main.rs:14:5
|
14 | println!("Unreachable")
| ^^^^^^^^^^^^^^^^^^^^^^^ expected `i32`, found `()`
|
= note: this error originates in a macro outside of the current crate (in Nightly builds, run with -Z external-macro-backtrace for more info)
Why is this? Isn't the return type the same, ()
, in both of these code snipets?
Note: I'm interested in understanding why the Rust compiler behaves differently on these two examples, i.e. how the Rust compiler is implemented. I did not mean to ask a philosophical question about how it "should" behave, from the perspective of language design (I understand that such a question would probably be off-topic).
!
as the return type because of the infinite loop, which makes sense. In the second case, there's a return expression, so the type inference solver uses that to infer the type, which also makes sense. I don't think this is specified in the language reference, nor do I think it matters in any way – just omit the unreachable statement and you'll be fine. – Dowdreturn <something>;
and then using an automatic return at the end of the function. It looks like the compiler checks things in a way that allows it to see both and register it as an error even though it is unreachable. – Salesclerk