次のRustコードを考えます。
fn f() -> i32 {
loop {
println!("Infinite loop!");
}
println!("Unreachable");
}
戻り値の型が間違っているにもかかわらず、これは(警告付きで)コンパイルされて実行されます。コンパイラーは()
、このコードに到達できないことを検出するため、最終行の戻り値のタイプがOKであるように見えます。
ただし、最後のセミコロンを削除すると、次のようになります。
fn f() -> i32 {
loop {
println!("Infinite loop!");
}
println!("Unreachable")
}
その後、コードはコンパイルされなくなり、型エラーが発生します。
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)
どうしてこれなの?()
これらのコードスニペットの両方で、戻り値の型は同じではありませんか?
注: Rustコンパイラーがこれら2つの例で異なる動作をする理由、つまりRustコンパイラーの実装方法を理解することに興味があります。言語設計の観点から、それがどのように「振る舞う」べきかについて哲学的な質問をするつもりはありませんでした(そのような質問はおそらくトピックから外れると思います)。
!
理にかなっているので、無限ループの戻り値の型、など。2番目のケースでは、戻り式があるため、型推論ソルバーはそれを使用して型を推論します。これも理にかなっています。これは言語リファレンスで指定されているとは思いませんし、それがどうでもいいとは思いません。到達できないステートメントを省略すれば大丈夫です。