Consider this struct:
struct Getter<T>(PhantomData<T>);
impl<T> Getter<T> {
fn get_thing<'a>(&'a mut self) -> Thing<'a> {
panic!();
}
}
This mimics an API that returns something, that has a borrow. For example, a deserializer returning structs that borrow data from an internal buffer.
Please ignore T
for now, it's going to become relevant in a moment. 'a
is not necessary here (can be elided), but I decided to add it for clarity.
Here's the Thing
that Getter
returns:
struct Thing<'a>(&'a ());
Thing
implements a trait, Trait
. This will become relevant in a moment:
trait Trait<'a> {}
impl<'a> Trait<'a> for Thing<'a> {}
Here's an example program that uses Getter
in a loop:
fn main() {
let mut getter = Getter::<Thing>(PhantomData);
loop {
let _thing = getter.get_thing();
}
}
This compiles just fine. _thing
borrows getter
, but _thing
is obviously dropped at the end of the loop iteration, so this borrow doesn't interfere with the next call to get_thing
.
There's a single change that will make this program break: Instead of returning Thing
from get_thing
, return a generic type that implements Trait
.
struct Getter<T>(PhantomData<T>);
impl<T> Getter<T> {
fn get_thing<'a>(&'a mut self) -> T where T: Trait<'a> { // return type in this line changed
panic!();
}
}
Now the example program no longer compiles:
error[E0499]: cannot borrow `getter` as mutable more than once at a time
--> src/main.rs:8:22
|
8 | let _thing = getter.get_thing();
| ^^^^^^ mutable borrow starts here in previous iteration of loop
I don't understand why it's not working. In my mind, literally nothing has changed from before:
-
_thing
is still dropped at the end of the loop iteration, so it shouldn't interfere with the call in the next one. - Nothing about the lifetime is new.
Thing
already implementedTrait
, andTrait
's lifetime was already tied to the lifetime ofThing
. - The compiler even knows that
T
isThing
!
I'm wondering if I'm missing something, and if there's some way to get this to compile. I can't seem to find a way.