以下Rust代码compiles successfully:
struct StructNothing;
impl<'a> StructNothing {
fn nothing(&'a mut self) -> () {}
fn twice_nothing(&'a mut self) -> () {
self.nothing();
self.nothing();
}
}
但是,如果我们尝试将其打包成特征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
特征,可以由rust-csv
和几个类似的库共享,但到目前为止,每次尝试实现它都会遇到上述问题。
答案 0 :(得分:2)
以下是使用隐式生命周期的弗朗西斯答案的扩展,但它允许返回值为终生限制:
pub trait TraitNothing<'a> {
fn change_it(&mut self);
fn nothing(&mut self) -> &Self {
self.change_it();
self
}
fn bounded_nothing(&'a mut self) -> &'a Self {
self.nothing()
}
fn twice_nothing(&'a mut self) -> &'a Self {
// uncomment to show old fail
// self.bounded_nothing();
// self.bounded_nothing()
self.nothing();
self.nothing()
}
}
它不完美,但您可以在其他方法中多次使用隐式生命周期change_it
和nothing
调用方法。我不知道这是否会解决您的真实问题,因为最终self
在特征方法中具有泛型类型&mut Self
,而在结构中它具有类型&mut StructNothing
并且编译器可以& #39; t保证Self
不包含引用。此解决方法确实解决了代码示例。
答案 1 :(得分:1)
如果您将生命周期参数放在每个方法而不是特征本身上,it compiles:
pub trait TraitNothing {
fn nothing<'a>(&'a mut self) -> () {}
fn twice_nothing<'a>(&'a mut self) -> () {
self.nothing();
self.nothing();
}
}
答案 2 :(得分:-2)
这真的令人惊讶吗?
您所做的断言是&mut self
至少持续一生'a
。
在前一种情况下,&mut self
是指向结构的指针。没有指针别名,因为借用完全包含在nothing()
。
在后一种情况下,&mut self
是一个指针到指针到结构+一个vtable的特征。您在TraitNothing
的持续时间内锁定了指向实现'a
的结构的结构;即每次都是整个功能。
删除'a
后,您隐式使用'static
,表示impl会永久存在,所以很好。
如果你想解决这个问题,请将&'a TraitNothing
转换为&'static TraitNothing
......但我很确定这不是你想要做的。
这就是我们在Rust ...
中需要块范围('b: { .... }
)的原因