rustrust-async-std

how to store Futures from 2 different async functions with equal signatures in vector


how to store Futures from 2 different async functions with equal signatures in vector?

i have 2 functions in different crates:

crate 1:

pub async fn resolve(
    client: &String,
    site: &String,
    id: &String,
) -> Result<String, Box<dyn std::error::Error>> {
    ...
    return Ok("".parse().unwrap());
}

crate 2:

pub async fn resolve(
    client: &String,
    site: &String,
    id: &String,
) -> Result<String, Box<dyn std::error::Error>> {
    ...
    return Ok("".parse().unwrap());
}

and i tried to aggregate results of functions calls like so:

let mut futures : Vec<_> = Vec::new();
for i in 0..self.settings.count {
    futures.push(
        crate1::resolve(
            &self.settings.filed1,
            &self.settings.filed2,
            &product.id,
        )
    );

    futures.push(
        crate2::resolve(
            &self.settings.filed1,
            &self.settings.filed2,
            &product.id,
        )
    );
}

but i got this:

error[E0308]: mismatched types
   --> src\client.rs:124:17
    |
124 | /                 crate2::resolve(
125 | |                     &self.settings.filed1,
126 | |                     &self.settings.filed2,
127 | |                     &product.id,
128 | |                 )
    | |_________________^ expected opaque type, found a different opaque type
    |
note: while checking the return type of the `async fn`
   --> src\crate1.rs:97:6
    |
97  | ) -> Result<String, Box<dyn std::error::Error>> {
    |      ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ checked the `Output` of this `async fn`, expected opaque type
note: while checking the return type of the `async fn`
   --> src\crate2.rs:17:6
    |
17  | ) -> Result<String, Box<dyn std::error::Error>> {
    |      ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ checked the `Output` of this `async fn`, found opaque type
    = note: expected opaque type `impl futures::Future` (opaque type at <src\crate1.rs:97:6>)
               found opaque type `impl futures::Future` (opaque type at <src\crate2.rs:17:6>)
    = help: consider `await`ing on both `Future`s
    = note: distinct uses of `impl Trait` result in different opaque types

why rust can't deduce type?


Solution

  • Rust can deduce the type, it just considers any 2 uses of impl Future (which is what async fn desugars to) to be different types.

    To illustrate, consider the following functions:

    async fn f1() {
      println!("f1");
    }
    
    async fn f2() {
      let a: Foo = another_future().await;
      let b: Bar = anoter_future_2().await;
    
      println!("f2: {} {}", a, b);
    }
    

    Rust will (very roughly speaking) rewrite these as state machines:

    enum f1_StateMachine {
      Done  // only one state because no await points
    }
    
    enum f2_StateMachine {
      AfterFirstAwait(a: Foo),
      AfterSecondFuture(b: Bar),
      Done,
    }
    
    impl Future for f1_StateMachine { ... }
    impl Future for f2_StateMachine { ... }
    

    These are clearly not the same type, so can't be used inside a Vec together. As with any time you want to have a Vec contain multiple different types that all implement the same trait, you can use a trait object, and put the futures in a Box.

    Note, boxed futures can be a little tricky, this SO answer might be helpful reading: How can one await a result of a boxed future?