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
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.
To accomplish this, Rust uses a borrowing mechanism. Instead of passing objects by value ( T ), objects can be passed by reference ( &T ). The compiler statically guarantees (via its borrow checker) that references always point to valid objects.
The borrow check is Rust's "secret sauce" – it is tasked with enforcing a number of properties: That all variables are initialized before they are used. That you can't move the same value twice. That you can't move a value while it is borrowed.
It is very inconvenient to pass the ownership of a variable to another function and then return the ownership. Rust supports a concept, borrowing, where the ownership of a value is transferred temporarily to an entity and then returned to the original owner entity.
A struct is a user-defined data type that contains fields which define its particular instance. Structs help programmers implement abstract ideas in a more understandable fashion. For example, creating a Student struct that consists of an id , name , marks , etc. makes the code more readable.
The following is an extension of Francis's answer using implicit lifetimes but it allows for the return value to be lifetime bound:
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() } }
It's less than perfect, but you can call the methods with implicit lifetimes change_it
and nothing
multiple times within other methods. I don't know if this will solve your real problem because ultimately self
has the generic type &mut Self
in the trait methods whereas in the struct it has type &mut StructNothing
and the compiler can't guarantee that Self
doesn't contain a reference. This workaround does solve the code example.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With