Tokio 文档 "chaining computations" 部分的示例无法编译:"expected struct `std::io::Error`, found ()"
The example from the "chaining computations" section of the Tokio docs does not compile: "expected struct `std::io::Error`, found ()"
我正在从官方文档中学习Tokio. I read Getting asynchronous,但是Chaining computations部分的源代码无法在最新的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编译器版本问题?我该如何解决?
Tokio::run
具有以下签名:
pub fn run<F>(future: F)
where
F: Future<Item = (), Error = ()> + Send + 'static,
这意味着它接受一个 Future
接受一个 ()
作为 Item
并且有 ()
作为错误类型。
另一方面,您的 HelloWorld
impl 有
type Item = ();
type Error = io::Error;
这意味着它们不兼容,您必须以某种方式将 io::Error
转换为 ()
。
我建议使用 map_err
tokio::run(hello_world.map_err(|e| Err(e).unwrap()))
处理错误以防万一发生不好的事情。您当然可以进行更好的错误处理,但这会起作用。
有趣的是,我在浏览器中禁用了 JavaScript,因此我在网页上的 Rustdoc 中看到了评论:
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)
}
#
表示 Rustdoc 不应打印该行,但应在测试时执行它。 我觉得这是一个mistake/oversight,还有一个open issue and a fix pending。PR已合并,网页已更新。
我正在从官方文档中学习Tokio. I read Getting asynchronous,但是Chaining computations部分的源代码无法在最新的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编译器版本问题?我该如何解决?
Tokio::run
具有以下签名:
pub fn run<F>(future: F)
where
F: Future<Item = (), Error = ()> + Send + 'static,
这意味着它接受一个 Future
接受一个 ()
作为 Item
并且有 ()
作为错误类型。
另一方面,您的 HelloWorld
impl 有
type Item = ();
type Error = io::Error;
这意味着它们不兼容,您必须以某种方式将 io::Error
转换为 ()
。
我建议使用 map_err
tokio::run(hello_world.map_err(|e| Err(e).unwrap()))
处理错误以防万一发生不好的事情。您当然可以进行更好的错误处理,但这会起作用。
有趣的是,我在浏览器中禁用了 JavaScript,因此我在网页上的 Rustdoc 中看到了评论:
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)
}
#
表示 Rustdoc 不应打印该行,但应在测试时执行它。 我觉得这是一个mistake/oversight,还有一个open issue and a fix pending。PR已合并,网页已更新。