Rust模式匹配如何确定绑定变量是引用还是值?

Hel*_*ang 0 pattern-matching rust

use crate::List::{Cons, Nil};

#[derive(Debug)]
struct Foo {}

#[derive(Debug)]
enum List {
    Cons(i32, Foo),
    Nil,
}

impl List {
    fn tail(&self) -> Option<&Foo> {
        match self {
            Cons(_, item) => Some(item), // why `item` is of type `&Foo`?
            Nil => None,
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

如评论中所述,为什么是item类型&Foo?说的item是类型&Foo而不是类型的规则是什么Foo

我理解项目是没有意义的Foo; &self表示self引用是参考,因此将值从引用中移出是没有意义的,但是是否有任何明确定义规则的规范?

Fra*_*gné 6

RFC 2005(又称匹配人体工程学引入了该规则。

在实施更改之前,有两种编写此方法的方法match

  1. 匹配self每个模式并&在其前面加上前缀,以“破坏”参考。

    fn tail(&self) -> Option<&Foo> {
        match self {
            &Cons(_, ref item) => Some(item),
            &Nil => None,
        }
    }
    
    Run Code Online (Sandbox Code Playgroud)
  2. 匹配*self,不要在每个模式前加上前缀&(因为*self这不是参考)。

    fn tail(&self) -> Option<&Foo> {
        match *self {
            Cons(_, ref item) => Some(item),
            Nil => None,
        }
    }
    
    Run Code Online (Sandbox Code Playgroud)

但是,在两种情况下,我们都需要编写ref item,否则我们将得到error[E0507]: cannot move out of borrowed content

但是,在match您撰写的内容中,匹配的表达式是一个引用(类型&List),但是这些模式不是引用模式(如上述1.)。这是匹配人机工程学的起点:规则说,当引用与非引用模式匹配时,该模式内的绑定通过引用而不是值进行绑定(即,它们以前缀ref)。