我有以下代码:
struct Baz {
x: usize,
y: usize,
}
struct Bar {
baz: Baz,
}
impl Bar {
fn get_baz_mut(&mut self) -> &mut Baz {
&mut self.baz
}
}
struct Foo {
bar: Bar,
}
impl Foo {
fn foo(&mut self) -> Option<&mut Baz> {
for i in 0..4 {
let baz = self.bar.get_baz_mut();
if baz.x == 0 {
return Some(baz);
}
}
None
}
}
无法编译:
error[E0499]: cannot borrow `self.bar` as mutable more than once at a time
--> src/main.rs:23:23
|
23 | let baz = self.bar.get_baz_mut();
| ^^^^^^^^ mutable borrow starts here in previous iteration of loop
...
29 | }
| - mutable borrow ends here
但是,如果我从Some(baz.x)
返回Foo::foo
(并将返回类型更改为Option<usize>
),则代码会进行编译。这让我相信问题不在于循环,即使编译器似乎表明了这一点。更具体地说,我相信本地可变引用baz
将在循环的下一次迭代中超出范围,导致这是一个非问题。上述代码的生命周期问题是什么?
以下问题类似:
但是,它们处理明确声明的生命周期(特别是这些显式生命周期是答案的一部分)。我的代码省略了这些生命周期,因此删除它们是一种非解决方案。
答案 0 :(得分:5)
它不起作用,因为返回借来的值会将借用扩展到函数的末尾。
有关有用的详细信息,请参阅here。
这适用于non-lexical lifetimes 1.27 每晚版本:
#![feature(nll)]
struct Baz {
x: usize,
y: usize,
}
// ...
非词汇生命期RFC解释了生命的实际工作:
但是当您有一个跨多个语句的引用时会出现问题。在这种情况下,编译器要求生命周期是包含两个语句的最内层表达式(通常是一个块),并且通常比实际需要或期望的要大得多
每夜生锈1.28
作为pointed out by @pnkfelix,从夜间1.28开始的非词汇生命期实现不再编译上述代码。
然而a long-term plan to (re)-enable a more powerful NLL analysis。