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()
}
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:
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 alsoPin
.This implementation is only possible because my struct is
Unpin
(otherwise I couldn't callget_mut()
). How would I achieve this otherwise?