借用检查器抱怨多次借用,而只有一次会发生
Borrow checker complains about multiple borrowing, when only one will ever occur
考虑以下代码(也available on the playground)
pub trait TextStream {
fn next_str(&mut self) -> Option<&str>;
}
pub struct FilterTextStream<T: TextStream> {
inner: T,
maxlen: usize,
}
impl<T: TextStream> TextStream for FilterTextStream<T> {
fn next_str(&mut self) -> Option<&str> {
match self.inner.next_str() {
None => None,
Some(txt) if txt.len() <= self.maxlen => {
Some(txt) // <-- this does not compile
//Some(unsafe {&*(txt as *const str)}) // <-- this fixes the problem
}
_ => self.next_str()
}
}
}
TextStream
trait 的工作方式类似于迭代器,除了它产生的 &str
没有重叠的生命周期。 FilterTextStream
就像一个(专门的)过滤器迭代器。
然而,此代码无法编译,出现以下错误:
error[E0499]: cannot borrow `*self` as mutable more than once at a time
--> src/main.rs:18:18
|
11 | fn next_str(&mut self) -> Option<&str> {
| - let's call the lifetime of this reference `'1`
12 | match self.inner.next_str() {
| ---------- first mutable borrow occurs here
...
15 | Some(txt)
| --------- returning this value requires that `self.inner` is borrowed for `'1`
...
18 | _ => self.next_str()
| ^^^^ second mutable borrow occurs here
令我吃惊的是,我不明白这是怎么借 self
两次的。要么我们在第 15 行 return,要么我们在第 18 行 return,所以只有两者之一会发生。我的假设是这不是 真正的 问题,但其中一个案例是借用检查器不够聪明。我错过了什么吗?
假设我是对的,我设法使用 unsafe
块(请参阅注释掉的第 16 行)通过人为地“打破”生命周期依赖性来避免此错误。谁能找到更好的方法(即没有任何 unsafe
块)来编译此代码?
根据 The Polonius Talk rustc 当前将函数签名中的生命周期视为它们在整个函数体中都是有效的。所以,如果我目前理解的话,rustc 认为借用在不同的火柴臂上并不重要。
代码类型检查 cargo +nightly rustc -- -Zpolonius
这意味着当 Polonius 功能完全集成时,代码应该进行类型检查而不做任何更改。
我找不到比在有问题的示例中使用 unsafe
并添加一条评论说 unsafe
可以在某些时候删除更好的解决方法。
考虑以下代码(也available on the playground)
pub trait TextStream {
fn next_str(&mut self) -> Option<&str>;
}
pub struct FilterTextStream<T: TextStream> {
inner: T,
maxlen: usize,
}
impl<T: TextStream> TextStream for FilterTextStream<T> {
fn next_str(&mut self) -> Option<&str> {
match self.inner.next_str() {
None => None,
Some(txt) if txt.len() <= self.maxlen => {
Some(txt) // <-- this does not compile
//Some(unsafe {&*(txt as *const str)}) // <-- this fixes the problem
}
_ => self.next_str()
}
}
}
TextStream
trait 的工作方式类似于迭代器,除了它产生的 &str
没有重叠的生命周期。 FilterTextStream
就像一个(专门的)过滤器迭代器。
然而,此代码无法编译,出现以下错误:
error[E0499]: cannot borrow `*self` as mutable more than once at a time
--> src/main.rs:18:18
|
11 | fn next_str(&mut self) -> Option<&str> {
| - let's call the lifetime of this reference `'1`
12 | match self.inner.next_str() {
| ---------- first mutable borrow occurs here
...
15 | Some(txt)
| --------- returning this value requires that `self.inner` is borrowed for `'1`
...
18 | _ => self.next_str()
| ^^^^ second mutable borrow occurs here
令我吃惊的是,我不明白这是怎么借 self
两次的。要么我们在第 15 行 return,要么我们在第 18 行 return,所以只有两者之一会发生。我的假设是这不是 真正的 问题,但其中一个案例是借用检查器不够聪明。我错过了什么吗?
假设我是对的,我设法使用 unsafe
块(请参阅注释掉的第 16 行)通过人为地“打破”生命周期依赖性来避免此错误。谁能找到更好的方法(即没有任何 unsafe
块)来编译此代码?
根据 The Polonius Talk rustc 当前将函数签名中的生命周期视为它们在整个函数体中都是有效的。所以,如果我目前理解的话,rustc 认为借用在不同的火柴臂上并不重要。
代码类型检查 cargo +nightly rustc -- -Zpolonius
这意味着当 Polonius 功能完全集成时,代码应该进行类型检查而不做任何更改。
我找不到比在有问题的示例中使用 unsafe
并添加一条评论说 unsafe
可以在某些时候删除更好的解决方法。