3

I am implementing Tokio's AsyncRead for a struct, but the implementation is just a pass through to a contained struct. The implementation that I finally got to compile is:

use std::pin::Pin;

// A simplified version of Tokio's AsyncRead
trait Async {
    fn poll_read(self: Pin<&mut Self>);
}

struct Inner {}

impl Async for Inner {
    fn poll_read(self: Pin<&mut Self>) {
        // Actual implementation would be here
    }
}

struct Outer {
    inner: Inner,
}

impl Async for Outer {
    fn poll_read(self: Pin<&mut Self>) {
        // This is a wrapper implementation, just deferring to inner
        Pin::new(&mut self.get_mut().inner).poll_read()
    }
}

fn main() {
    let mut outer = Outer { inner: Inner {} };
    Pin::new(&mut outer).poll_read()
}

Rust Playground

There are libraries that hide some details of these pin handling issues (e.g. see the answer in No method named `poll` found for a type that implements `Future`), but I am trying to understand what is actually going on 'under the hood'. I have two related questions:

  1. Is there a cleaner way of doing Pin::new(&mut self.get_mut().io).? That seems a particularly convoluted way of showing the compiler that the struct inside a pinned struct is also Pin.

  2. This implementation is only possible because my struct is Unpin (otherwise I couldn't call get_mut()). How would I achieve this otherwise?

Lucretiel
  • 3,145
  • 1
  • 24
  • 52
WillW
  • 871
  • 6
  • 18
  • See also [When is it safe to move a member value out of a pinned future?](https://stackoverflow.com/q/56058494/155423) – Shepmaster Aug 21 '19 at 14:05
  • I have edited to add a MRE, and also to clarify why the other question (that I hadn't found - thanks) doesn't quite answer what I'm looking for. The latter is a judgement call though and I would understand if you wanted to close this question as 'already answered'. – WillW Aug 21 '19 at 15:41
  • Your question(s) seem to be straying off in different directions. The linked question shows how to do it for `Unpin` types, and links further to the docs to explain how it works. This ostensibly answers your #2. You are also asking if there's a "cleaner" way, but haven't described what "cleaner" means. You could create function or extension trait that writes some of that code for you (like the `poll_unpin` method in the other question). Then you've updated your question to ask about "under the hood", which is drastically different and broader from anything else in the question. – Shepmaster Aug 21 '19 at 15:48

0 Answers0