rustfuturerust-tokiotokio-postgres

How to pass a Future as a function argument?


I am used to Scala's Future type where you wrap whatever object you're returning in Future[..] to designate it as such.

My Rust function hello returns Query and I don't seem able to pass that result as an argument with type Future<Output = Query>. Why not and how should I type this better?

The failure occurs when I try to pass the future as an argument:

use std::future::Future;

struct Person;
struct DatabaseError;

type Query = Result<Vec<Person>, DatabaseError>;

async fn hello_future(future: &dyn Future<Output = Query>) -> bool {
    future.await.is_ok()
}

async fn hello() -> Query {
    unimplemented!()
}

async fn example() {
    let f = hello();
    hello_future(&f);
}

fn main() {}

Which fails to compile with the error:

error[E0277]: `&dyn Future<Output = Result<Vec<Person>, DatabaseError>>` is not a future
 --> src/main.rs:9:5
  |
9 |     future.await.is_ok()
  |     ^^^^^^^^^^^^ `&dyn Future<Output = Result<Vec<Person>, DatabaseError>>` is not a future
  |
  = help: the trait `Future` is not implemented for `&dyn Future<Output = Result<Vec<Person>, DatabaseError>>`
  = note: required by `poll`

Solution

  • async functions desugar to returning an opaque value that implements the Future trait. This means that you can accept a generic type that implements that trait. The most succinct syntax is impl Trait, but you could also introduce a named generic parameter:

    async fn hello_future(future: impl Future<Output = Query>) -> bool {
        future.await.is_ok()
    }
    
    async fn example() {
        let f = hello();
        hello_future(f);
    }
    

    See also: