示例代码片段:
fn foo() -> i32 {
let a = return 2;
a + 1
}
fn main() {
println!("{}", foo());
}
Run Code Online (Sandbox Code Playgroud)
我希望由于a永远不会真正被分配任何东西,所以它的类型应该是!. 然而编译器告诉我它的类型实际上是()(单位类型)。这对我来说很奇怪。这背后的原因可能是什么?
的类型return 42 是 !:
break,continue并且return表达式也有类型!。例如我们可以这样写:Run Code Online (Sandbox Code Playgroud)#![feature(never_type)] let x: ! = { return 123 };
来自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 时代并不存在。随着时间的推移,它变得更像是一等公民,但需要一些特殊情况才能向后兼容,这些情况!将被视为()与任何其他类型相同。