tokio/future/
poll_fn.rs

1#![allow(dead_code)]
2
3//! Definition of the `PollFn` adapter combinator.
4
5use std::fmt;
6use std::future::Future;
7use std::pin::Pin;
8use std::task::{Context, Poll};
9
10// This struct is intentionally `!Unpin` when `F` is `!Unpin`. This is to
11// mitigate the issue where rust puts noalias on mutable references to the
12// `PollFn` type if it is `Unpin`. If the closure has ownership of a future,
13// then this "leaks" and the future is affected by noalias too, which we don't
14// want.
15//
16// See this thread for more information:
17// <https://internals.rust-lang.org/t/surprising-soundness-trouble-around-pollfn/17484>
18//
19// The fact that `PollFn` is not `Unpin` when it shouldn't be is tested in
20// `tests/async_send_sync.rs`.
21
22/// Future for the [`poll_fn`] function.
23pub struct PollFn<F> {
24    f: F,
25}
26
27/// Creates a new future wrapping around a function returning [`Poll`].
28pub fn poll_fn<T, F>(f: F) -> PollFn<F>
29where
30    F: FnMut(&mut Context<'_>) -> Poll<T>,
31{
32    PollFn { f }
33}
34
35impl<F> fmt::Debug for PollFn<F> {
36    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
37        f.debug_struct("PollFn").finish()
38    }
39}
40
41impl<T, F> Future for PollFn<F>
42where
43    F: FnMut(&mut Context<'_>) -> Poll<T>,
44{
45    type Output = T;
46
47    fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<T> {
48        // Safety: We never construct a `Pin<&mut F>` anywhere, so accessing `f`
49        // mutably in an unpinned way is sound.
50        //
51        // This use of unsafe cannot be replaced with the pin-project macro
52        // because:
53        //  * If we put `#[pin]` on the field, then it gives us a `Pin<&mut F>`,
54        //    which we can't use to call the closure.
55        //  * If we don't put `#[pin]` on the field, then it makes `PollFn` be
56        //    unconditionally `Unpin`, which we also don't want.
57        let me = unsafe { Pin::into_inner_unchecked(self) };
58        (me.f)(cx)
59    }
60}