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

8
这个问题是关于如何阅读Rust文档并提高对Rust的理解,以便了解如何解决特定的编译器错误。
我已经阅读了tokio文档并尝试了许多示例。在编写自己的代码时,我经常遇到我不理解的编译器错误,并且经常发现我可以修复代码,但不理解为什么需要特定的语法。
我根据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()。我知道这是对的,但不知道为什么。这可能是先前问题如何解释read_until的签名以及Tokio中AsyncRead + BufRead是什么?的另一半——现在我更好地理解了闭包,但无法解析文档以了解预期的返回值。
当我尝试编译上面的错误代码时,会出现以下错误:
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的文档来理解预期的返回值?

1
我在处理 Stream 对象上的 for_each() 时遇到了类似的问题。阅读了响应后,我成功地通过在传入闭包的末尾返回 futures_util::future::ready(()) 来解决它。 - MKroehnert
2个回答

7

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` 必须可以转换为一个 future。 - 如果该 future 返回一个错误,则该错误必须具有类型 `Self::Error`。
此外,如果您查看 IntoFuture 的文档,您会发现它已经针对 Result 实现了,因此对于 `Ok(())` 已经可以工作了,但是它没有为 `()` 实现,所以如果您的闭包不返回任何内容,则它将无法工作。

谢谢您的好解释!对我来说关键缺失的部分是IntoFuture是为Result实现的。我忘记了另一个部分(在文档中也找不到),那就是在Rust中返回“nothing”会返回() - Ultrasaurus

2
基本上,您传递给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项目有一个跟踪诊断问题进展的票据,称为"最初的回答"。你可以在这里查看相关内容。

感谢提供票据链接 - 我添加了一个建议 https://github.com/rust-lang/rust/issues/54771#issuecomment-526631724 - Ultrasaurus

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接