I am trying to wrap a stream object with the goal of introducing some timeouts on it's read operations, and am starting with just the bare skeleton, but not even this compiles:
use futures::io::{AsyncBufRead, AsyncRead};
use std::io;
use std::io::Result;
use std::pin::Pin;
use std::task::{Context, Poll};
pub struct ImpatientStream<T> {
inner: Pin<Box<T>>,
}
impl<T> ImpatientStream<T> {
pub fn new(stream: T) -> Self {
Self {
inner: Box::pin(stream),
}
}
}
impl<T: AsyncRead + Unpin> AsyncRead for ImpatientStream<T> {
fn poll_read(
mut self: Pin<&mut Self>,
cx: &mut Context<'_>,
buf: &mut [u8],
) -> Poll<Result<usize>> {
self.inner.as_mut().poll_read(cx, buf)
}
}
impl<T: AsyncBufRead + Unpin> AsyncBufRead for ImpatientStream<T> {
fn poll_fill_buf(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<io::Result<&[u8]>> {
self.inner.as_mut().poll_fill_buf(cx)
}
fn consume(mut self: Pin<&mut Self>, amt: usize) {
self.inner.as_mut().consume(amt)
}
}
fn main() -> io::Result<()> {
Ok(())
}
When I try to compile this I get:
error[E0515]: cannot return value referencing function parameter `self`
--> src/bin/echo-server-copy.rs:31:9
|
31 | self.inner.as_mut().poll_fill_buf(cx)
| ----^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
| |
| returns a value referencing data owned by the current function
| `self` is borrowed here
Am I doing something wrong or is this just not possible to be done like this?
For anyone coming across this in the future, the trick lies in what
self
actually is. It's easy to miss thatself
is actually aPin
rather than a reference toself
.As far as I understand it, the expression
self.inner
ends up returning aPin
which itself has a reference toself
- hence the compiler message that we return a value referencing data owned by the current function.The workaround I found here is to use
Pin::get_mut
which allows us to get a&mut self
, and thus return a reference to its fieldself.inner
.Updating the above example on line 31:
This can be confirmed on the playground
Also this discussion was helpful in understanding what's happening here.