使用TcpConnectionNew时,不满足特征绑定`():futures :: Future`

Ser*_*gey 8 tcp rust rust-tokio

我正在尝试使用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();
}
Run Code Online (Sandbox Code Playgroud)

但是,编译失败并显示错误:

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 `()`
Run Code Online (Sandbox Code Playgroud)

我发现它很奇怪,因为根据文档它应该实现.

我正在使用

  • Rust 1.19.0
  • 期货0.1.16
  • tokio-core 0.1.10
  • tokio-io 0.1.3

我错过了什么?

She*_*ter 12

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, 
Run Code Online (Sandbox Code Playgroud)

closure(F)必须返回一些type(B),它可以转换为future(B: IntoFuture),其错误类型与起始闭包(Error = Self::Error)相匹配.

什么是你的封闭返回?().这是为什么?因为你;在行的末尾放了一个分号().()没有实现特征IntoFuture,由错误消息部分"on impl of futures::IntoFuturefor ()"表示:

impl<F: Future> IntoFuture for F {
    type Future = F;
    type Item = F::Item;
    type Error = F::Error;
}
Run Code Online (Sandbox Code Playgroud)

删除分号将导致Future返回的io::write_all返回and_then,程序将编译.

一般来说,期货通过将较小的组成部分组合在一起来进行工作.所有这些共同构建了一个基本上是状态机的单一大型未来.记住这一点很好,因为在使用这种组合器时,你几乎总是需要回归未来.


Dou*_*oug 7

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

特质futures::Future未实现()

这种错误的典型情况是:

foo.then(|stream| {
    // ... Do random things here
    final_statement();
});
Run Code Online (Sandbox Code Playgroud)

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

但是,IntoFuture 针对OptionResult实现的。

考虑到希望以某种方式神奇地使代码编译,而不仅仅是模糊地随机删除分号,请考虑:

您应该返回可以转换为Futureusing的内容IntoFuture

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

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

注意,具体来说,我使用显式的return语句终止此块;这是故意的。这是“省略分号以隐式返回对象”的人机工程学对人类有害的典型示例。用终止该块Ok(());将继续失败,并显示相同的错误。