为什么 Rust 允许带有错误 return 类型的代码,但只允许带有尾随分号?
Why does Rust allow code with the wrong return type, but only with a trailing semicolon?
考虑以下 Rust 代码:
fn f() -> i32 {
loop {
println!("Infinite loop!");
}
println!("Unreachable");
}
尽管 return 类型是错误的,但它编译(带有警告)并运行。
编译器似乎可以接受最后一行 ()
的 return 类型,因为它检测到此代码无法访问。
但是,如果我们删除最后一个分号:
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)
这是为什么?在这两个代码片段中,return 类型是否相同 ()
?
注意: 我很想了解为什么 Rust 编译器在这两个示例中的行为不同,即 Rust 编译器是如何实现的。我并不是要从语言设计的角度问一个关于它 "should" 行为方式的哲学问题(我知道这样的问题可能会跑题)。
第一个代码块中的 return 类型实际上是 !
(调用 never),因为你有一个永不退出的循环(所以 rust 给你一个警告,说它无法访问)。完整类型为:
fn f() -> !
我怀疑 !
更像是 Rust 中的 'bottom' 类型。在第二种情况下,您的函数可能会在类型检查的早期阶段出错,因为在编译器进入 'unreachability' 分析之前 i32 和 () 之间不匹配,就像第一个示例中那样。
编辑:按照提示,这里是rust book的相关部分https://doc.rust-lang.org/book/ch19-04-advanced-types.html#the-never-type-that-never-returns
(将斯文的第一条评论转化为答案)
Rust 编译器需要推断函数体的类型。在第一种情况下,没有 return 表达式,显然编译器推断 !作为 return 类型,因为无限循环,这是有道理的。在第二种情况下,有一个 return 表达式,因此类型推断求解器使用它来推断类型,这也是有道理的。
我不认为这在语言参考中指定,也不认为它有任何关系 - 只需省略无法访问的语句就可以了。
考虑以下 Rust 代码:
fn f() -> i32 {
loop {
println!("Infinite loop!");
}
println!("Unreachable");
}
尽管 return 类型是错误的,但它编译(带有警告)并运行。
编译器似乎可以接受最后一行 ()
的 return 类型,因为它检测到此代码无法访问。
但是,如果我们删除最后一个分号:
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)
这是为什么?在这两个代码片段中,return 类型是否相同 ()
?
注意: 我很想了解为什么 Rust 编译器在这两个示例中的行为不同,即 Rust 编译器是如何实现的。我并不是要从语言设计的角度问一个关于它 "should" 行为方式的哲学问题(我知道这样的问题可能会跑题)。
第一个代码块中的 return 类型实际上是 !
(调用 never),因为你有一个永不退出的循环(所以 rust 给你一个警告,说它无法访问)。完整类型为:
fn f() -> !
我怀疑 !
更像是 Rust 中的 'bottom' 类型。在第二种情况下,您的函数可能会在类型检查的早期阶段出错,因为在编译器进入 'unreachability' 分析之前 i32 和 () 之间不匹配,就像第一个示例中那样。
编辑:按照提示,这里是rust book的相关部分https://doc.rust-lang.org/book/ch19-04-advanced-types.html#the-never-type-that-never-returns
(将斯文的第一条评论转化为答案)
Rust 编译器需要推断函数体的类型。在第一种情况下,没有 return 表达式,显然编译器推断 !作为 return 类型,因为无限循环,这是有道理的。在第二种情况下,有一个 return 表达式,因此类型推断求解器使用它来推断类型,这也是有道理的。
我不认为这在语言参考中指定,也不认为它有任何关系 - 只需省略无法访问的语句就可以了。