Write HRTB for multiple where clauses linked together

Is there a way to use the for<'a> lifetime in both the where clauses below.
I know one way is boxing the future. Is there any other way?

(Doesn't compile)

    pub async fn add_requests<F, Fut>(&mut self, mut invoke: F) -> bool
    where
        for<'a> F: FnMut(&'a mut dyn Observer) -> Fut,
        Fut: Future<Output = bool> + 'a 
    { .. }

If I mark self as &'a mut self, the the code doesn't compile because the borrow becomes too large when it should be only for the duration of the call.

Basically what I want to write is impl Trait in closure:

(Doesn't compile)

    pub async fn add_requests<F>(&mut self, mut invoke: F) -> bool
    where
       for<'a> F: FnMut(&'a mut dyn Observer) -> impl Future<Output = bool> + 'a,
    { .. }

No, this is currently impossible. Initially, it appears that using a helper trait would work:

use std::future::Future;

trait MyFn<'a> {
    type Future: Future<Output = Self::Output> + 'a;
    type Output;
    fn call(&mut self, arg: &'a u32) -> Self::Future;
}

async fn takes_f<F>(mut f: F) -> i32
where
    F: for<'a> MyFn<'a, Output = i32>,
{
    let a = 10u32;
    let b = f.call(&a).await;
    b
}

and it even works when you add a blanket impl:

impl<'a, F, Fut> MyFn<'a> for F
where
    F: FnMut(&'a u32) -> Fut,
    Fut: Future + 'a,
{
    type Future = Fut;
    type Output = Fut::Output;
    fn call(&mut self, arg: &'a u32) -> Fut {
        self(arg)
    }
}

but when you try to call it:

#[tokio::main]
async fn main() {
    let b = takes_f(|i: &u32| async move { (*i) as i32 }).await;
    println!("{}", b);
}

it does not work:

error: implementation of `MyFn` is not general enough
  --> src/main.rs:32:13
   |
3  | / trait MyFn<'a> {
4  | |     type Future: Future<Output = Self::Output> + 'a;
5  | |     type Output;
6  | |     fn call(&mut self, arg: &'a u32) -> Self::Future;
7  | | }
   | |_- trait `MyFn` defined here
...
32 |       let b = takes_f(|i: &u32| async move { (*i) as i32 }).await;
   |               ^^^^^^^ implementation of `MyFn` is not general enough
   |
   = note: `MyFn<'1>` would have to be implemented for the type `[closure@src/main.rs:32:21: 32:57]`, for any lifetime `'1`...
   = note: ...but `MyFn<'_>` is actually implemented for the type `[closure@src/main.rs:32:21: 32:57]`, for some specific lifetime `'2`

The compiler is not able to see that the closure could satisfy the requirement. Note that it is possible to successfully implement the trait for your own structs, but not for closures.

This topic was automatically closed 90 days after the last reply. We invite you to open a new topic if you have further questions or comments.