Reputation: 148
Consider the following example
trait MyTrait<'a> {
type N: 'a;
fn func(&'a self) -> Self::N;
}
fn myfunc<'a, T: 'a + MyTrait<'a>>(g: T) {
g.func();
}
fn main() {}
Compiling this small program fails with:
error[E0597]: `g` does not live long enough
--> src/main.rs:8:5
|
8 | g.func();
| ^ borrowed value does not live long enough
9 | }
| - borrowed value only lives until here
|
note: borrowed value must be valid for the lifetime 'a as defined on the function body at 7:1...
--> src/main.rs:7:1
|
7 | fn myfunc<'a, T: 'a + MyTrait<'a>>(g: T) {
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
As far as I understand, the lifetime parameter 'a
is not restricted and could be arbitrary. However, g
is a parameter and its lifetime is only the function scope, therefore it does not satisfy the condition of lifetime 'a
in the definition of method func
.
What I really want is that the associated type N
is always restricted to the lifetime of self
in MyTrait
. That's why I came up with the explicit lifetime parameter 'a
of MyTrait
. I want function myfunc
to work, i.e. 'a
should somehow be restricted to the lifetime of of the parameter g
.
What is the "correct" way to solve this problem?
A very simple example is
struct MyPtr<'a> {
x: &'a usize,
}
struct MyStruct {
data: Vec<usize>,
}
impl<'a> MyTrait<'a> for MyStruct {
type N = MyPtr<'a>;
fn func(&'a self) -> Self::N {
MyPtr { x: &self.data[0] }
}
}
Note that this is extremely simplified, of course. The idea is that N
always contains a reference to something contained in MyTrait
and should therefore never outlive MyTrait
.
Upvotes: 4
Views: 389
Reputation: 31173
What you want is not to bind a generic lifetime, but to allow "any" lifetime:
fn myfunc<T: for<'a> MyTrait<'a>>(g: T) {
g.func();
}
Fully working example in the playground.
The best source for an explanation is How does for<> syntax differ from a regular lifetime bound?.
Upvotes: 3