Rustが誤った戻り型のコードを許可するのはなぜですか?


8

次の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コンパイラーの実装方法を理解することに興味があります。言語設計の観点から、それがどのように「振る舞う」べきかについて哲学的な質問をするつもりはありませんでした(そのような質問はおそらくトピックから外れると思います)。


1
Rustコンパイラは、関数本体の型を推測する必要があります。最初のケースでは、return式、と明らかにコンパイラの推論全くありません!理にかなっているので、無限ループの戻り値の型、など。2番目のケースでは、戻り式があるため、型推論ソルバーはそれを使用して型を推論します。これも理にかなっています。これは言語リファレンスで指定されているとは思いませんし、それがどうでもいいとは思いません。到達できないステートメントを省略すれば大丈夫です。
Sven Marnach

@SvenMarnachそれはまだ言語についての質問です。それはまだ話題です。
ピーターホール

1
@SvenMarnachそれは本当に必要ですか?私はRustの初心者であり、コンパイラーがなぜそれを行うのかを理解しようとしています。私は哲学的な答えを求めているのではありません。あなたのコメントは私の質問に対する誤解を示しており、SOが有毒であるという認識に貢献していると思います。
6005

@ 6005スヴェンのコメントは、SOが非難されている「毒性のある文化」とはまったく無関係です(性別、セクシュアリティ、人種などの理由で実際に彼が別様に扱っていると思わない限り)。彼はあなたの質問がSOに適しているかどうかについての(文明化された)議論に貢献しました。
ピーターホール

3
多分私は少し簡潔でしたが、私は確かに気分を害するつもりはありませんでした。私はあなたの質問に何か問題があるとは思わない–私はそれを楽しんだ。:) Rustの型推論の詳細は指定されていないため、「正しい」答えはないと思います。この場合、型推論どのように機能するかを確認できます、それ以上の理由はありません。コンパイラの内部に精通している人なら、コンパイラがこのように動作する理由を説明できるかもしれませんが、言語についてはあまり学習しません。
Sven Marnach

回答:


6

最初のコードブロックの戻り値の型は、!終了しないループがあるため、実際には(neverと呼ばれます)です(したがって、錆が到達できないという警告が表示されます)。完全なタイプは次のようになります。

fn f() -> !

!何よりもRustの「ボトム」タイプに似ていると思います。2番目のケースでは、最初の例のように、コンパイラが「到達不能」分析に到達する前にi32と()の不一致が原因で、型チェックの初期段階で関数がエラーになる可能性があります。

編集:示唆されたように、これは錆びた本の関連部分ですhttps://doc.rust-lang.org/book/ch19-04-advanced-types.html#the-never-type-that-never-returns


1
Rustブックのそのセクションへのリンクが役立つ場合があります。具体的には、「この動作を説明する正式な方法は、型の式!を他の型に強制変換できることです。
Herohtar

ありがとう!それは興味深いです、私はこれを読みます。ただし、警告はそれとは関係ありません。警告は単に「到達できないステートメント」です(最後のを指していますprintln!
6005

それはまさに私がほのめかしていたことです。ステートメントに到達できず、戻り値のタイプは!です。
leshow

回答ありがとうございます。正解であり、間違った説明は受け付けていません:)
6005

正解です。リンクを読んでください
leshow

0

(スヴェンの最初のコメントを回答に変換する)

Rustコンパイラは、関数本体の型を推測する必要があります。最初のケースでは、return式はなく、コンパイラーは明らかに!無限ループのため、戻り値の型として、これは理にかなっています。2番目のケースでは、戻り式があるため、型推論ソルバーはそれを使用して型を推論します。これも理にかなっています。

私はこれが言語リファレンスで指定されているとは思いませんし、それがどんな意味でも重要だとは思いません。到達できないステートメントを省略すれば大丈夫です。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.