【发布时间】:2020-06-05 10:10:45
【问题描述】:
考虑以下 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 编译器需要推断函数体的类型。在第一种情况下,没有返回表达式,显然由于无限循环,编译器将
!推断为返回类型,这是有道理的。在第二种情况下,有一个返回表达式,因此类型推断求解器使用它来推断类型,这也很有意义。我不认为这是在语言参考中指定的,我认为这在任何方面都不重要——只要省略 unreachable 语句就可以了。 -
@SvenMarnach 仍然是关于语言的问题。我认为这仍然是主题。
-
@SvenMarnach 真的有必要吗?我是 Rust 的新手,我试图理解为什么编译器会这样做。我不要求任何哲学答案。我认为您的 cmets 对我的问题有一些误解,并有助于人们认为 SO 是有毒的。
-
@6005 Sven 的 cmets 与 SO 被指控的“有毒文化”完全无关(除非你真的认为他因为你的性别、性取向、种族等而区别对待你)。他为关于您的问题是否适合 SO 的(文明)讨论做出了贡献。
-
也许我有点简洁,但我当然没有冒犯的意思。我不认为你的问题有什么问题——我什至喜欢它。 :) 我只是不认为有任何“正确”的答案,因为没有指定 Rust 中类型推断的细节。在这种情况下,我们可以看到类型推断 做了什么,但根本没有任何更深层次的原因。也许对编译器内部有深入了解的人可以解释为什么编译器会这样,但我们不会对这种语言了解太多。
标签: rust return-type unreachable-code