Errors implementing using generics

I know I must be doing something boneheaded here, but I can't for the life of me see it. I'm trying to create a struct which wraps something which implements tokio.io.AsyncRead and something which implements tokio.io.AsyncWrite. Here's my code:

use std::pin::Pin;
use std::task::{Context, Poll};
use tokio::io::{AsyncRead, AsyncWrite, Error, Result};

struct AsyncReadWrite<In: AsyncRead, Out: AsyncWrite> {
    input: In,
    output: Out,
}

impl<In: AsyncRead, Out: AsyncWrite> AsyncRead for AsyncReadWrite<In, Out> {
    fn poll_read(self: Pin<&mut Self>, cx: &mut Context, buf: &mut [u8]) -> Poll<Result<usize>> {
        self.input.poll_read(cx, buf)
    }
}

impl<In: AsyncRead, Out: AsyncWrite> AsyncWrite for AsyncReadWrite<In, Out> {
    fn poll_write(self: Pin<&mut Self>, cx: &mut Context, buf: &[u8]) -> Poll<Result<usize>> {
        self.output.poll_write(cx, buf)
    }

    fn poll_flush(self: Pin<&mut Self>, cx: &mut Context) -> Poll<std::result::Result<(), Error>> {
        self.output.poll_flush(cx)
    }

    fn poll_shutdown(
        self: Pin<&mut Self>,
        cx: &mut Context,
    ) -> Poll<std::result::Result<(), Error>> {
        self.output.poll_shutdown(cx)
    }
}

What I get is the following errors:

error[E0599]: no method named `poll_read` found for type `In` in the current scope
  --> src/main.rs:12:20
   |
12 |         self.input.poll_read(cx, buf)
   |                    ^^^^^^^^^ method not found in `In`
   |
   = help: items from traits can only be used if the type parameter is bounded by the trait
help: the following trait defines an item `poll_read`, perhaps you need to restrict type parameter `In` with it:
   |
10 | impl<In: tokio::io::async_read::AsyncRead + AsyncRead, Out: AsyncWrite> AsyncRead for AsyncReadWrite<In, Out> {
   |      ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

error[E0599]: no method named `poll_write` found for type `Out` in the current scope
  --> src/main.rs:18:21
   |
18 |         self.output.poll_write(cx, buf)
   |                     ^^^^^^^^^^ method not found in `Out`
   |
   = help: items from traits can only be used if the type parameter is bounded by the trait
help: the following trait defines an item `poll_write`, perhaps you need to restrict type parameter `Out` with it:
   |
16 | impl<In: AsyncRead, Out: tokio::io::async_write::AsyncWrite + AsyncWrite> AsyncWrite for AsyncReadWrite<In, Out> {
   |                     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

error[E0599]: no method named `poll_flush` found for type `Out` in the current scope
  --> src/main.rs:22:21
   |
22 |         self.output.poll_flush(cx)
   |                     ^^^^^^^^^^ method not found in `Out`
   |
   = help: items from traits can only be used if the type parameter is bounded by the trait
help: the following trait defines an item `poll_flush`, perhaps you need to restrict type parameter `Out` with it:
   |
16 | impl<In: AsyncRead, Out: tokio::io::async_write::AsyncWrite + AsyncWrite> AsyncWrite for AsyncReadWrite<In, Out> {
   |                     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

error[E0599]: no method named `poll_shutdown` found for type `Out` in the current scope
  --> src/main.rs:29:21
   |
29 |         self.output.poll_shutdown(cx)
   |                     ^^^^^^^^^^^^^ method not found in `Out`
   |
   = help: items from traits can only be used if the type parameter is bounded by the trait
help: the following trait defines an item `poll_shutdown`, perhaps you need to restrict type parameter `Out` with it:
   |
16 | impl<In: AsyncRead, Out: tokio::io::async_write::AsyncWrite + AsyncWrite> AsyncWrite for AsyncReadWrite<In, Out> {
   |                     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

error: aborting due to 4 previous errors

Basically, it's telling me to do exactly what I'm doing. What am I doing wrong here?

Any help would be greatly appreciated. Playground link: https://play.rust-lang.org/?version=stable&mode=debug&edition=2018&gist=0dc44312029b629217740330225c7730

Thank you in advance!

-Jack

poll_read takes the receiver as Pin<&mut Self>, so In's impl would need to be passed a Pin<&mut In>. But when you write self.input.poll_read(...) there is no Pin<&mut In> that exists, just a &mut In.

https://doc.rust-lang.org/1.40.0/std/pin/index.html#projections-and-structural-pinning covers this aspect of Pin and ways to proceed.

1 Like

Doh! I knew I was missing something!

Works now! Thanks @dtolnay!!!

-Jack

1 Like

This topic was automatically closed 90 days after the last reply. New replies are no longer allowed.