発散関数

発散関数は値を返しません。空の型である!を使って示してください。


#![allow(unused_variables)]
fn main() {
fn foo() -> ! {
    panic!("This call never returns.");  // この呼び出しは決して返りません。
}
}

他の方とは違い、この型はインスタンス化できません。この型には持ちうる値 がないからです。一つの値を持ちうる()型とは違うことに注意してください。

例えば、この関数は、返り値の型に関する情報がありませんが、 普通に値を返します。

fn some_fn() {
    ()
}

fn main() {
    let a: () = some_fn();
    println!("This function returns and you can see this line.")  // この関数は値を返し、この行が出力されます。
}

この関数とは違い、呼び出し元に制御が戻ることはありません。

#![feature(never_type)]

fn main() {
    let x: ! = panic!("This call never returns.");
    println!("You will never see this line!");  // この行は出力されません。
}

これは、抽象的な概念に見えますが、実はとても有用で、手頃です。 この型の主な利点は、どんな型にもキャストでき、matchの枝など、 正確な型が必要なときに使えます。これを使って、このような関数が書けます。

fn main() {
    fn sum_odd_numbers(up_to: u32) -> u32 {
        let mut acc = 0;
        for i in 0..up_to {
            // このmatch式は、変数additionの型であるu32を返さなければ
            // いけないことに注意してください。
            let addition: u32 = match i%2 == 1 {
                // 変数iは u32になるので、問題ありません。
                true => i,
                // 一方、"continue"式はu32を返しませんが、何も返さないことは、
                // match式の型の要件に違反しないので、これでも問題ありません。
                false => continue,
            };
            acc += addition;
        }
        acc
    }
    println!("Sum of odd numbers up to 9 (excluding): {}", sum_odd_numbers(9));  // 9未満の奇数の和: {}
}

ネットワークサーバのように、永遠にループ(例えばloop {})する処理や、 プロセスを終了する関数(例えばexit())などに使われます。