【发布时间】:2014-11-29 07:34:44
【问题描述】:
以下 Rust 代码compiles successfully:
struct StructNothing;
impl<'a> StructNothing {
fn nothing(&'a mut self) -> () {}
fn twice_nothing(&'a mut self) -> () {
self.nothing();
self.nothing();
}
}
但是,如果我们尝试将其打包到 trait 中,it fails:
pub trait TraitNothing<'a> {
fn nothing(&'a mut self) -> () {}
fn twice_nothing(&'a mut self) -> () {
self.nothing();
self.nothing();
}
}
这给了我们:
error[E0499]: cannot borrow `*self` as mutable more than once at a time
--> src/lib.rs:6:9
|
1 | pub trait TraitNothing<'a> {
| -- lifetime `'a` defined here
...
5 | self.nothing();
| --------------
| |
| first mutable borrow occurs here
| argument requires that `*self` is borrowed for `'a`
6 | self.nothing();
| ^^^^ second mutable borrow occurs here
- 为什么允许第一个版本,而禁止第二个版本?
- 有什么方法可以让编译器相信第二个版本没问题?
背景和动机
像rust-csv 这样的库希望支持流式、零拷贝解析,因为它比分配内存快 25 到 50 倍(根据基准测试)。 But Rust's built-in Iterator trait can't be used for this,因为没有办法实现collect()。目标是定义一个StreamingIterator trait,它可以由rust-csv 和几个类似的库共享,但到目前为止,每次尝试实现它都遇到了上述问题。
【问题讨论】:
-
将
fn nothing(&'a mut self)更改为fn nothing(&mut self)可解决此问题。鉴于你的函数什么都不返回,你真的需要这个生命周期说明符吗?然而,它看起来确实像一个错误。 -
Levans:是的,如果没有生命周期说明符,设计的其余部分就会分崩离析。但是,如果我们能让生命周期说明符起作用,我们就可以构建一个非常好的
StreamingIterator库。这只是让我们摸不着头脑的最小例子。 -
我相信这可以通过诸如 HRL(更高等级的生命周期)之类的东西来解决,您可以在其中拥有(假设语法)
trait StreamingIterator<T<'*>> { fn next<'a>(&'a mut self) -> T<'a>; }。不过,我们现在还没有能力准确地表达这一点。 -
(It was pointed out 我误用了术语:上面应该说“HKL(更高种类的生命周期)”。)