为什么 &Option<T> 上的模式匹配会产生 Some(&T) 类型的东西?

Why does pattern matching on &Option<T> yield something of type Some(&T)?

我这里有一个小小的playground example

fn main() {
    let l = Some(3);
    match &l {
        None => {}
        Some(_x) => {} // x is of type &i32
    }
}

我在 &Option 上进行模式匹配,如果我使用 Some(x) 作为分支,为什么 x 的类型是 &i32

你匹配的表达式 &l 的类型是 &Option<i32>,所以如果我们是严格的模式应该是 &None&Some(x),如果我们使用这些模式,x的类型确实是i32。如果我们像您在代码中所做的那样省略模式中的 & 符号,首先看起来模式根本无法匹配,编译器应该抛出类似于“预期选项,找到引用”的错误,并且确实这是编译器在 Rust 版本 1.26 之前所做的。

当前版本的 Rust 支持 RFC 2005 引入的“匹配人体工程学”,现在允许将对枚举的引用与不带符号的模式进行匹配。一般来说,如果你的匹配表达式只是一个引用,你不能将任何成员移出枚举,所以匹配一个引用与 Some(x) 等同于匹配模式 &Some(ref x),即 x 成为对 Option 的内部值的引用。在您的特定情况下,内部值是 i32,即 Copy,因此您可以匹配 &Some(x) 并获得 i32,但这不是可能用于一般类型。

RFC 的想法是让模式中的 & 符号和 refs 更容易正确,但我不完全相信新规则是否真的简化了事情,或者它们是否增加了通过在某些情况下使事情神奇地工作而造成的混乱,从而使人们更难以真正理解底层逻辑。 (这个观点是有争议的——见评论。)