在Rust中,对非引用类型和引用类型进行模式匹配会发生什么?

7

当针对不包含引用的模式匹配参考时会发生什么?

以下是使用结构体模式的示例:

fn main() {
    struct S(u32);
    let S(x) = &S(2);
    // type of x is `&u32`
}

这种行为让我感到惊讶,因为左边的模式似乎与右边的数据不匹配,不像let &S(x) = &S(2),其中&对齐了。

看起来发生的情况是当RHS是结构引用且lhs是带有字段模式的结构模式时,字段模式中变量的类型为&F,其中F是字段的类型。

我要寻找的是:

  • 解释预期行为的参考资料
  • 解释该行为的说明足以概括元组和枚举的情况。例如,在 let (x,) = &(2,);中,x 的类型是 (更正: &i32)。

我在 Rust 参考手册和 Rust 书籍中都没有找到相关内容,但是我可能已经错过了。


2
@Stargateur ,这不是自动引用,而是匹配的人体工程学。在 Rust 1.26 之前,该示例无法编译,而自动引用存在于 1.0 版本中。 - user4815162342
2
@Stargateur,我并不是在抱怨,只是想理解这种行为,以便我能够最有效地使用功能和阅读代码。https://dev59.com/2sPra4cB1Zd3GeqPc0rG#70642417 中链接的资源对我很有帮助。 - Max Heiber
1
我不知道"autoref"是什么意思,所以查了一下资料,并在此提供链接,以便未来读者参考:据我所知,该术语指的是方法调用中“调整”的最后一步骤(“然后,对于每个候选T,在&T和&mut T之后立即将其添加到列表中”)。https://doc.rust-lang.org/reference/expressions/method-call-expr.html,基于这个问题标题中的“autoref”:https://github.com/rust-lang/reference/issues/62 - Max Heiber
1
是的,autoref只是添加了一些隐式的“&”。因此,如果您有T,则可以在不使用&/显式引用的情况下从&T调用方法。 - MeetTitan
2
编译器工作的一半是拒绝不完整的程序。 如果您认为自己的程序存在问题,而编译器没有标记它,则应该感到担忧(仅因为这表明您对编译器的理解不完整)。 - BallpointBen
显示剩余2条评论
1个回答

10
你遇到的行为是在Rust 1.26中引入的"匹配人体工程学",并在它自己的RFC中描述。简而言之,在将引用与非引用模式进行匹配时,默认情况下会切换绑定模式以使用ref绑定。
在你的情况下,let S(x) = &S(2)被展开为let &S(ref x) = &S(2)。关于ref的"传统"状态很快在Rust书中讨论

一个解释行为的通用说明,足以解释元组和枚举类型以及结构体发生的情况。例如,在let (x,) = &(2,);中,x的类型是i32

这是不正确的-如果你询问Rust x的类型,它会告诉你它是&i32,正如人们所期望的那样:
let (x,) = &(2i32,);
let () = x;
//       ^^   - this expression has type `&i32`

换句话说,适用于结构体和枚举的绑定模式规则也适用于元组。


为什么不在重复的问题中回答它?现在我们有两个回答相同问题的问题。我投票关闭另一个问题,因为我发现这个问答质量更高。 - Stargateur
1
@Stargateur 当我写回复时,我没有意识到有一个重复的问题。如果你指的是这个,它似乎从不同的角度提出了问题,所以我的回答也不适用。 - user4815162342

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