I'm using a library that has the following interface (code snippets simplified to relevant details):
use std::marker::PhantomData;
struct SomeLib<T>(PhantomData<T>);
impl<T> SomeLib<T> {
fn foo(&mut self, t: &mut T) { }
}
Note that the library struct does not need a value of type T to be created.
At first I was using it with a struct that only contained data as the generic parameter and everything went well. The code looked roughly like this: (1)
struct MyStruct1;
fn baz1() {
let mut lib = SomeLib(PhantomData);
let mut my1 = MyStruct1;
lib.foo(&mut my1);
}
As I was fleshing out the code a bit I realised my struct needed to contain a reference to some data. After adding a field for the reference and a lifetime parameter to the struct I had the following code: (2)
struct MyStruct2<'a>(&'a mut u8);
fn baz2() {
let mut lib = SomeLib(PhantomData);
let mut data = 0;
let mut my2 = MyStruct2(&mut data);
lib.foo(&mut my2);
}
However (2) fails to compile with a message claiming that data
does not live long enough:
main.rs:23:33: 23:37 error: `data` does not live long enough
main.rs:23 let mut my2 = MyStruct2(&mut data);
^~~~
main.rs:21:39: 26:2 note: reference must be valid for the block suffix following statement 0 at 21:38...
main.rs:21 let mut lib = SomeLib(PhantomData);
main.rs:22 let mut data = 0;
main.rs:23 let mut my2 = MyStruct2(&mut data);
main.rs:24
main.rs:25 lib.foo(&mut my2);
main.rs:26 }
main.rs:22:21: 26:2 note: ...but borrowed value is only valid for the block suffix following statement 1 at 22:20
main.rs:22 let mut data = 0;
main.rs:23 let mut my2 = MyStruct2(&mut data);
main.rs:24
main.rs:25 lib.foo(&mut my2);
main.rs:26 }
I need some help to understand why (2) fails.
In (1) foo
is called with a reference to a value that lives longer than the function call but shorter than lib
, and it works fine.
But in (2) where both my2
and data
lives longer than the call to foo
and shorter than lib
it does not work.
Moving the binding of data
to before lib
makes the example code compile, but it would be rather awkward to do this in the real code.
Why doesn't the code in (2) work? Is there some way to change MyStruct2
so that it can contain a reference to data shorter lived than the library struct but still be passed to foo
?