Async closure that takes a reference

I've been trying to declare a function that accepts an async closure with a borrowed argument.

Here is my current attempt: (playground)

use std::future::Future;

trait AsyncFn<'fut, T: 'fut> {
    type Future: Future + Send + 'fut;
    
    fn call(&'fut self, arg: T) -> Self::Future;
}

impl<'fut, F, T, Fut> AsyncFn<'fut, T> for F
where
    F: Fn(T) -> Fut,
    T: 'fut,
    Fut: Future + Send + 'fut,
{
    type Future = Fut;
    
    fn call(&'fut self, arg: T) -> Self::Future {
        self(arg)
    }
}

fn take_async_fn<F: for<'fut> AsyncFn<'fut, &'fut str>>(_f: F) {
    // ...
}

fn main() {
    take_async_fn(|s| async move {});
}

It fails with:

error[E0308]: mismatched types
  --> src/main.rs:27:5
   |
27 |     take_async_fn(|s| async move {});
   |     ^^^^^^^^^^^^^ one type is more general than the other
   |
   = note: expected type `FnOnce<(&'fut str,)>`
              found type `FnOnce<(&str,)>`

I believe this is similar to this more general workaround. However, neither solution seems to work for closures, and I'm not sure why; could be related to rust-lang/rust#22340.

Is there any way to do this in current Rust?

As I understand it, not with closures. You could manually implement AsyncFn on your own struct, and that'd likely work, but I don't think you can convince the compiler to have closures implement it properly.

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.