为什么这个借用被认为是 "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 Thing
在 MutReference<'a>
中使用。这意味着你第一次调用 a.another_reference_mut
时,你必须使用 可变借用,它的寿命与 &mut Thing
一样长。当您尝试第二次调用它时,您必须对 a
进行另一个可变借用,这意味着第一个可变借用必须具有“结束”(粗略地说)的生命周期,但这意味着 &mut Thing
不再有效,意味着 a
本身不再有效。这就是 Rust 无法找到符合您要求的生命周期的原因。
在您的第二个版本中,您使可变借用独立于(或至少不强制等于)&mut Thing
的生命周期,因此也是 a
的生命周期。然后 Rust 可以使 'b
比 'a
更短,这允许您借用两次可变的 a
.
就在我以为我已经弄明白了一生的时候...
编译器不会让这种情况发生:
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 Thing
在 MutReference<'a>
中使用。这意味着你第一次调用 a.another_reference_mut
时,你必须使用 可变借用,它的寿命与 &mut Thing
一样长。当您尝试第二次调用它时,您必须对 a
进行另一个可变借用,这意味着第一个可变借用必须具有“结束”(粗略地说)的生命周期,但这意味着 &mut Thing
不再有效,意味着 a
本身不再有效。这就是 Rust 无法找到符合您要求的生命周期的原因。
在您的第二个版本中,您使可变借用独立于(或至少不强制等于)&mut Thing
的生命周期,因此也是 a
的生命周期。然后 Rust 可以使 'b
比 'a
更短,这允许您借用两次可变的 a
.