`return` 语句不应该返回 `!` (从不输入)吗?

Viv*_*dav 2 return rust

示例代码片段:

fn foo() -> i32 {
    let a = return 2;
    a + 1
}
fn main() {
    println!("{}", foo());
}
Run Code Online (Sandbox Code Playgroud)

我希望由于a永远不会真正被分配任何东西,所以它的类型应该是!. 然而编译器告诉我它的类型实际上是()(单位类型)。这对我来说很奇怪。这背后的原因可能是什么?

mca*_*ton 6

的类型return 42 !

breakcontinue并且return表达式也有类型!。例如我们可以这样写:

#![feature(never_type)]
let x: ! = {
    return 123
};
Run Code Online (Sandbox Code Playgroud)

来自https://doc.rust-lang.org/std/primitive.never.html

但 的特点之一!是它可以强制转换为任何类型的值:

fn foo() -> i32 {
    let a: String = return 2;
    42
}

fn main() {
    println!("{}", foo());
}
Run Code Online (Sandbox Code Playgroud)

这就是使诸如

let num: u32 = match get_a_number() {
    Some(num) => num,
    None => break,
};
Run Code Online (Sandbox Code Playgroud)

(来自同一页面)。

两个分支必须具有相同的类型。num显然是u32,并且break!u32然后,通过强制,break两者可以具有相同的类型u32

这完全没问题,因为类型的值!永远不会存在,因此编译器可以将其“转换”为任何其他类型的任何值。

您的示例中出现混淆的地方是编译器将声明“错误[E0277]:无法添加i32()”。这大概是有历史原因的。!在 Rust 1.0 时代并不存在。随着时间的推移,它变得更像是一等公民,但需要一些特殊情况才能向后兼容,这些情况!将被视为()与任何其他类型相同。