発散する関数

発散する関数は決してリターンしない関数です。こうした関数は ! を使って、空の型であることが示されます。

#![allow(unused)]
fn main() {
fn foo() -> ! {
    panic!("This call never returns.");
}
}

他の全ての型と異なり、この型はインスタンス化できません。この型が持ちうる全ての値の集合は空です。この型は()型とは異なることに注意してください。()型は値をただ1つだけ持つ型です。

例えば、この関数は通常どおりリターンしますが、戻り値には何の情報も含みません。

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!");
}

Although this might seem like an abstract concept, it is actually very useful and often handy. The main advantage of this type is that it can be cast to any other type, making it versatile in situations where an exact type is required, such as in match branches. This flexibility allows us to write code like this:

fn main() {
    fn sum_odd_numbers(up_to: u32) -> u32 {
        let mut acc = 0;
        for i in 0..up_to {
            // 変数"addition"の型がu32であるため、
            // このmatch式は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));
}

この型は、ネットワークサーバのような永遠にループする関数(例:loop {})の戻り値の型や、プロセスを終了させる関数(例:exit())の戻り値の型としても使用されます。