模式匹配如何与 Rust 中的 ref 一起使用?

How does pattern matching work with ref in Rust?

刚从 here:

看到这段代码
...
    let mut txn = client.transaction()?;
    loop {
        let mut sp = txn.savepoint("cockroach_restart")?;
        match op(&mut sp).and_then(|t| sp.commit().map(|_| t)) {
            Err(ref err)
                if err
                    .code()
                    .map(|e| *e == SqlState::T_R_SERIALIZATION_FAILURE)
                    .unwrap_or(false) => {}
            r => break r,
        }
    }
    .and_then(|t| txn.commit().map(|_| t))
...

目前还不清楚 match 块内部发生了什么。

  1. 为什么在处理 Err 后没有处理 Ok 变体?
  2. r从何而来?
  3. err.code()...的逻辑是什么?它是从指针到 bool 的映射,然后在 bool 上展开???然后什么都不做?

Why is there no handling for Ok variant after handling Err?

匹配的第二个分支是匹配任何值的包罗万象的模式,因此它涵盖了 Ok 变体,以及 Err 变体,第一个中的守卫变体失败。

Where does r come from?

当像r这样的标识符被用作模式时,它表示一个新的局部变量来捕获匹配的值。

What's the logic with err.code()...?

postgres::Error::code() returns 一个 Option<&SqlState>。如果提供了代码(选项为 Some),并且等于 SqlState::T_R_SERIALIZATION_FAILURE,则循环继续。如果它不是 T_R_SERIALIZATION_FAILURE 或未提供(选项是 None),则匹配守卫 returns false 和 catch-all 模式被执行,停止循环。

逐步解开 code() 的处理:

  • postgres::Error::code() returns Option<&SqlState>.
  • Option<&SqlState>::map(closure)Option<&SqlState> 映射到 Option<type returned by the closure>。 The closure is called only if the option is Some, otherwise Option::map just returns None.由于我们的闭包只评估 ==,它 returns boolmap 因此 returns Option<bool>。 (闭包必须使用 * 来取消引用该值,因为它接收 &SqlState。)
  • Option<bool>::unwrap_or(default_value) 如果选项为 Some 则计算为选项中的值,如果为 None 则计算为 default_value,有效地将 Option<bool> 转换为一个 bool,我们需要 if.