代码之家  ›  专栏  ›  技术社区  ›  Ukonn Ra

如何将async fn放入Rust中的映射?

  •  1
  • Ukonn Ra  · 技术社区  · 6 年前

    hyper .

    use std::collections::HashMap;
    use std::future::Future;
    
    type BoxedResult<T> = Result<T, Box<dyn std::error::Error + Send + Sync>>;
    type CalcFn = Box<dyn Fn(i32, i32) -> dyn Future<Output = BoxedResult<i32>>>;
    
    async fn add(a: i32, b: i32) -> BoxedResult<i32> {
        Ok(a + b)
    }
    
    async fn sub(a: i32, b: i32) -> BoxedResult<i32> {
        Ok(a - b)
    }
    
    fn main() {
        let mut map: HashMap<&str, CalcFn> = Default::default();
        map.insert("add", Box::new(add));
        map.insert("sub", Box::new(sub));
    
        println!("map size: {}", map.len());
    }
    

    生成以下编译器错误:

    error[E0271]: type mismatch resolving `<fn(i32, i32) -> impl std::future::Future {add} as std::ops::FnOnce<(i32, i32)>>::Output == dyn std::future::Future<Output = std::result::Result<i32, std::boxed::Box<dyn std::error::Error + std::marker::Send + std::marker::Sync>>>`
      --> src/main.rs:17:23
       |
    17 |     map.insert("add", Box::new(add));
       |                       ^^^^^^^^^^^^^ expected opaque type, found trait std::future::Future
       |
       = note: expected type `impl std::future::Future`
                  found type `dyn std::future::Future<Output = std::result::Result<i32, std::boxed::Box<dyn std::error::Error + std::marker::Send + std::marker::Sync>>>`
       = note: required for the cast to the object type `dyn std::ops::Fn(i32, i32) -> dyn std::future::Future<Output = std::result::Result<i32, std::boxed::Box<dyn std::error::Error + std::marker::Send + std::marker::Sync>>>`
    
    error[E0271]: type mismatch resolving `<fn(i32, i32) -> impl std::future::Future {sub} as std::ops::FnOnce<(i32, i32)>>::Output == dyn std::future::Future<Output = std::result::Result<i32, std::boxed::Box<dyn std::error::Error + std::marker::Send + std::marker::Sync>>>`
      --> src/main.rs:18:23
       |
    18 |     map.insert("sub", Box::new(sub));
       |                       ^^^^^^^^^^^^^ expected opaque type, found trait std::future::Future
       |
       = note: expected type `impl std::future::Future`
                  found type `dyn std::future::Future<Output = std::result::Result<i32, std::boxed::Box<dyn std::error::Error + std::marker::Send + std::marker::Sync>>>`
       = note: required for the cast to the object type `dyn std::ops::Fn(i32, i32) -> dyn std::future::Future<Output = std::result::Result<i32, std::boxed::Box<dyn std::error::Error + std::marker::Send + std::marker::Sync>>>`
    

    似乎两者之间有冲突 impl Future dyn Future 但我不知道怎么处理。

    0 回复  |  直到 6 年前
        1
  •  5
  •   Ömer Erden Eugen Dück    6 年前

    这是因为 impl Future 是一个具体的独特类型 dyn Future 是一种抽象类型。 HashMap 应为抽象类型,因为它只能包含单个类型的实例。

    如果我们可以将异步函数的返回类型装箱,我们将能够将这些未来添加到 .

    CalcFn

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

    这样就可以做到:

    let mut map: HashMap<&str, CalcFn> = Default::default();
    map.insert("add", Box::new(|a, b| Box::pin(add(a, b))));
    map.insert("sub", Box::new(|a, b| Box::pin(sub(a, b))));
    
    println!("map size: {}", map.len());
    
    //map.get("add").unwrap()(2, 3).await
    

    这个 complete example 简化 Future Item 类型,使用 i32 而不是 Result . 请同时检查 full code for your case .

    推荐文章