How to put async fn into vec?

this is PlayGround link Playground

use std::future::Future;
pub async fn handle(req: i32) -> i32 {
    req + 1
}

fn main() {
    let mut data: Vec<Box<fn(i32) -> dyn Future<Output=i32>>> = vec![];
    data.push(Box::new(handle));
}
   Compiling playground v0.0.1 (/playground)
error[E0308]: mismatched types
 --> src/main.rs:8:24
  |
8 |     data.push(Box::new(handle));
  |                        ^^^^^^ expected trait object `dyn Future`, found opaque type
  |
  = note: expected fn pointer `fn(_) -> dyn Future<Output = i32>`
                found fn item `fn(_) -> impl Future<Output = i32> {handle}`

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

See e.g. How to store async functions in a vector? - #2 by steffahn

Also: Type sig of `async fn (x: usize) -> u32`? - #2 by steffahn

3 Likes

Thank you so much for your recovery. It really helped me

Is the workaround with closures purely because impl Trait in positions other than fn args and fn return positions is unstable? Or is there more to it?

Assuming the question is about storing different async fn's in a Vec (and honestly, storing copies of the same function would be fairly nonsensical), something like an impl Trait opaque type won’t work, because different async fn return different future types. You need a trait object, and owned trait objects need to be boxed. The main reason why a closure is involved in all the code examples in my other answers then is mainly because you need to transform the async fn which is fn(…) -> SomeFutureType to fn(…) -> Box<dyn Future<…> +…>; these “adapter closures” introduce the additional boxing step (and also the unsize coercion) to create a boxed trait object.

3 Likes

Perhaps the compiler should give the appropriate solution, currently the compiler has no valuable information