【发布时间】:2017-05-23 09:35:53
【问题描述】:
如何在不复制数组或每次迭代多次调用 b() 的情况下编译此示例 - b() 必须执行一些昂贵的解析?
这不是我编写的完整代码,但它说明了我遇到的问题。在这里,Test 正在尝试执行某种流解析工作。 c()是解析函数,解析成功时返回Some。 b() 是一个函数,当c() 无法使用可用数据进行解析时,它会尝试从流中读取更多数据。返回的值是self.v 中包含已解析范围的切片。
struct Test {
v: [u8; 10],
index: u8,
}
impl Test {
fn b(&mut self) {
self.index = 1
}
fn c(i: &[u8]) -> Option<&[u8]> {
Some(i)
}
fn a(&mut self) -> &[u8] {
loop {
self.b();
match Test::c(&self.v) {
Some(r) => return r,
_ => continue,
}
}
}
}
fn main() {
let mut q = Test {
v: [0; 10],
index: 0,
};
q.a();
}
编译时,会产生以下借用检查错误:
error[E0502]: cannot borrow `*self` as mutable because `self.v` is also
borrowed as immutable
--> <anon>:17:13
|
17 | self.b();
| ^^^^ mutable borrow occurs here
18 |
19 | match Test::c(&self.v) {
| ------ immutable borrow occurs here
...
24 | }
| - immutable borrow ends here
如果我将a() 更改为:
fn a(&mut self) -> Option<&[u8]> {
loop {
self.b();
if let None = Test::c(&self.v) {
continue
}
if let Some(r) = Test::c(&self.v) {
return Some(r);
} else {
unreachable!();
}
}
}
然后它运行,但有一个明显的缺点是调用解析函数c() 两次。
我有点理解在返回值取决于它时更改 self 是不安全的,但是,我不明白为什么 self.v 的不可变借用在下一次迭代中仍然存在,当我们尝试调用时再次b()。
【问题讨论】:
-
对我来说看起来像是一个编译器错误。我认为第二个版本也不应该编译(事实上,如果你删除 else 分支,它不会编译)
-
@PaoloFalabella,这不是错误。编译器可以推断,当
self.v的第二次借用处于活动状态时,不会调用self.b(),因为在使用此借用后循环无条件结束。如果你删除 else 分支,那么它就不再是真的了。 -
@red75prim 啊,你是对的,谢谢!
标签: rust borrow-checker