diff options
| author | Matthias Krüger <matthias.krueger@famsik.de> | 2023-06-19 19:26:25 +0200 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2023-06-19 19:26:25 +0200 |
| commit | 663fb5a0e9c02279bd063b06235e4e8e4bd9fb50 (patch) | |
| tree | 7eae08965799b8e850d6b21e9c10f03f6dc88bb3 | |
| parent | 689511047a75a30825e367d4fd45c74604d0b15e (diff) | |
| parent | 94f7a7931c035473565c1b2ec0a6c2ffaa3b4f79 (diff) | |
| download | rust-663fb5a0e9c02279bd063b06235e4e8e4bd9fb50.tar.gz rust-663fb5a0e9c02279bd063b06235e4e8e4bd9fb50.zip | |
Rollup merge of #109970 - danielhenrymantilla:add-poll-fn-pin-clarifications, r=thomcc
[doc] `poll_fn`: explain how to `pin` captured state safely Usage of `Pin::new_unchecked(&mut …)` is dangerous with `poll_fn`, even though the `!Unpin`-infectiousness has made things smoother. Nonetheless, there are easy ways to avoid the need for any `unsafe` altogether, be it through `Box::pin`ning, or the `pin!` macro. Since the latter only works within an `async` context, showing an example artificially introducing one ought to help people navigate this subtlety with safety and confidence. ## Preview https://user-images.githubusercontent.com/9920355/230092494-da22fdcb-0b8f-4ff4-a2ac-aa7d9ead077a.mov ```@rustbot``` label +A-docs
| -rw-r--r-- | library/core/src/future/poll_fn.rs | 87 |
1 files changed, 87 insertions, 0 deletions
diff --git a/library/core/src/future/poll_fn.rs b/library/core/src/future/poll_fn.rs index 90cb797391a..d27a9dfc176 100644 --- a/library/core/src/future/poll_fn.rs +++ b/library/core/src/future/poll_fn.rs @@ -24,6 +24,93 @@ use crate::task::{Context, Poll}; /// assert_eq!(read_future.await, "Hello, World!".to_owned()); /// # } /// ``` +/// +/// ## Capturing a pinned state +/// +/// Example of a closure wrapping inner futures: +/// +/// ``` +/// # async fn run() { +/// use core::future::{self, Future}; +/// use core::task::Poll; +/// +/// /// Resolves to the first future that completes. In the event of a tie, `a` wins. +/// fn naive_select<T>( +/// a: impl Future<Output = T>, +/// b: impl Future<Output = T>, +/// ) -> impl Future<Output = T> +/// { +/// let (mut a, mut b) = (Box::pin(a), Box::pin(b)); +/// future::poll_fn(move |cx| { +/// if let Poll::Ready(r) = a.as_mut().poll(cx) { +/// Poll::Ready(r) +/// } else if let Poll::Ready(r) = b.as_mut().poll(cx) { +/// Poll::Ready(r) +/// } else { +/// Poll::Pending +/// } +/// }) +/// } +/// +/// let a = async { 42 }; +/// let b = future::pending(); +/// let v = naive_select(a, b).await; +/// assert_eq!(v, 42); +/// +/// let a = future::pending(); +/// let b = async { 27 }; +/// let v = naive_select(a, b).await; +/// assert_eq!(v, 27); +/// +/// let a = async { 42 }; +/// let b = async { 27 }; +/// let v = naive_select(a, b).await; +/// assert_eq!(v, 42); // biased towards `a` in case of tie! +/// # } +/// ``` +/// +/// This time without [`Box::pin`]ning: +/// +/// [`Box::pin`]: ../../std/boxed/struct.Box.html#method.pin +/// +/// ``` +/// # async fn run() { +/// use core::future::{self, Future}; +/// use core::pin::pin; +/// use core::task::Poll; +/// +/// /// Resolves to the first future that completes. In the event of a tie, `a` wins. +/// fn naive_select<T>( +/// a: impl Future<Output = T>, +/// b: impl Future<Output = T>, +/// ) -> impl Future<Output = T> +/// { +/// async { +/// let (mut a, mut b) = (pin!(a), pin!(b)); +/// future::poll_fn(move |cx| { +/// if let Poll::Ready(r) = a.as_mut().poll(cx) { +/// Poll::Ready(r) +/// } else if let Poll::Ready(r) = b.as_mut().poll(cx) { +/// Poll::Ready(r) +/// } else { +/// Poll::Pending +/// } +/// }).await +/// } +/// } +/// +/// let a = async { 42 }; +/// let b = future::pending(); +/// let v = naive_select(a, b).await; +/// assert_eq!(v, 42); +/// # } +/// ``` +/// +/// - Notice how, by virtue of being in an `async` context, we have been able to make the [`pin!`] +/// macro work, thereby avoiding any need for the `unsafe` +/// <code>[Pin::new_unchecked](&mut fut)</code> constructor. +/// +/// [`pin!`]: crate::pin::pin! #[stable(feature = "future_poll_fn", since = "1.64.0")] pub fn poll_fn<T, F>(f: F) -> PollFn<F> where |
