10

我正在尝试使用Tokio crate 在 Rust 中编写一个简单的 TCP 客户端。我的代码非常接近这个例子减去 TLS:

extern crate futures;
extern crate tokio_core;
extern crate tokio_io;

use futures::Future;
use tokio_core::net::TcpStream;
use tokio_core::reactor::Core;
use tokio_io::io;

fn main() {
    let mut core = Core::new().unwrap();
    let handle = core.handle();

    let connection = TcpStream::connect(&"127.0.0.1:8080".parse().unwrap(), &handle);

    let server = connection.and_then(|stream| {
        io::write_all(stream, b"hello");
    });

    core.run(server).unwrap();
}

但是,编译失败并出现以下错误:

error[E0277]: the trait bound `(): futures::Future` is not satisfied
  --> src/main.rs:16:29
   |
16 |     let server = connection.and_then(|stream| {
   |                             ^^^^^^^^ the trait `futures::Future` is not implemented for `()`
   |
   = note: required because of the requirements on the impl of `futures::IntoFuture` for `()`

error[E0277]: the trait bound `(): futures::Future` is not satisfied
  --> src/main.rs:20:10
   |
20 |     core.run(server).unwrap();
   |          ^^^ the trait `futures::Future` is not implemented for `()`
   |
   = note: required because of the requirements on the impl of `futures::IntoFuture` for `()`

我觉得这很奇怪,因为根据文档,它应该被实施。

我正在使用

  • 锈 1.19.0
  • 期货 0.1.16
  • 东京核心 0.1.10
  • 东京io 0.1.3

我错过了什么?

4

2 回答 2

14

TL;DR:删除 . 之后的分号io::write_all


查看 的定义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, 

闭包 ( F) 必须返回某种类型 ( B),该类型 ( ) 可以转换为具有B: IntoFuture与起始闭包 ( ) 匹配的错误类型的 future ( Error = Self::Error)。

你的关闭会返回什么?(). 这是为什么?;因为您在行尾放置了一个分号 ( )。()实现 traitIntoFuture,这由错误消息部分“on the impl of futures::IntoFuturefor ()”指示:

impl<F: Future> IntoFuture for F {
    type Future = F;
    type Item = F::Item;
    type Error = F::Error;
}

删除分号将导致Future返回的io::write_all返回到and_then并且程序将编译。

通常,期货通过将本身就是期货的较小组件组合在一起来工作。所有这些共同构建了一个庞大的未来,它本质上是一个状态机。记住这一点很好,因为在使用此类组合器时几乎总是需要返回未来。

于 2017-10-07T22:02:18.183 回答
10

不幸的是,这里的答案非常具体,但是对于任何类型的搜索都会出现问题:

该特征futures::Future未实现()

这种错误的典型场景是:

foo.then(|stream| {
    // ... Do random things here
    final_statement();
});

这会导致错误,因为大多数扩展函数都需要返回类型来实现IntoFuture。但是,()不实现IntoFuture,并且通过以;隐式返回类型终止块是()

但是,IntoFuture OptionResult实现。

不要只是模糊地随机删除分号,希望这会以某种方式神奇地使您的代码编译,请考虑:

您应该返回可以转换为Futureusing的东西IntoFuture

如果您没有返回的特定承诺,请考虑Ok(())在回调中返回简单地说“这已完成”:

foo.then(|stream| {
    // ... Do random things here
    final_statement();
    return Ok(()); // <-- Result(()) implements `IntoFuture`.
});

请特别注意,我使用显式的 return 语句终止此块;这是故意的。这是一个典型的例子,说明“可以省略分号以隐式返回对象”的人机工程学是如何明显有害的;终止块Ok(());将继续失败并出现相同的错误。

于 2018-03-17T02:19:33.200 回答