为什么没有重叠借用时会出现借用错误?

5
以下代码由于借用错误而失败:
extern crate chrono; // 0.4.6

fn main() {
    let mut now = chrono::Local::today();
    now = std::mem::replace(&mut now, now.succ());
}

错误信息如下:
error[E0502]: cannot borrow `now` as immutable because it is also borrowed as mutable
 --> src/lib.rs:5:39
  |
5 |     now = std::mem::replace(&mut now, now.succ());
  |           ----------------- --------  ^^^ immutable borrow occurs here
  |           |                 |
  |           |                 mutable borrow occurs here
  |           mutable borrow later used by call

为什么这里会出现借用错误?now.succ() 返回一个新的对象,看起来 succ() 调用应该返回新的对象,然后在可变借用和 replace 发生之前结束不可变借用。

我认为顺序很重要。但无论如何,你已经有了解决方案。 - Stargateur
是的,问题不在于如何修复它,而在于为什么它会出现错误。 - Listerone
1个回答

4

参数的顺序很重要。例如,这个是有效的:

/// Same as `std::mem::replace`, but with the reversed parameter order.
pub fn replace<T>(src: T, dest: &mut T) -> T {
    std::mem::replace(dest, src)
}

fn main() {
    let mut now = chrono::Local::today();
    now = replace(now.succ(), &mut now);
}

(播放链接)

但在您的示例中,&mut now 首先出现,当评估第二个参数时,它已被借用。


1
@Stargateur,我从来没有想过让这个示例函数起作用。我甚至要打unimplemented(),但懒得连这个都做了。 - mcarton
@Listerone 在这个例子中,顺序实际上并不重要,但对于具有不同生命周期和引用的更复杂的示例,它可能很重要,因此编译器必须在某个时候设置一条线。 - mcarton
@mcarton 这是真的吗?由于不可变借用是一个必须在替换实际接收到可变引用之前返回的调用,除了预期的情况外,是否存在任何这两者可能相互作用的情况? - jspencer
我认为函数调用参数的求值顺序是未指定的。 - hkBst
在Rust中,@hkBst已经被指定了,即使它没有被指定,借用检查器也可以比生成的代码更加受限。 - mcarton
显示剩余2条评论

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