understanding error: trait `futures::future::Future` is not implemented for `()`

偶尔善良 提交于 2020-05-16 18:40:32

问题


This question is about how to read the Rust documentation and improve my understanding of Rust so as to understand how to address this specific compiler error.

I've read the tokio docs and experimented with many of the examples. In writing my own code, I frequently run into compiler errors that I don't understand and often found I can fix the code, but don't understand why specific syntax is needed.

I reproduced with a very simple example based on tokio's hello world:

use futures::Future;
use tokio::net::TcpStream;
use tokio::prelude::*;

fn main() {
  let addr = "127.0.0.1:6142".parse().unwrap();

  let client = TcpStream::connect(&addr).and_then(|stream| {
      println!("created stream");
      // Process stream here.

      // Ok(())
  });

}

The above code is incorrect, requiring the commented out Ok(). I know that this is true, but not exactly why. This is perhaps the other half of a prior question How do I interpret the signature of read_until and what is AsyncRead + BufRead in Tokio? -- now I understand closures better, but can't quite parse the docs to understand the expected return value.

When I attempt to compile the incorrect code above, I get the following error:

error[E0277]: the trait bound `(): futures::future::Future` is not satisfied
 --> tokio-chat-client/src/main.rs:8:42
  |
8 |   let client = TcpStream::connect(&addr).and_then(|stream| {
  |                                          ^^^^^^^^ the trait `futures::future::Future` is not implemented for `()`
  |
  = note: required because of the requirements on the impl of `futures::future::IntoFuture` for `()`

There are two parts to my question:

  1. What is the error message trying to tell me?
  2. How would I use the docs for and_then to understand the expected return value?

回答1:


The docs for and_then state that:

fn and_then<F, B>(self, f: F) -> AndThen<Self, B, F> where
    F: FnOnce(Self::Item) -> B,
    B: IntoFuture<Error = Self::Error>,
    Self: Sized, 

This means that:

  • Your closure must accept an argument of type Self::Item and return some type B
  • The type B returned by your closure must be convertible into a future.
  • And if that future returns an error, then that error must have type Self::Error.

Moreover, if you look at the doc for IntoFuture, you will see that it is implemented for Result, so it works for Ok(()), but that it is not implemented for (), so it doesn't work if your closure returns nothing.




回答2:


Basically the closure you pass to and_then has the wrong type. It expects:

F: FnOnce(Self::Item) -> B

But you give it a closure of unit type, i.e. returns no value. Hence the error.

That said, the rustc error message isn't optimal here. It would be much better if it reads:

let client = TcpStream::connect(&addr).and_then(|stream| {
    println!("created stream");
    // error: mismatched types: expected `IntoFuture` but found `()`
});

The rust-lang project has this ticket to track the progress on said diagnostics issue.



来源:https://stackoverflow.com/questions/57720321/understanding-error-trait-futuresfuturefuture-is-not-implemented-for

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!