引用模式在进行两次取消引用时会出现什么情况?

7

请问根据人机工程学匹配( RFC 2005 )规则,有人能否解释一下为什么在引用模式中使用单个&会导致匹配值多次取消引用

示例

假设我们有一个 map: HashMap<i32, bool>。考虑表达式 map.iter().filter(|entry| ...),其中entry的类型是&(&i32, &bool)。现在,如果我们按以下两种方式对entry进行模式匹配,会发生什么?

map
    .iter()
    .filter(|entry| {
        let (key1, _) = entry;   // typeof(key1) -> &&i32
        let (&key2, _) = entry;  // typeof(key2) -> i32
    })

据我理解,这两种模式都使用非引用模式匹配引用(元组),因此将默认绑定模式更改为ref。但让我困惑的是,key2的类型最终变成了i32而不是&i32
根据RFC 2005,以下是对上述两个模式进行解糖的尝试:
let &(ref key1_desugared, _) = entry;    // typeof(key1_desugared) -> &&i32
let &(& ref key2_desugared, _) = entry;  // typeof(key2_desugared) -> &i32

虽然key1_desuraged的类型最终与key1的类型匹配,但key2_desugared的类型是&i32

如何以展开形式表达模式key2的正确方式?

游乐场

https://play.rust-lang.org/?version=stable&mode=debug&edition=2021&gist=1cb8170b1221fb1dd221db885f8eed8d


1
可能相关:https://dev59.com/Zl4b5IYBdhLWcg3w7Fgv#QLOiEYcBWogLw_1bax9F - Finomnis
@Finomnis 模式匹配与接收器解析无关。我认为这里的问题确实是提到的 "match ergonomics" RFC 的结果,尽管我也没有预料到。 (我个人非常不喜欢匹配人体工程学,而根据我们在 Stack Overflow 上得到的问题来判断,它们已经引起了很多困惑,而它们的目标是使 Rust 更易于使用。) - Sven Marnach
1个回答

2
这里需要注意的重要一点是,匹配人体工程学只会改变非引用模式的绑定模式,而不是引用模式。这相当于讨论问题Match ergonomics and & pattern中提到的第二种情况。应用该问题答案中的解释:
  • (key1, _) 是一个非引用模式,被匹配到一个引用上,因此 entry 被解引用为 (&i32, _)。由于 key1 是一个非引用模式,它现在以 ref 模式绑定(因为外部绑定被解引用了)。由于 entry.0 是一个 &i32key1 现在变成了一个指向 &i32 的引用,或者说是一个 &&i32
  • (&key2, _) 是一个非引用模式,因此 entry 被解引用为 (&i32, _)。然后,&key2 被匹配到一个 &i32 引用上。由于 &key2 是一个引用模式,匹配人性化规则不适用。因此,key2 是一个 i32

这绝对不是我阅读RFC的方式。首先,如果没有匹配人体工程学,代码将无法编译,因此我认为您不能声称它们不适用。其次,RFC明确指出一旦我们切换到“ref”绑定模式,就没有回头路可走,这应该在最外层元组模式上完成。 - Sven Marnach
@SvenMarnach 我的措辞可能不够好 - 我所说的“匹配人体工程学不适用”是指在第二种情况下,key2的绑定模式保持不变。这是因为所讨论的内部模式 &key2 是一个 引用 模式,并且除了自动解引用之外,匹配人体工程学 RFC 只会更改 非引用 模式的默认绑定模式。在第二种情况下,我们实际上从未切换到 ref 绑定模式,因为我们从未使用非引用模式匹配引用(当然,除了最外层的引用,它被解引用)。 - EvilTak
我同意这似乎是正在发生的事情,但我仍然觉得不可能以这种方式解释RFC措辞。我甚至认为措辞并不含糊,它明确指定了不同的行为。 - Sven Marnach

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