From dd6d81ca4a180695dc70d6c9b2aececd29606224 Mon Sep 17 00:00:00 2001 From: Noa Date: Thu, 16 Nov 2023 07:22:49 -0600 Subject: [PATCH] fix(rt): implement Read/Write for Pin

(#3413) Without these impls, something like Pin> 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. --- src/rt/io.rs | 57 ++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 57 insertions(+) diff --git a/src/rt/io.rs b/src/rt/io.rs index bf045c3714..793103c339 100644 --- a/src/rt/io.rs +++ b/src/rt/io.rs @@ -1,5 +1,6 @@ use std::fmt; use std::mem::MaybeUninit; +use std::ops::DerefMut; use std::pin::Pin; use std::task::{Context, Poll}; @@ -294,6 +295,20 @@ impl Read for &mut T { deref_async_read!(); } +impl

Read for Pin

+where + P: DerefMut, + P::Target: Read, +{ + fn poll_read( + self: Pin<&mut Self>, + cx: &mut Context<'_>, + buf: ReadBufCursor<'_>, + ) -> Poll> { + pin_as_deref_mut(self).poll_read(cx, buf) + } +} + macro_rules! deref_async_write { () => { fn poll_write( @@ -336,3 +351,45 @@ impl Write for Box { impl Write for &mut T { deref_async_write!(); } + +impl

Write for Pin

+where + P: DerefMut, + P::Target: Write, +{ + fn poll_write( + self: Pin<&mut Self>, + cx: &mut Context<'_>, + buf: &[u8], + ) -> Poll> { + pin_as_deref_mut(self).poll_write(cx, buf) + } + + fn poll_write_vectored( + self: Pin<&mut Self>, + cx: &mut Context<'_>, + bufs: &[std::io::IoSlice<'_>], + ) -> Poll> { + pin_as_deref_mut(self).poll_write_vectored(cx, bufs) + } + + fn is_write_vectored(&self) -> bool { + (**self).is_write_vectored() + } + + fn poll_flush(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll> { + pin_as_deref_mut(self).poll_flush(cx) + } + + fn poll_shutdown(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll> { + pin_as_deref_mut(self).poll_shutdown(cx) + } +} + +/// Polyfill for Pin::as_deref_mut() +/// TODO: use Pin::as_deref_mut() instead once stabilized +fn pin_as_deref_mut(pin: Pin<&mut Pin

>) -> Pin<&mut P::Target> { + // SAFETY: we go directly from Pin<&mut Pin

> to Pin<&mut P::Target>, without moving or + // giving out the &mut Pin

in the process. See Pin::as_deref_mut() for more detail. + unsafe { pin.get_unchecked_mut() }.as_mut() +}