我有一些无法编译的代码,我不明白为什么。下面是一个简化的、人为的版本:
struct Thing<'a> {
slice: &'a [u8],
}
struct ThingGetter {
buffer: [u8; 10],
index: usize,
}
impl ThingGetter {
pub fn next_thing(&mut self) -> Option<Thing> {
self.index += 1;
if self.index == 42 {
return None;
} else {
let thing = Thing {
slice: &self.buffer[..],
};
return Some(thing);
}
}
}
struct Wrapper {
getter: ThingGetter,
}
impl Wrapper {
pub fn get_thing(&mut self) -> Option<Thing> {
loop {
if let Some(thing) = self.getter.next_thing() {
return Some(thing);
} else {
continue;
}
}
}
}
其失败原因为:
error[E0499]: cannot borrow `self.getter` as mutable more than once at a time
--> src/thing.rs:31:34
|
29 | pub fn get_thing(&mut self) -> Option<Thing> {
| - let's call the lifetime of this reference `'1`
30 | loop {
31 | if let Some(thing) = self.getter.next_thing() {
| ^^^^^^^^^^^^^^^^^^^^^^^^ `self.getter` was mutably borrowed here in the previous iteration of the loop
32 | return Some(thing);
| ----------- returning this value requires that `self.getter` is borrowed for `'1`
我已经费力地研究了大量关于多个可变借用和生命周期的Stack Overflow答案,但我就是没有看到答案。
如果将continue;
行更改为return None;
,则编译正常。
我知道thing
依赖于getter
,getter
是可变借用的。我不明白的是为什么这段代码认为getter
被借用了两次,一次是在上一次迭代中。一旦再次调用if let Some(thing) = ...
,上一次迭代中的借用就不再可访问了。
或者这可能是一个终身问题?我不能告诉从编译器消息。
Here's a link to the playground.
1条答案
按热度按时间wwtsj6pe1#
我很确定你遇到了最大的已知假阳性,目前的借用检查。
新的实验性借位检查器
polonius
成功地确认了代码的有效性,尽管它还不稳定。有很多类似的例子,但都归结为here所描述的问题。
在大多数情况下,可以解决这个问题。然而,在少数情况下,如果没有
unsafe
代码,就不可能正确解决这个问题。幸运的是,polonius-the-crab
crate为这个小unsafe
代码提供了一个良好的封装。在它的帮助下,你的问题可以像这样解决: