这些签名之间的主要区别归结为! 可以强制 转换为任何其他类型,因此兼容 与任何其他类型(因为这个代码路径永远不会被采用,我们可以假设它是我们需要的任何类型)。当我们有多个可能的代码路径时,这一点很重要,例如 if-else 或 match。
例如,考虑以下(可能是做作的,但希望足够清晰)代码:
fn assert_positive(v: i32) -> u32 {
match v.try_into() {
Ok(v) => v,
Err(_) => func(),
}
}
当func被声明返回!时,这个函数compiles成功。如果我们去掉返回类型,func会被声明为返回(),编译breaks:
error[E0308]: `match` arms have incompatible types
--> src/main.rs:8:19
|
6 | / match v.try_into() {
7 | | Ok(v) => v,
| | - this is found to be of type `u32`
8 | | Err(_) => func(),
| | ^^^^^^ expected `u32`, found `()`
9 | | }
| |_____- `match` arms have incompatible types
您也可以将此与definition for Result::unwrap进行比较:
pub fn unwrap(self) -> T {
match self {
Ok(t) => t,
Err(e) => unwrap_failed("called `Result::unwrap()` on an `Err` value", &e),
}
}
这里是unwrap_failed is returning !,所以它与Ok case 中返回的任何类型相统一。