理解错误:特征`futures :: future :: Future`未为`()`实现

时间:2019-08-30 03:59:30

标签: rust rust-tokio

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

我已经阅读了tokio docs,并尝试了许多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()。我知道这是事实,但不完全是原因。这也许是先前问题How do I interpret the signature of read_until and what is AsyncRead + BufRead in Tokio?的另一半-现在,我对闭包有了更好的了解,但无法完全解析文档以了解期望的返回值。

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

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的文档来了解期望的返回值?

2 个答案:

答案 0 :(得分:1)

基本上,您传递给and_then的闭包类型错误。期望:

  

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

但是您给它一个单位类型的闭包,即不返回任何值。因此,错误。

也就是说,rustc错误消息在这里不是最佳的。如果它显示为:

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

rust-lang项目使用此ticket来跟踪有关诊断问题的进度。

答案 1 :(得分:1)

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类型的参数,并返回某种B类型的
  • 闭包返回的类型B必须转换为将来的类型。
  • 如果将来返回错误,则该错误必须具有类型Self::Error

此外,如果您查看IntoFuture的文档,您会发现它是implemented for Result,因此它适用于Ok(()),但并未为{{1 }},因此如果您的闭包不返回任何内容,它将不起作用。