Higher-ranked lifetime in associated types

Why does this code not work?

trait Wrappers {
    type Wrapper<'a>
    where
        Self: 'a;
}

fn foo<W1, W2, F>(f: F)
where
    W1: Wrappers,
    W2: Wrappers,
    F: for<'a> Fn(W1::Wrapper<'a>) -> W2::Wrapper<'a>,
{
}

playground

The error message is:

error[E0582]: binding for associated type `Output` references lifetime `'a`, which does not appear in the trait input types
  --> src/lib.rs:11:39
   |
11 |     F: for<'a> Fn(W1::Wrapper<'a>) -> W2::Wrapper<'a>,
   |                                       ^^^^^^^^^^^^^^^

For more information about this error, try `rustc --explain E0582`.

this is a tricky one, I sort of understand the reason, but I don't know how to fix. the problem comes from the Fn() sugar syntax. if you know the desugared syntax, you'll probably get an rough idea.

the sugar syntax Fn(A1, A2) -> Ret can be desugared to Fn<(A1, A2), Output = Ret>, note the return type is an associated type instead of generic parameter. that's the what the compile error message means. but I don't know how to express your idea in rust.

1 Like

Crazy. this works: F: for<'a> Fn(&'a (), W1::Wrapper<'a>) -> W2::Wrapper<'a>.

1 Like

is this acceptable? I use a custom trait instead of the Fn trait:

trait Map<From, To> {
    fn map(&self, from: From) -> To; 
}
impl<From, To, F> Map<From, To> for F where F: Fn(From) -> To {
    fn map(&self, from: From) -> To {
        self(from)
    }
}

fn foo<W1, W2, F>(f: F)
where
    W1: Wrappers,
    W2: Wrappers,
    F: for<'a> Map<W1::Wrapper<'a>, W2::Wrapper<'a>>,
{
}

Is this a bug of the compiler?:thinking:

It's either a limitation or necessary for soundness, I'm not entirely sure which.[1]


  1. See also. ↩ī¸Ž

1 Like