Rust结构可以两次借用"&"一个mut self,所以为什么不能有特质呢?

emk*_*emk 22 iterator lifetime rust

以下Rust代码成功编译:

struct StructNothing;

impl<'a> StructNothing {
    fn nothing(&'a mut self) -> () {}

    fn twice_nothing(&'a mut self) -> () {
        self.nothing();
        self.nothing();
    }
}
Run Code Online (Sandbox Code Playgroud)

但是,如果我们尝试将其打包成特征,则会失败:

pub trait TraitNothing<'a> {
    fn nothing(&'a mut self) -> () {}

    fn twice_nothing(&'a mut self) -> () {
        self.nothing();
        self.nothing();
    }
}
Run Code Online (Sandbox Code Playgroud)

这给了我们:

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
Run Code Online (Sandbox Code Playgroud)

两个问题:

  • 为什么允许使用第一个版本,但禁止使用第二个版本?
  • 有没有办法说服编译器第二个版本没问题?

背景和动机

图书馆喜欢rust-csv支持流式传输,零拷贝解析,因为它比分配内存快25到50倍(根据基准测试).但Rust的内置Iterator特性不能用于此,因为没有办法实现collect().目标是定义一个StreamingIterator可以由rust-csv几个类似的库共享的特征.但到目前为止,每次实施它的尝试都遇到了上述问题.

小智 -4

这真的令人惊讶吗?

您所做的断言&mut self至少会持续一生'a

在前一种情况下,&mut self是指向结构的指针。不会发生指针别名,因为借用完全包含在 中nothing()

在后一种情况下,&mut self是一个指向该特征的结构体+虚函数表的指针。TraitNothing您正在锁定在 ;持续时间内实现的指向结构'a。即每次的整个功能。

通过删除'a,您隐式地使用了'static,这表示 impl 会永远持续下去,所以它没问题。

如果您想解决它,请将其转换&'a TraitNothing&'static TraitNothing...但我很确定这不是您想要做的。

这就是为什么我们'b: { .... }在 Rust 中需要块作用域 ()...

也许尝试使用虚拟生命周期?

  • Trait 声明中的 `&amp;mut self` 不是一个 Trait 对象;它只是一个简单的指针,指向实现该特征的任何值。(即使它是一个“&amp;mut TraitNothing”特征对象,它也只是一个指向结构体的指针+一个指向虚函数表的指针,没有额外的间接层。) (3认同)