The following Rust code compiles successfully:
struct StructNothing;
impl<'a> StructNothing {
fn nothing(&'a mut self) -> () {}
fn twice_nothing(&'a mut self) -> () {
self.nothing();
self.nothing();
}
}
However, if we try to package it in a trait, it fails:
pub trait TraitNothing<'a> {
fn nothing(&'a mut self) -> () {}
fn twice_nothing(&'a mut self) -> () {
self.nothing();
self.nothing();
}
}
This gives us:
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
- Why is the first version allowed, but the second version forbidden?
- Is there any way to convince the compiler that the second version is OK?
Background and motivation
Libraries like rust-csv
would like to support streaming, zero-copy parsing because it's 25 to 50 times faster than allocating memory (according to benchmarks). But Rust's built-in Iterator
trait can't be used for this, because there's no way to implement collect()
. The goal is to define a StreamingIterator
trait which can be shared by rust-csv
and several similar libraries, but every attempt to implement it so far has run into the problem above.
fn nothing(&'a mut self)
tofn nothing(&mut self)
fixes the issue. Do you really need this lifetime specifier given your function returns nothing ? Yet, it does look like a bug. – ImpatiensStreamingIterator
library. This is just the minimal example that's left us scratching our heads. – Glomerationtrait StreamingIterator<T<'*>> { fn next<'a>(&'a mut self) -> T<'a>; }
. We don't have the ability to express exactly that now, though. – Hussein