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

3
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,
        }
    }
}

如评论中所述,为什么item&Foo类型?有什么规则表明item将是&Foo类型而不是Foo类型?

我理解item不能是Foo类型;&self表示self是一个引用,因此没有意义从引用中移动值,但是否有任何规范能清晰地定义这些规则呢?


@SergioTulentsev 谢谢您的回复。实际上,RefCell与我所要问的无关。为避免混淆,已将其移除。 - Helin Wang
1个回答

8

RFC 2005(又称为匹配机制舒适性 引入了这个规则。

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

  1. Match on self and prefix each pattern with & to "destructure" the reference.

    fn tail(&self) -> Option<&Foo> {
        match self {
            &Cons(_, ref item) => Some(item),
            &Nil => None,
        }
    }
    
  2. Match on *self and don't prefix each pattern with & (because *self is not a reference).

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

然而,在这两种情况下,我们都需要写上ref item,否则会出现error[E0507]: cannot move out of borrowed content的错误。

但是,在你所写的match中,被匹配的表达式是一个引用(类型为&List),但模式不是引用模式(如上文1.所示)。这就是匹配人体工程学发挥作用的地方:规则指出,当引用与非引用模式匹配时,该模式内的绑定将按引用方式而非按值方式绑定(即好像它们前面加了ref)。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接