循环中的可变借位 [英] Mutable borrow in a loop
问题描述
我有以下代码:
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
但是,如果我从Foo::foo
返回Some(baz.x)
(并将返回类型更改为Option<usize>
),则代码将编译.这使我相信问题不在于循环,即使编译器似乎表明了这一点.更具体地说,我相信局部可变引用baz
在循环的下一次迭代时将超出范围,从而导致这不是问题.上面的代码的生命周期问题是什么?
However, if I return Some(baz.x)
from Foo::foo
(and change the return type to Option<usize>
), the code compiles. This makes me believe the problem is not with the loop even though the compiler seems to indicate so. More specifically, I believe the local mutable reference baz
would go out of scope at the next iteration of the loop, causing this to be a non-problem. What is the lifetime problem with the above code?
以下问题类似:
- Mutable borrow in loop
- Linking the lifetimes of self and a reference in method
- Cannot borrow as mutable more than once at a time in one code - but can in another very similar
但是,它们处理显式声明的生存期(特别是这些显式生存期是答案的一部分).我的代码忽略了这些生命周期,因此删除它们是一个非解决方案.
However, they deal with explicitly declared lifetimes (and specifically these explicit lifetimes are part of the answer). My code omits these lifetimes so removing them is a non-solution.
推荐答案
它不起作用,因为返回借用的值会将借用扩展到函数的末尾.
It does not work because returning a borrowed value extends the borrow to the end of the function.
有关一些有用的详细信息,请参见此处.
See here for some useful details.
这可用于非词汇生存期和 1.27 夜间版本:
#![feature(nll)]
struct Baz {
x: usize,
y: usize,
}
// ...
非词条生命周期RFC解释了生命周期的实际工作:
The non-lexical lifetimes RFC explains the actual working of lifetimes:
但是,当您具有跨多个语句的引用时,就会出现问题.在那种情况下,编译器要求生命周期是包含两个语句的最里面的表达式(通常是一个块),并且通常比实际需要或期望的要大得多
Problems arise however when you have a reference that spans multiple statements. In that case, the compiler requires the lifetime to be the innermost expression (which is often a block) that encloses both statements, and that is typically much bigger than is really necessary or desired
rustc每晚1.28
@pnkfelix指出从每晚1.28开始不再编译以上代码.
As pointed out by @pnkfelix, the non-lexical lifetimes implementation starting from nightly 1.28 no longer compiles the above code.
但是,有(重新)-启用更强大的NLL分析.
这篇关于循环中的可变借位的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!