HRTB for multiple bounds

Is there a way to do something like this?

trait T1 {}
trait T2 {}
struct S1<'a>(&'a u32); // any type with a lifetime

impl<A, B> T1 for B where 
    for <'a> A: 'a + T2, B: Fn(S1<'a>) -> A {}

Basically, both U and T need to be bound somehow by the lifetime 'a, but the for<'a> can only apply to one of the two bounds.

EDIT: fixed code

You could make a trait for it,

trait Check<'a, A, B> {}

impl<'a, A: 'a + T2, B: Fn(S1<'a>) -> A> Check<'a, A, B> for A {}

impl<A, B> T1 for B where 
    for<'a> A: Check<'a, A, B> {}
1 Like

Sorry I didn't make this very clear, but the implementation of T1 actually depends on B being Fn(S1<'a>) -> A where A shares a lifetime with the parameter. That is, I need to call B as a closure in the implementation, which means the bounds on B have to be in the header of the impl block.

A not pretty hack. (Unsure of practicality.) If I understand correctly you need the the first generic to be higher-kind rather than of concrete lifetime.

trait T1<H> {}
trait T2 {}
struct S1<'a>(&'a u32); // any type with a lifetime

trait Lo<'a> {
    type A: 'a + T2;
}
trait Hi: for<'a> Lo<'a> {}

impl<H, B> T1<H> for B where
    H: Hi,
    B: for<'a> Fn(S1<'a>) -> <H as Lo<'a>>::A  {}

Unfortunately, I need to export a trait T1 that doesn't take a type parameter.

Here's the full situation. Tide has this middleware trait defined as such:

pub trait Middleware<State>: 'static + Send + Sync {
    /// Asynchronously handle the request, and return a response.
    fn handle<'a>(
        &'a self,
        cx: Context<State>,
        next: Next<'a, State>,
    ) -> BoxFuture<'a, Response>;
}

Tide currently implements Middleware on all functions Fn(Context<State>, Next<'a, State>) -> BoxFuture<'a, Response>, but I'm trying to implement it for Fn(Context<State>, Next<'a, State>) -> impl Future<Response> + 'a (async functions), and now I'm beginning to see why they didn't.

Thanks for your help anyways; I should've known that they put enough thought into it to realize it was impossible.

So like this would work?

trait T1 {}
trait T2 {}
struct S1<'a>(&'a u32); // any type with a lifetime

trait Lo<'a> {
    type A: 'a + T2;
}

impl<B> T1 for B where
    B: for<'a> Lo<'a> + Fn(S1<'a>) -> <B as Lo<'a>>::A  {}

Trying to implement Lo<'a> for all B creates an odd compiler error.

trait T1 {}
trait T2 {}
struct S1<'a>(&'a u32); // any type with a lifetime

trait Lo<'a> {
    type A: 'a + T2;
}

impl<'a, B, F> Lo<'a> for B where B: Fn(S1<'a>) -> F, F: 'a + T2 {
    type A = F;
}

impl<B> T1 for B where for<'a> B: Lo<'a> + Fn(S1<'a>) -> <B as Lo<'a>>::A  {}
error[E0275]: overflow evaluating the requirement `B: Lo<'_>`
  --> src/main.rs:17:9
   |
17 | impl<B> T1 for B where for<'a> B: Lo<'a> + Fn(S1<'a>) -> <B as Lo<'a>>::A  {}
   |         ^^
   |
   = help: consider adding a `#![recursion_limit="256"]` attribute to your crate
   = note: required because of the requirements on the impl of `Lo<'_>` for `B`
   ... same thing over and over again
   = note: required because of the requirements on the impl of `T1` for `B`

This topic was automatically closed 90 days after the last reply. New replies are no longer allowed.