発散関数
発散関数は決して戻りません。これらは空の型である ! を使って示されます。
#![allow(unused)] fn main() { fn foo() -> ! { panic!("この呼び出しは決して戻りません。"); } }
他のすべての型とは異なり、この型はインスタンス化できません。なぜなら、この型が取り得るすべての可能な値の集合は空だからです。これは、取り得る値が正確に 1 つだけある () 型とは異なることに注意してください。
たとえば、この関数は通常どおり戻りますが、戻り値には情報がありません。
fn some_fn() { () } fn main() { let _a: () = some_fn(); println!("この関数は戻るので、この行を見ることができます。"); }
これに対して、次の関数は呼び出し元に制御を戻すことは決してありません。
#![feature(never_type)]
fn main() {
let x: ! = panic!("この呼び出しは決して戻りません。");
println!("この行を見ることは決してありません!");
}
これは抽象的な概念のように思えるかもしれませんが、実際には非常に有用で、しばしば便利です。この型の主な利点は、他の任意の型にキャストできることであり、match の分岐のように正確な型が必要とされる状況で汎用的に使えます。この柔軟性により、次のようなコードを書くことができます。
fn main() { fn sum_odd_numbers(up_to: u32) -> u32 { let mut acc = 0; for i in 0..up_to { // この match 式の戻り値の型は u32 でなければならないことに注意してください // これは "addition" 変数の型によるものです。 let addition: u32 = match i%2 == 1 { // "i" 変数は u32 型であり、これはまったく問題ありません。 true => i, // 一方、"continue" 式は u32 を返しませんが、 // 決して戻らないため、依然として問題ありません。したがって // match 式の型要件に違反しません。 false => continue, }; acc += addition; } acc } println!("9 未満(9 を含まない)の奇数の合計: {}", sum_odd_numbers(9)); }
これはまた、ネットワークサーバーのように永遠にループする関数(例: loop {})や、プロセスを終了させる関数(例: exit())の戻り値の型でもあります。