Пример из раздела "Цепные вычисления" документации Tokio не компилируется: "ожидаемая структура`std::io::Error`, found ()"
Я учу Токио. Я прочитал Получение асинхронного из официальных документов, но исходный код из раздела вычислений Chaining не может быть скомпилирован в последней версии 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 ответ
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()))
обработать ошибку в случае, если что-то плохое случится. Конечно, вы можете улучшить обработку ошибок, но это сработает.
Интересно, что у меня отключен 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 не должен печатать эту строку, но должен выполнять ее во время тестирования. Я думаю, что это ошибка / недосмотр, и есть еще открытая проблема и ожидающие исправления. PR был объединен, веб-страница обновлена.