Skip to content

Commit dd6d81c

Browse files
authoredNov 16, 2023
fix(rt): implement Read/Write for Pin<P> (#3413)
Without these impls, something like Pin<Box<T: Read>> does not actually implement Read. Closes #3412 BREAKING CHANGE: Pin is #[fundamental], so this theoretically conflicts with existing user Read/Write for Pin<...> impls. However, those impls probably don't exist yet.
1 parent a475ada commit dd6d81c

File tree

1 file changed

+57
-0
lines changed

1 file changed

+57
-0
lines changed
 

‎src/rt/io.rs

+57
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
use std::fmt;
22
use std::mem::MaybeUninit;
3+
use std::ops::DerefMut;
34
use std::pin::Pin;
45
use std::task::{Context, Poll};
56

@@ -294,6 +295,20 @@ impl<T: ?Sized + Read + Unpin> Read for &mut T {
294295
deref_async_read!();
295296
}
296297

298+
impl<P> Read for Pin<P>
299+
where
300+
P: DerefMut,
301+
P::Target: Read,
302+
{
303+
fn poll_read(
304+
self: Pin<&mut Self>,
305+
cx: &mut Context<'_>,
306+
buf: ReadBufCursor<'_>,
307+
) -> Poll<std::io::Result<()>> {
308+
pin_as_deref_mut(self).poll_read(cx, buf)
309+
}
310+
}
311+
297312
macro_rules! deref_async_write {
298313
() => {
299314
fn poll_write(
@@ -336,3 +351,45 @@ impl<T: ?Sized + Write + Unpin> Write for Box<T> {
336351
impl<T: ?Sized + Write + Unpin> Write for &mut T {
337352
deref_async_write!();
338353
}
354+
355+
impl<P> Write for Pin<P>
356+
where
357+
P: DerefMut,
358+
P::Target: Write,
359+
{
360+
fn poll_write(
361+
self: Pin<&mut Self>,
362+
cx: &mut Context<'_>,
363+
buf: &[u8],
364+
) -> Poll<std::io::Result<usize>> {
365+
pin_as_deref_mut(self).poll_write(cx, buf)
366+
}
367+
368+
fn poll_write_vectored(
369+
self: Pin<&mut Self>,
370+
cx: &mut Context<'_>,
371+
bufs: &[std::io::IoSlice<'_>],
372+
) -> Poll<std::io::Result<usize>> {
373+
pin_as_deref_mut(self).poll_write_vectored(cx, bufs)
374+
}
375+
376+
fn is_write_vectored(&self) -> bool {
377+
(**self).is_write_vectored()
378+
}
379+
380+
fn poll_flush(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<std::io::Result<()>> {
381+
pin_as_deref_mut(self).poll_flush(cx)
382+
}
383+
384+
fn poll_shutdown(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<std::io::Result<()>> {
385+
pin_as_deref_mut(self).poll_shutdown(cx)
386+
}
387+
}
388+
389+
/// Polyfill for Pin::as_deref_mut()
390+
/// TODO: use Pin::as_deref_mut() instead once stabilized
391+
fn pin_as_deref_mut<P: DerefMut>(pin: Pin<&mut Pin<P>>) -> Pin<&mut P::Target> {
392+
// SAFETY: we go directly from Pin<&mut Pin<P>> to Pin<&mut P::Target>, without moving or
393+
// giving out the &mut Pin<P> in the process. See Pin::as_deref_mut() for more detail.
394+
unsafe { pin.get_unchecked_mut() }.as_mut()
395+
}

0 commit comments

Comments
 (0)
Please sign in to comment.