这个问题是关于如何阅读 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 `()`
我的问题有两个部分:
- 错误消息试图告诉我什么?
- 如何使用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 项目有此票证来跟踪所述诊断问题的进度。