对发生恐慌的模式匹配进行类型检查

Bar*_*rry 7 rust

我试图了解 Rust 的规则!和类型检查。

该函数进行类型检查:

fn works<E>(r: Result<i32, E>) -> i32 {
    match r {
        Ok(v) => v,
        Err(_) => {
            panic!("bad");
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

而这个则没有:

fn fails<E>(r: Result<i32, E>) -> i32 {
    match r {
        Ok(v) => v,
        Err(_) => {
            panic!("bad");
            ()
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

这似乎与我实际上是否选择不稳定!功能无关。使用 时fails,我收到有关无法访问代码的警告和有关手臂返回 a而不是 a 的错误 ( E0308 ) 。Err()i32

为什么有这样的区别?我的印象是{ E; }和之间确实没有区别{ E; () }- 前者没有最终操作数,所以是隐式的(),而后者有最终操作数,所以是......显式的()。但在这种情况下, 的存在会panic!导致 那里;没有效果。

实际上是否{ panic!("bad"); }以某种方式具有类型!,或者编译器是否有其他方式简单地抑制错误?

Cha*_*man 6

我不认为这在某处有记录,而且我不知道这是否是故意的 - 您可以尝试报告错误。

这种差异源于这样的事实:当块中存在尾部表达式时,编译器首先期望它与预期的返回类型匹配,如果不匹配则发出错误。只有这样,它才会检查块是否发散(有一个返回 的表达式!),如果发散则允许任何类型,但错误已经发出。

这里编译器检查尾部表达式的类型如果块发散,它允许任何类型

这在 rustc 的源代码中有所记录

// Subtle: if there is no explicit tail expression,
// that is typically equivalent to a tail expression
// of `()` -- except if the block diverges. In that
// case, there is no value supplied from the tail
// expression (assuming there are no other breaks,
// this implies that the type of the block will be
// `!`).
Run Code Online (Sandbox Code Playgroud)