trait Example {
    type HasLifetime<'a>;

    fn example<F>()
    where
        F: for<'a> FnOnce(Self::HasLifetime<'a>) -> Box<dyn 'a + Send>;
}

Produces:

error[E0582]: binding for associated type `Output` references lifetime `'a`, which does not appear in the trait input types
 --> src/lib.rs:6:53
  |
6 |         F: for<'a> FnOnce(Self::HasLifetime<'a>) -> Box<dyn 'a + Send>;
  |                                                     ^^^^^^^^^^^^^^^^^^

I'm a bit confused how the lifetime "does not appear in the input types" as it quite clearly does. The following changes allow the code to compile:

  • Changing the closure argument type to &'a Self::HasLifetime<'a>.
  • Changing the closure argument type to Foo<'a> given the existence of a struct Foo<'a>.

Why is the lifetime GAT case rejected, given that it also takes the lifetime parameter as an input?

1

There are 1 best solutions below

6
On

Take for example the following implementation:

impl Example for Something {
    type HasLifetime<'a> = ();

    // ...
}

In which example() normalizes too:

fn example<F>()
where
    F: for<'a> FnOnce(()) -> Box<dyn 'a + Send>;

Closures (and traits with associated types in general) when an associated type references some lifetime not in the trait's generic parameters or the implementing type, are rejected for soundness reasons. So this cannot work.

If you change it to &'a Self::HasLifetime<'a> or Foo<'a>, the parameter always references the lifetime (even if the associated type doesn't), so this works again.