Home > Back-end >  Expected `async` block, found a different `async` block
Expected `async` block, found a different `async` block

Time:02-11

I was trying to use futures::future::select_ok (playground):

use std::time::Duration;
use tokio; // 1.16.1
use futures; // 0.3.19

#[tokio::main]
async fn main() {
    let first_future = async {
        tokio::time::sleep(Duration::from_secs(1)).await;
        Ok(3)
    };
    let second_future = async {
        tokio::time::sleep(Duration::from_millis(100)).await;
        Err(())
    };
    let third_future = async {
        tokio::time::sleep(Duration::from_secs(300)).await;
        Ok(3)
    };
    futures::future::select_ok(&[first_future,second_future.await,third_future]).await;
}

and encountered the error:

error[E0308]: mismatched types
  --> src/main.rs:19:47
   |
7  |       let first_future = async {
   |  ______________________________-
8  | |         tokio::time::sleep(Duration::from_secs(1)).await;
9  | |         Ok(3)
10 | |     };
   | |_____- the expected `async` block
...
19 |       futures::future::select_ok(&[first_future,second_future.await,third_future]).await;
   |                                                 ^^^^^^^^^^^^^^^^^^^ expected opaque type, found enum `Result`
   |
   = note: expected opaque type `impl futures::Future<Output = [async output]>`
                     found enum `Result<_, ()>`

For more information about this error, try `rustc --explain E0308`.
error: could not compile `playground` due to previous error

I have no idea what I'm missing here, would really appreciate any help.

CodePudding user response:

Each of the async blocks are treated as a different type, the same way closures are (IIRC). All of them implements Future, so you may want to actually dynamically dispatch them. For that you need to wrap them in Pin<Box>:

use futures;
use std::future::Future;
use std::pin::Pin;
use std::time::Duration;
use tokio; // 1.16.1 // 0.3.19

#[tokio::main]
async fn main() {
    let first_future = async {
        tokio::time::sleep(Duration::from_secs(1)).await;
        Ok(3)
    };
    let second_future = async {
        tokio::time::sleep(Duration::from_millis(100)).await;
        Err(())
    };
    let third_future = async {
        tokio::time::sleep(Duration::from_secs(300)).await;
        Ok(3)
    };
    let futures: [Pin<Box<dyn Future<Output = Result<usize, ()>>>>; 3] = [
        Box::pin(first_future),
        Box::pin(second_future),
        Box::pin(third_future),
    ];
    futures::future::select_ok(futures).await;
}

Playground

  • Related