rust - 借款检查器抱怨多次借款,而只有一次借款会发生
问题描述
考虑以下代码(也可在操场上找到)
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
特征的工作方式类似于迭代器,只是&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 行返回,要么在第 18 行返回,所以两者中只有一个会发生。我的假设是这也不是一个真正的问题,但其中一种情况是借用检查器不够聪明。我错过了什么吗?
假设我是对的,我设法unsafe
通过人为地“打破”生命周期依赖性来使用一个块(参见注释掉的第 16 行)来规避这个错误。任何人都可以看到更好的方法(即没有任何unsafe
块)来编译这段代码吗?
解决方案
根据The Polonius Talk,rustc 目前将函数签名中的生命周期视为整个函数体中的生命周期。因此,如果我理解正确,那么 rustc 借用不同的匹配武器并不重要。
代码类型检查cargo +nightly rustc -- -Zpolonius
意味着当 Polonius 功能完全集成时,代码应该在没有任何更改的情况下进行类型检查。
我找不到比unsafe
在有问题的示例中使用 like 并添加评论说unsafe
可以在某些时候删除更好的解决方法。
推荐阅读
- python - 如何在 python 字典中复制表?(或任何其他数据结构)
- ms-access - 我们如何重新进行查询以从 Price.Present 中删除 [Goods].Remnant 中不存在的估值器?
- google-sheets - =QUERY 获取列名并在 Google 表格中给出列范围?
- google-sheets - 在谷歌表格中创建多级 WBS 级别列表?任务 1.1,子任务 1.1.1 与 arrayFormula
- mysql - UnhandledPromiseRejectionWarning 与 nodejs 和 mysql 请让我知道是什么问题
- c++ - 如何更改代码以避免运行时错误(AddressSanitizer)?
- c# - 在没有 UAC 的情况下使用管理员权限从 C# 运行 PsExec
- sql - SQL-获取列中的字符长度问题,但无法使用变量重现
- arrays - 获取数据库中的单列数组并在 laravel Blade 中显示
- qemu - 如何将每个受支持的 CPU 标志作为 QEMU CPU 标志?