How can I receive an async function as param and put the async function into a map in Rust?

I'm getting this error :

 |
13 | async fn get_add_future_from_map<F, T>(f: F) -> i32
   |                                  - help: consider adding an explicit lifetime bound...: `F: 'static`
...
18 |     map.insert("str_to_int", Box::new(|a: String| Box::pin(f(a))));
   |                              ^^^^^^^^ ...so that the reference type `&F` does not outlive the data it points at

this is the code :

/*
[dependencies]
futures-preview = "0.3.0-alpha.19"
*/
use futures::executor::block_on;
use std::collections::HashMap;
use std::future::Future;
use std::pin::Pin;

type CalcFn = Box<dyn Fn(String) -> Pin<Box<dyn Future<Output = i32>>>>;


async fn get_add_future_from_map<F, T>(f: F) -> i32
where F: Fn(String) -> T,
      T: Future<Output = i32> + Send + 'static,
{
    let mut map: HashMap<&str, CalcFn> = Default::default();
    map.insert("str_to_int", Box::new(|a: String| Box::pin(f(a))));

    println!("map size: {}", map.len());

    map.remove("str_to_int").unwrap()("2".to_string()).await
}

fn main() {
    let async_func = |s: String| {
        async {
            s.parse().unwrap()
        }
    };
    println!("Total : {:?}", block_on(get_add_future_from_map(async_func)));
}

Link to play.rust-lang

You can add the proposed F: 'static bound; then you need to ensure that a closure an an async block in your code capture by move instead of by reference (the latter would violate the 'static bound on either F or T), and then the code will work:

/*
[dependencies]
futures-preview = "0.3.0-alpha.19"
*/
use futures::executor::block_on;
use std::collections::HashMap;
use std::future::Future;
use std::pin::Pin;

type CalcFn = Box<dyn Fn(String) -> Pin<Box<dyn Future<Output = i32>>>>;


async fn get_add_future_from_map<F, T>(f: F) -> i32
- where F: Fn(String) -> T,
+ where F: Fn(String) -> T + 'static,
      T: Future<Output = i32> + Send + 'static,
{
    let mut map: HashMap<&str, CalcFn> = Default::default();
-   map.insert("str_to_int", Box::new(|a: String| Box::pin(f(a))));
+   map.insert("str_to_int", Box::new(move |a: String| Box::pin(f(a))));

    println!("map size: {}", map.len());

    map.remove("str_to_int").unwrap()("2".to_string()).await
}

fn main() {
    let async_func = |s: String| {
-       async {
+       async move {
            s.parse().unwrap()
        }
    };
    println!("Total : {:?}", block_on(get_add_future_from_map(async_func)));
}
1 Like

Wow.. thank you