繁体   English   中英

Rust 模式匹配选项的一种方式工作但其他方式不工作的参考(借用检查器不通过)

[英]Rust pattern match on a reference of Option one way working but the others way not (borrow checker not pass)

在 Rust 如果结构是这样的

struct Node {
    next: Option<Box<Node>>,
}

然后实现一个方法来查找尾部并在其上添加一个新节点可能看起来像这样

fn add1<'a>(mut node: &'a mut Node) {
    while let Some(next) = node.next.as_deref_mut() {
        node = next;
    }
    node.next = Some(Box::new(Node { next: None }));
}

然后遇到这样的错误:

error[E0506]: cannot assign to `node.next` because it is borrowed
  --> src/lib.rs:16:5
   |
12 | fn add1<'a>(mut node: &'a mut Node) {
   |         -- lifetime `'a` defined here
13 |     while let Some(next) = node.next.as_deref_mut() {
   |                            ------------------------
   |                            |
   |                            borrow of `node.next` occurs here
   |                            argument requires that `node.next` is borrowed for `'a`
...
16 |     node.next = Some(Box::new(Node { next: None }));
   |     ^^^^^^^^^ assignment to borrowed `node.next` occurs here

其他一些变体也不起作用:

fn add1_borken_ergonomics(mut node: &mut Node) {
    while let Some(next) = &mut node.next {
        node = next;
    }
    node.next = Some(Box::new(Node { next: None }));
}

fn add1_borken_explicit<'a>(mut node: &'a mut Node) {
    while let Some(ref mut next) = *&mut node.next {
        node = next;
    }
    node.next = Some(Box::new(Node { next: None }));
}

这给出了类似的错误

error[E0506]: cannot assign to `node.next` because it is borrowed
  --> src/lib.rs:30:5
   |
26 | fn add1_borken_explicit(mut node: &mut Node) {
   |                                   - let's call the lifetime of this reference `'1`
27 |     while let Some(ref mut next) = *&mut node.next {
   |                    ------------     -------------- borrow of `node.next` occurs here
   |                    |
   |                    assignment requires that `node.next` is borrowed for `'1`
...
30 |     node.next = Some(Box::new(Node { next: None }));
   |     ^^^^^^^^^ assignment to borrowed `node.next` occurs here

所以问题是,为什么像这样写这样的打击它会起作用

fn add1_working<'a>(mut node: &'a mut Node) {
    while let Some(ref mut next) = node.next {
        node = next;
    }
    node.next = Some(Box::new(Node { next: None }));
}

上面的代码应该都是一样的意思,但是编译器对待它们的方式不同?

Rust 操场上的示例代码 同样的问题也可以在另一个更简单的代码示例中看到(来自问题页面,见下文。)

问了一圈后发现了一个与这个https://github.com/rust-lang/rust/issues/67957相关的问题,但似乎没有提到是否是一些编译器错误可以稍后修复,或者是因为我们需要更好地理解语言的某些方面?

这是一个已知的错误

我从 rust 论坛得到了解释

还有另一个与此相关的错误报告,类似于 StackOverflow 线程中链接的错误报告,但有更多讨论: if/while Some(n) = &mut foo sugar will leak a temporary mutable borrow to current scope in specific situation · Issue # 62013·rust-lang/rust·GitHub

我没有遵循所有细节,但我相信这里的行为差异是无意的,最终会得到修复。 使用下一代借用检查器Polonius编译时,两个函数都编译成功。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM