The example from the “chaining computations” section of the Tokio docs does not compile: “expected struct `std::io::Error`, found ()”

守給你的承諾、 提交于 2020-01-05 09:34:42

问题


I am learning Tokio. I read Getting asynchronous from the official docs, but the source code from the Chaining computations section cannot be compiled under the latest Rust version (Rust 2018, v1.31):

extern crate tokio;
extern crate bytes;
#[macro_use]
extern crate futures;

use tokio::io::AsyncWrite;
use tokio::net::{TcpStream, tcp::ConnectFuture};
use bytes::{Bytes, Buf};
use futures::{Future, Async, Poll};
use std::io::{self, Cursor};

// HelloWorld has two states, namely waiting to connect to the socket
// and already connected to the socket
enum HelloWorld {
    Connecting(ConnectFuture),
    Connected(TcpStream, Cursor<Bytes>),
}

impl Future for HelloWorld {
    type Item = ();
    type Error = io::Error;

    fn poll(&mut self) -> Poll<(), io::Error> {
        use self::HelloWorld::*;

        loop {
            let socket = match *self {
                Connecting(ref mut f) => {
                    try_ready!(f.poll())
                }
                Connected(ref mut socket, ref mut data) => {
                    // Keep trying to write the buffer to the socket as long as the
                    // buffer has more bytes it available for consumption
                    while data.has_remaining() {
                        try_ready!(socket.write_buf(data));
                    }

                    return Ok(Async::Ready(()));
                }
            };

            let data = Cursor::new(Bytes::from_static(b"hello world"));
            *self = Connected(socket, data);
        }
    }
}

fn main() {
    let addr = "127.0.0.1:1234".parse().unwrap();
    let connect_future = TcpStream::connect(&addr);
    let hello_world = HelloWorld::Connecting(connect_future);

    // Run it
    tokio::run(hello_world)
}

The compiler outputs error messages:

error[E0271]: type mismatch resolving `<HelloWorld as futures::Future>::Error == ()`
  --> src\main.rs:54:5
   |
54 |     tokio::run(hello_world)
   |     ^^^^^^^^^^ expected struct `std::io::Error`, found ()
   |
   = note: expected type `std::io::Error`
              found type `()`
   = note: required by `tokio::run`

Is the problem caused by the version of my Rust compiler? How do I fix it?


回答1:


Tokio::run has the following signature:

pub fn run<F>(future: F)
where
    F: Future<Item = (), Error = ()> + Send + 'static, 

which means that it accepts a Future which accepts a () as Item and has () as the error type.

On the other hand, your HelloWorld impl has

type Item = ();
type Error = io::Error;

which means they are not compatible, you have to convert the io::Error to () somehow.

I would suggest using map_err

tokio::run(hello_world.map_err(|e| Err(e).unwrap()))

to handle the error in case something bad happens. You could of course make better error handling, but this will work.


Interestingly enough, I have JavaScript disabled in my browser and therefore I see the comments in the Rustdoc on the webpage:

fn main() {
    let addr = "127.0.0.1:1234".parse().unwrap();
    let connect_future = TcpStream::connect(&addr);
    let hello_world = HelloWorld::Connecting(connect_future);
# let hello_world = futures::future::ok::<(), ()>(());

    // Run it
    tokio::run(hello_world)
}

The # means that Rustdoc should not print that line, but should execute it while testing. I think this is a mistake/oversight and there is also an open issue and a fix pending. PR has been merged, webpage has been updated.



来源:https://stackoverflow.com/questions/53818465/the-example-from-the-chaining-computations-section-of-the-tokio-docs-does-not

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!