Почему `Box <dyn Sink>` не реализует черту `Sink` при использовании Tokio и экспериментальной поддержки async / await? - PullRequest
0 голосов
/ 14 ноября 2018

Я играю с async / await, используя Tokio с включенной функцией async / await в моем Cargo.toml (и последней версии Rust nightly с выпуском 2018):

tokio = { version = "0.1.11", features = ["async-await-preview"] }

столкнуться с ошибкой, которую я не понимаю, которая воспроизводится в этом минимальном примере:

#![feature(await_macro, async_await, futures_api)]
use tokio::prelude::*;

pub fn main() {
    tokio::run_async(async {
        let s: Option<Box<dyn Sink<SinkItem = u8, SinkError = ()> + Send + Sync + 'static>> = None;

        if let Some(sink) = s {
            await!(sink.send_async(100));
        }
    });
}

Ошибка:

error[E0277]: the trait bound `for<'r> (dyn futures::sink::Sink<SinkItem=u8, SinkError=()> + std::marker::Sync + std::marker::Send + 'r): futures::sink::Sink` is not satisfied
 --> src/main.rs:5:5
  |
5 |     tokio::run_async(async {
  |     ^^^^^^^^^^^^^^^^ the trait `for<'r> futures::sink::Sink` is not implemented for `dyn futures::sink::Sink<SinkItem=u8, SinkError=()> + std::marker::Sync + std::marker::Send`
  |
  = note: required because of the requirements on the impl of `futures::sink::Sink` for `std::boxed::Box<dyn futures::sink::Sink<SinkItem=u8, SinkError=()> + std::marker::Sync + std::marker::Send>`
  = note: required because it appears within the type `tokio_async_await::sink::send::Send<'_, std::boxed::Box<dyn futures::sink::Sink<SinkItem=u8, SinkError=()> + std::marker::Sync + std::marker::Send>>`
  = note: required because it appears within the type `for<'r, 's, 't0, 't1> {std::option::Option<std::boxed::Box<(dyn futures::sink::Sink<SinkItem=u8, SinkError=()> + std::marker::Sync + std::marker::Send + 'r)>>, std::boxed::Box<(dyn futures::sink::Sink<SinkItem=u8, SinkError=()> + std::marker::Sync + std::marker::Send + 's)>, tokio_async_await::sink::send::Send<'t0, std::boxed::Box<(dyn futures::sink::Sink<SinkItem=u8, SinkError=()> + std::marker::Sync + std::marker::Send + 't1)>>, ()}`
  = note: required because it appears within the type `[static generator@src/main.rs:5:28: 11:6 for<'r, 's, 't0, 't1> {std::option::Option<std::boxed::Box<(dyn futures::sink::Sink<SinkItem=u8, SinkError=()> + std::marker::Sync + std::marker::Send + 'r)>>, std::boxed::Box<(dyn futures::sink::Sink<SinkItem=u8, SinkError=()> + std::marker::Sync + std::marker::Send + 's)>, tokio_async_await::sink::send::Send<'t0, std::boxed::Box<(dyn futures::sink::Sink<SinkItem=u8, SinkError=()> + std::marker::Sync + std::marker::Send + 't1)>>, ()}]`
  = note: required because it appears within the type `std::future::GenFuture<[static generator@src/main.rs:5:28: 11:6 for<'r, 's, 't0, 't1> {std::option::Option<std::boxed::Box<(dyn futures::sink::Sink<SinkItem=u8, SinkError=()> + std::marker::Sync + std::marker::Send + 'r)>>, std::boxed::Box<(dyn futures::sink::Sink<SinkItem=u8, SinkError=()> + std::marker::Sync + std::marker::Send + 's)>, tokio_async_await::sink::send::Send<'t0, std::boxed::Box<(dyn futures::sink::Sink<SinkItem=u8, SinkError=()> + std::marker::Sync + std::marker::Send + 't1)>>, ()}]>`
  = note: required because it appears within the type `impl std::future::Future`
  = note: required by `tokio::async_await::run_async`

и она исчезнет, ​​если я удалю начало строки"Ждите!".

При использовании Tokio без экспериментальной поддержки async / await моя программа довольна идеей, что Box<dyn Sink> - это Sink, поэтому я не совсем уверен, почему ошибка возникает при использовании async /подождите.

Что означает ошибка?Как я могу обойти это?

1 Ответ

0 голосов
/ 15 ноября 2018

Мое исправление заключалось в том, чтобы обернуть Box ed Sink s в новый тип и реализовать черту Sink. Я думаю, что, возможно, Box<dyn Sink> не реализует Sink в этот ночной вечер, что, в основном, означает сообщение об ошибке (я полагаю, что async / await shims переопределяет Sink и не реализует его на Box).

Моя оболочка в итоге выглядела так:

struct BoxedSink<I, E>(Box<dyn Sink<SinkItem = I, SinkError = E> + Send + Sync + 'static>);

impl<I, E> Sink for BoxedSink<I, E> {
    type SinkItem = I;
    type SinkError = E;

    fn start_send(
        &mut self,
        input: Self::SinkItem,
    ) -> Result<AsyncSink<Self::SinkItem>, Self::SinkError> {
        self.0.start_send(input)
    }

    fn poll_complete(&mut self) -> Poll<(), Self::SinkError> {
        self.0.poll_complete()
    }
}

Вы должны обернуть здесь Box<Sinks>, чтобы они снова реализовали Sink.

...