Victor Ermolaev
Victor Ermolaev

Reputation: 791

Why do I get an error about mismatched types when using TryFuture instead of the equivalent Future?

I have the following working piece of code using Future.

use futures::{future, Future};

fn fut_res() -> impl Future<Output = Result<(), failure::Error>> {
    future::ok::<(), failure::Error>(())
}

#[tokio::main]
async fn main() -> Result<(), failure::Error> {
    if let Err(e) = fut_res().await {
        println!("{:?}", e);
    }

    Ok(())
}

From what I read in the docs I should be able to alter the code to use TryFuture as follows:

use futures::{future, TryFuture};

fn try_fut() -> impl TryFuture<Ok = (), Error = failure::Error> {
    future::ok::<(), failure::Error>(())
}

#[tokio::main]
async fn main() -> Result<(), failure::Error> {
    if let Err(e) = try_fut().await {
        println!("{:?}", e);
    }

    Ok(())
}

The compiler complains that try_fut must return the associated type Output, but this type by definition is Result<(), failure::Error>:

error[E0308]: mismatched types
 --> src/lib.rs:9:12
  |
9 |     if let Err(e) = try_fut().await {
  |            ^^^^^^ expected associated type, found enum `std::result::Result`
  |
  = note: expected type `<impl futures_core::future::TryFuture as core::future::future::Future>::Output`
             found type `std::result::Result<_, _>`
  = note: consider constraining the associated type `<impl futures_core::future::TryFuture as core::future::future::Future>::Output` to `std::result::Result<_, _>` or calling a method that returns `<impl futures_core::future::TryFuture as core::future::future::Future>::Output`
  = note: for more information, visit https://doc.rust-lang.org/book/ch19-03-advanced-traits.html

How do I explain this to the compiler?

Playground does not work because tokio is still in alpha, but there is also an appropriate Cargo.toml.

Upvotes: 5

Views: 977

Answers (1)

Ahmed Masud
Ahmed Masud

Reputation: 22402

Your syntax doesn't work at the moment. The docs for TryFuture show that you have to wrap the Result in a Poll for the time being (the emphasis is mine):

fn try_poll(
    self: PinMut<Self>, 
    cx: &mut Context ) -> Poll<Result<Self::Ok, Self::Error>> [−]

Poll this TryFuture as if it were a Future.

This method is a stopgap for a compiler limitation that prevents us from directly inheriting from the Future trait; in the future it won't be needed.

playground

When this compiler limitation resolves, this approach will no longer be necessary and you will be able to do what you did (or something along the same lines)

References

Upvotes: 2

Related Questions