0

I'm trying to store a function in a struct:

trait T<'a> {}

struct A {}

struct B<'a> {
    a: &'a A
}

impl<'a> T<'a> for B<'a> {}

fn f1<'a, E: T<'a>>(a: &'a A) {}

struct D {
    f: fn(&A)
}

fn main() {
    let d = D { f: f1::<B> };
}

The compiler complains:

error[E0308]: mismatched types
  --> src/main.rs:18:20
   |
18 |     let d = D { f: f1::<B> };
   |                    ^^^^^^^ expected concrete lifetime, found bound lifetime parameter 
   |
   = note: expected type `fn(&A)`
   = note:    found type `fn(&A) {f1::<'_, B<'_>>}`
Shepmaster
  • 388,571
  • 95
  • 1,107
  • 1,366
Cheng-Chang Wu
  • 187
  • 1
  • 7

1 Answers1

3

When you write f1::<B>, the compiler interprets that as f1::<B<'_>>, there '_ is a lifetime inferred by the compiler, because B is generic over a lifetime and you can only pass concrete types as type parameters.

But then, in D, the f field is expected to be a function that accepts references to A with any lifetime. f1::<B> does not fulfill that requirement, because the function has been instantiated with a specific lifetime.

Unfortunately, at the moment, there's no way to make this work. Rust would have to support either higher kinded types or associated type constructors. You could then define E in f1 to be a type constructor parameter, rather than a type parameter (though I'm wondering how the compiler would handle the 'a lifetime parameter).

Francis Gagné
  • 60,274
  • 7
  • 180
  • 155
  • I think you're right, but it didn't stop me from trying to use `for<'a> ...` in a few ways to get around it. :-) – Chris Emerson Dec 11 '16 at 19:31
  • I've read something about for<'a>, but found no way to get around it. May I know how do you do it? – Cheng-Chang Wu Dec 11 '16 at 22:49
  • @Cheng-ChangWu: What Chris was saying is that he tried using `for<'a>...` to solve your problem, but unfortunately it doesn't work here. For the record, in `D`, `f: fn(&A)` is a shorthand for `f: for<'a> fn(&'a A)`. – Francis Gagné Dec 12 '16 at 00:42