Considere o seguinte código de ferrugem:
fn f() -> i32 {
loop {
println!("Infinite loop!");
}
println!("Unreachable");
}
Isso compila (com um aviso) e executa, apesar do tipo de retorno estar errado. Parece que o compilador está OK com o tipo de retorno da ()última linha, porque detecta que esse código está inacessível.
No entanto, se removermos o último ponto e vírgula:
fn f() -> i32 {
loop {
println!("Infinite loop!");
}
println!("Unreachable")
}
Em seguida, o código não é mais compilado, fornecendo um erro de tipo:
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)
Por que é isso? O tipo de retorno não é o mesmo ()em ambos os trechos de código?
Nota: Estou interessado em entender por que o compilador Rust se comporta de maneira diferente nesses dois exemplos, ou seja, como o compilador Rust é implementado. Eu não pretendia fazer uma pergunta filosófica sobre como "deveria" se comportar, da perspectiva do design da linguagem (eu entendo que essa pergunta provavelmente seria fora de tópico).
!o tipo de retorno por causa do loop infinito, o que faz sentido. No segundo caso, há uma expressão de retorno, então o solucionador de inferência de tipo usa isso para inferir o tipo, o que também faz sentido. Eu não acho que isso esteja especificado na referência de idioma, nem acho que isso importe de alguma forma - apenas omita a declaração inacessível e você ficará bem.