Tokio文档的“链接计算”部分中的示例未编译:“预期的结构`std :: io :: Error`,found()”

时间:2018-12-17 15:40:53

标签: rust rust-tokio

我正在学习Tokio。我从官方文档中阅读了Getting asynchronous,但是 Chaining Calculations 部分的源代码无法在最新的Rust版本(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)
}

编译器输出错误消息:

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`

问题是由Rust编译器的版本引起的吗?我该如何解决?

1 个答案:

答案 0 :(得分:2)

Tokio::run具有以下签名:

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

这意味着它接受Future,该()接受Item作为()并具有HelloWorld作为错误类型。

另一方面,您的type Item = (); type Error = io::Error; 展示有

io::Error

这意味着它们不兼容,您必须以某种方式将()转换为map_err

我建议使用tokio::run(hello_world.map_err(|e| Err(e).unwrap()))

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)
}

处理错误,以防万一发生不良情况。您当然可以进行更好的错误处理,但这会起作用。


有趣的是,我在浏览器中禁用了JavaScript,因此我在网页的Rustdoc中看到了注释:

#

"networkSecurityGroup": { "id": "NSG_Resource_Id" } 表示Rustdoc不应打印该行,而应在测试时执行。 我认为这是一个错误/疏忽,并且还有open issuefix pending PR已合并,网页已更新。