理解错误:特征"期货::未来::未来"未为"()"实现



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

我已经阅读了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文档来了解预期的返回值?

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的文档,您会发现它是为Result实现的,因此它适用于Ok(()),但它不适用于(),因此如果您的闭包不返回任何内容,它不起作用。

基本上你传递给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 项目有此票证来跟踪所述诊断问题的进度。

最新更新