Rust 和可变性中的模式匹配

Pattern matching in rust and mutability

假设我有一个 Option<String> 并且想要进行模式匹配以获得对 String 的可变引用。我可以执行以下操作(_a 需要可变):

  let mut _a: Option<String> = Some(String::from("foo"));
  if let Some(ref mut aa) = _a {
    aa.push_str("_");
    println!("aa: {:?}", aa)
  }

现在假设我有两个要进行模式匹配的 Option<String> 值。

  let _b: Option<String> = Some(String::from("bar"));
  let _c: Option<String> = Some(String::from("baz"));
  if let (Some(ref mut bb), Some(ref mut cc)) = (_b, _c) {
    bb.push_str("_");
    cc.push_str("_");
    println!("bb: {:?}, cc: {:?}", bb, cc);
  }

奇怪的是,我可以在模式中使用 ref mut,即使 _b_c 都不可变,而且我可以改变字符串。为什么在这种情况下允许这样做?我希望这不会编译,除非 _b_c 都被声明为可变的,类似于上面的第一个例子。

我认为可能发生的情况是在模式匹配中构造了一个元组,即 (_b, _c),然后一些编译器魔术允许 ref mut 在 "bound" 的模式上] 到这个元组。对吗?

Rust 版本:

rustc 1.41.1 (f3e1a954d 2020-02-24)

如果值包装在元组中,则不需要 mut,因为元组是一个新值 (playground):

let a = Some(String::from("foo"));
if let (Some(mut aa),) = (a,) {
    aa.push_str("_");
    println!("aa: {:?}", aa)
}