From 17d78c4ef922f81e752feb077d66fbce80630c6c Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Thu, 6 Oct 2022 13:36:07 +0200 Subject: [PATCH] poll_fn and Unpin: fix pinning --- library/core/src/future/poll_fn.rs | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/library/core/src/future/poll_fn.rs b/library/core/src/future/poll_fn.rs index db2a523323b7a..90cb797391a08 100644 --- a/library/core/src/future/poll_fn.rs +++ b/library/core/src/future/poll_fn.rs @@ -5,7 +5,9 @@ use crate::task::{Context, Poll}; /// Creates a future that wraps a function returning [`Poll`]. /// -/// Polling the future delegates to the wrapped function. +/// Polling the future delegates to the wrapped function. If the returned future is pinned, then the +/// captured environment of the wrapped function is also pinned in-place, so as long as the closure +/// does not move out of its captures it can soundly create pinned references to them. /// /// # Examples /// @@ -41,7 +43,7 @@ pub struct PollFn { } #[stable(feature = "future_poll_fn", since = "1.64.0")] -impl Unpin for PollFn {} +impl Unpin for PollFn {} #[stable(feature = "future_poll_fn", since = "1.64.0")] impl fmt::Debug for PollFn { @@ -57,7 +59,8 @@ where { type Output = T; - fn poll(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll { - (&mut self.f)(cx) + fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll { + // SAFETY: We are not moving out of the pinned field. + (unsafe { &mut self.get_unchecked_mut().f })(cx) } }