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

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

这个问题是关于如何阅读 Rust 文档并提高我对 Rust 的理解,从而了解如何解决这个特定的编译器错误。

我已阅读 tokio docs and experimented with many of the examples。在编写自己的代码时,我经常 运行 遇到我不理解的编译器错误,并且经常发现我可以修复代码,但不理解 为什么 具体语法是需要。

我根据tokio的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(())
  });

}

以上代码不正确,需要注释掉Ok()。我知道这是真的,但不完全是为什么。这可能是先前问题 的另一半——现在我更了解闭包,但不能完全解析文档以理解预期的 return 值。

当我尝试编译上面不正确的代码时,出现以下错误:

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 `()`

我的问题分为两部分:

  1. 错误消息试图告诉我什么?
  2. 我如何使用 and_then 的文档来理解预期的 return 值?

基本上您传递给 and_then 的闭包类型错误。它预计:

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

但是你给它一个单位类型的闭包,即returns没有值。因此错误。

也就是说,rustc 错误消息在这里不是最佳选择。如果是这样就更好了:

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

rust-lang 项目有这个 ticket 来跟踪上述诊断问题的进展。

and_then 的文档指出:

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, 

这意味着:

  • 您的闭包必须接受 Self::Item 类型的参数和 return 某种类型 B
  • 由闭包编辑的 B return 类型必须可转换为 future。
  • 如果未来 return 是一个错误,那么该错误的类型必须是 Self::Error

此外,如果您查看 IntoFuture, you will see that it is implemented for Result 的文档,那么它适用于 Ok(()),但未针对 () 实现,因此如果你的闭包 return 没什么。