考虑以下 Rust 代码:
fn f() -> i32 {
loop {
println!("Infinite loop!");
}
println!("Unreachable");
}
尽管返回类型错误,它仍会编译(带有警告)并运行。
编译器似乎可以接受
()
的返回类型在最后一行,因为它检测到此代码不可访问。但是,如果我们删除最后一个分号:
fn f() -> i32 {
loop {
println!("Infinite loop!");
}
println!("Unreachable")
}
然后代码不再编译,出现类型错误:
error[E0308]: mismatched types
--> src/main.rs:14:5
|
14 | println!("Unreachable")
| ^^^^^^^^^^^^^^^^^^^^^^^ expected `i32`, found `()`
|
= note: this error originates in a macro outside of the current crate (in Nightly builds, run with -Z external-macro-backtrace for more info)
为什么是这样?返回类型不一样吗,
()
,在这两个代码片段中?注意:我有兴趣了解为什么 Rust 编译器在这两个示例中表现不同,即 Rust 编译器是如何实现的。从语言设计的角度来看,我并不是要问一个关于它“应该”如何表现的哲学问题(我知道这样的问题可能是题外话)。
最佳答案
第一个代码块中的返回类型实际上是!
(称为从不),因为你有一个永远不会退出的循环(所以 rust 会给你一个警告,说它无法访问)。完整的类型是:fn f() -> !
我怀疑 !
更像是 Rust 中的“底部”类型,而不是其他任何东西。在第二种情况下,由于 i32 和 () 在编译器进行“不可达性”分析之前不匹配,您的函数可能会在类型检查的早期阶段出错,就像在第一个示例中一样。
编辑:按照建议,这里是 rust book https://doc.rust-lang.org/book/ch19-04-advanced-types.html#the-never-type-that-never-returns 的相关部分
关于rust - 为什么 Rust 允许返回类型错误的代码,但只允许尾随分号?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/60330870/