这是一个简短的示例,不能编译。错误发生在add1
函数中。如果我在add2
中这样做,它会起作用,但这不是很干。有经验的人可以告诉我如何以比add2
更好的方式克服可变借用不止一次的错误。
struct S1 {
full: bool,
v: Vec<u32>,
}
struct S2 {
v: Vec<S1>,
}
impl S2 {
// If last is not full push n to last.v, otherwise push a new S1
// Doesn't work
fn add1(&mut self, n: u32) {
// Let's assume it's not empty
let s1 = self.v.last_mut().unwrap();
if !s1.full {
s1.v.push(n);
} else {
self.v.push(S1 {
full: false,
v: vec![n],
});
}
}
// Works
fn add2(&mut self, n: u32) {
// First getting last as immutable ref and then as mutable ref
let full = self.v.last().unwrap().full;
if !full {
self.v.last_mut().unwrap().v.push(n);
} else {
self.v.push(S1 {
full: false,
v: vec![n],
});
}
}
}
fn main() {}
编译错误:
error[E0499]: cannot borrow `self.v` as mutable more than once at a time
--> src/main.rs:20:13
|
16 | let s1 = self.v.last_mut().unwrap();
| ------ first mutable borrow occurs here
...
20 | self.v.push(S1 {
| ^^^^^^ second mutable borrow occurs here
...
25 | }
| - first borrow ends here
答案 0 :(得分:3)
您有两种选择。
1)每晚使用并将#![feature(nll)]
放在文件的顶部。
非词汇生命周期正好解决了这个问题:即使{else}块中没有使用s1
借用,它仍然存活并阻止self.v
的变异。对于非词汇生命周期,编译器会认识到s1
实际上已经死了,让你再次借用。
2)像这样构建你的代码:
fn add1(&mut self, n: u32) {
{ // add a scope around s1 so that it disappears later
let s1 = self.v.last_mut().unwrap();
if !s1.full {
s1.v.push(n);
return; // just return early instead of using else
}
}
self.v.push(S1 {
full: false,
v: vec![n]
});
}
答案 1 :(得分:0)
您可以限制重复:
fn add1(&mut self, n: u32) {
// Let's assume it's not empty
if {
let s1 = self.v.last_mut().unwrap();
if !s1.full {
s1.v.push(n);
}
s1.full
} {
self.v.push(S1 {
full: false,
v: vec![n],
});
}
}