为什么这个借用被认为是 "used later",尽管它显然不是?

Why is this borrow considered to be "used later" even though it clearly isn't?

就在我以为我已经弄明白了一生的时候...

编译器不会让这种情况发生:

fn main() {
    let mut thing = Thing();

    let mut a = MutReference { data: &mut thing };
    a.another_reference_mut();
    a.another_reference_mut();
}

struct Thing();

struct MutReference<'a> {
    data: &'a mut Thing,
}

impl<'a> MutReference<'a> {
    fn another_reference_mut(&'a mut self) -> MutReference<'a> {
        MutReference { data: self.data }
    }
}

错误信息比较混乱:

error[E0499]: cannot borrow `a` as mutable more than once at a time
 --> src/main.rs:6:5
  |
5 |     a.another_reference_mut();
  |     ------------------------- first mutable borrow occurs here
6 |     a.another_reference_mut();
  |     ^^^^^^^^^^^^^^^^^^^^^^^^^
  |     |
  |     second mutable borrow occurs here
  |     first borrow later used here

他说的“先借后用”是什么意思?很明显,第一个借用并没有在那里使用——它被丢弃在第 5 行并且再也没有使用过。即使将该行包装在 {} 中也无济于事。

经过一些修改,我发现为函数创建一个单独的生命周期可以解决问题:

impl<'a> MutReference<'a> {
    fn another_reference_mut<'b>(&'b mut self) -> MutReference<'b> {
        MutReference { data: self.data }
    }
}

'b也可以省略)

现在我很确定这是正确的解决方案,但我仍然不确定为什么旧代码不起作用。看来我写了一些我不打算的生命周期约束,但我不知道如何正确推理这种情况下的生命周期,编译器错误也无济于事。

我的理解是,当在多个“输入”引用和一个“输出”引用上使用相同的生命周期时,这意味着“输出”引用不能超过任何输入引用...但是似乎这里发生了其他事情——就好像 &'a mut self 输入引用“迫使”return 值比正常情况下更长寿?这是如何运作的?我的旧代码有什么问题?

如果您尝试 运行 通过您的代码,明确标记每个生命周期,原因就很简单。实际发生的是,在第一个代码中,another_reference_mut 函数在整个生命周期内不是通用的:&mut self 的生命周期是 'a,这与由 &'a mut ThingMutReference<'a> 中使用。这意味着你第一次调用 a.another_reference_mut 时,你必须使用 可变借用,它的寿命与 &mut Thing 一样长。当您尝试第二次调用它时,您必须对 a 进行另一个可变借用,这意味着第一个可变借用必须具有“结束”(粗略地说)的生命周期,但这意味着 &mut Thing 不再有效,意味着 a 本身不再有效。这就是 Rust 无法找到符合您要求的生命周期的原因。

在您的第二个版本中,您使可变借用独立于(或至少不强制等于)&mut Thing 的生命周期,因此也是 a 的生命周期。然后 Rust 可以使 'b'a 更短,这允许您借用两次可变的 a.