【问题标题】:understanding error: trait `futures::future::Future` is not implemented for `()`理解错误:特征 `futures::future::Future` 未针对 `()` 实现
【发布时间】:2019-08-30 03:59:30
【问题描述】:

这个问题是关于如何阅读 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 的文档来了解预期的返回值?

【问题讨论】:

  • 我在 Stream 对象上遇到了与 for_each() 类似的问题。阅读回复后,我可以通过在传入的闭包结束时返回 futures_util::future::ready(()) 来修复它。

标签: rust rust-tokio


【解决方案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(()),但它没有为() 实现,所以它没有如果您的闭包没有返回任何内容,则可以工作。

【讨论】:

  • 感谢您的精彩解释!对我来说,缺少的关键部分是 IntoFuture 是为 Result 实现的。我忘记的另一部分(并且在文档中的任何地方都找不到)是在 Rust 中返回“无”,返回 ()
【解决方案2】:

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

F: FnOnce(Self::Item) -&gt; B

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

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

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

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

【讨论】:

猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-05-23
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2014-10-14
  • 1970-01-01
相关资源
最近更新 更多