Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
792 views
in Technique[技术] by (71.8m points)

tcp - The trait bound `(): futures::Future` is not satisfied when using TcpConnectionNew

I am trying to write a simple TCP client in Rust using Tokio crate. My code is pretty close to this example minus the 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();
}

However, compilation fails with the error:

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 `()`

I find it strange because according to the documentation it should be implemented.

I'm using

  • Rust 1.19.0
  • futures 0.1.16
  • tokio-core 0.1.10
  • tokio-io 0.1.3

What am I missing?

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

TL;DR: remove the semicolon after io::write_all.


Review the definition of 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, 

The closure (F) has to return some type (B) that can be converted into a future (B: IntoFuture) with an error type that matches the starting closure (Error = Self::Error).

What does your closure return? (). Why is that? Because you've placed a semicolon (;) at the end of your line. () does not implement the trait IntoFuture, which is indicated by the error message part "on the impl of futures::IntoFuture for ()":

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

Removing the semicolon will cause the Future returned by io::write_all to be returned back to and_then and the program will compile.

In general, futures work by combining together smaller components which are themselves futures. All of this works together to build a single large future which is essentially a state machine. It's good to keep this in mind, as you will almost always need to return a future when using such combinators.


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...