fifr
fifr

Reputation: 148

Restrict lifetime parameter to scope of parameters of a function

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

Answers (1)

oli_obk
oli_obk

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

Related Questions