Skip to content

Commit d82588b

Browse files
authored
Rollup merge of #72303 - yoshuawuyts:future-poll-fn, r=dtolnay
Add core::future::{poll_fn, PollFn} This is a sibling PR to #70834, adding `future::poll_fn`. This is a small helper function that helps bridge the gap between "poll state machines" and "async/await". It was first introduced in [futures@0.1.7](https://docs.rs/futures/0.1.7/futures/future/fn.poll_fn.html) in December of 2016, and has been tried and tested as part of the ecosystem for the past 3.5 years. ## Implementation Much of the same reasoning from #70834 applies: by returning a concrete struct rather than an `async fn` we get to mark the future as `Unpin`. It also becomes named which allows storing it in structs without boxing. This implementation has been modified from the implementation in `futures-rs`. ## References - [`futures::future::poll_fn`](https://docs.rs/futures/0.3.5/futures/future/fn.poll_fn.html) - [`async_std::future::poll_fn`](https://docs.rs/async-std/1.5.0/async_std/future/fn.poll_fn.html)
2 parents ec1e7e9 + a31f103 commit d82588b

File tree

2 files changed

+70
-0
lines changed

2 files changed

+70
-0
lines changed

src/libcore/future/mod.rs

+4
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ use crate::{
1212
mod future;
1313
mod into_future;
1414
mod pending;
15+
mod poll_fn;
1516
mod ready;
1617

1718
#[stable(feature = "futures_api", since = "1.36.0")]
@@ -25,6 +26,9 @@ pub use pending::{pending, Pending};
2526
#[unstable(feature = "future_readiness_fns", issue = "70921")]
2627
pub use ready::{ready, Ready};
2728

29+
#[unstable(feature = "future_poll_fn", issue = "72302")]
30+
pub use poll_fn::{poll_fn, PollFn};
31+
2832
/// This type is needed because:
2933
///
3034
/// a) Generators cannot implement `for<'a, 'b> Generator<&'a mut Context<'b>>`, so we need to pass

src/libcore/future/poll_fn.rs

+66
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,66 @@
1+
use crate::fmt;
2+
use crate::future::Future;
3+
use crate::pin::Pin;
4+
use crate::task::{Context, Poll};
5+
6+
/// Creates a future that wraps a function returning `Poll`.
7+
///
8+
/// Polling the future delegates to the wrapped function.
9+
///
10+
/// # Examples
11+
///
12+
/// ```
13+
/// #![feature(future_poll_fn)]
14+
/// # async fn run() {
15+
/// use core::future::poll_fn;
16+
/// use core::task::{Context, Poll};
17+
///
18+
/// fn read_line(_cx: &mut Context<'_>) -> Poll<String> {
19+
/// Poll::Ready("Hello, World!".into())
20+
/// }
21+
///
22+
/// let read_future = poll_fn(read_line);
23+
/// assert_eq!(read_future.await, "Hello, World!".to_owned());
24+
/// # };
25+
/// ```
26+
#[unstable(feature = "future_poll_fn", issue = "72302")]
27+
pub fn poll_fn<T, F>(f: F) -> PollFn<F>
28+
where
29+
F: FnMut(&mut Context<'_>) -> Poll<T>,
30+
{
31+
PollFn { f }
32+
}
33+
34+
/// A Future that wraps a function returning `Poll`.
35+
///
36+
/// This `struct` is created by the [`poll_fn`] function. See its
37+
/// documentation for more.
38+
///
39+
/// [`poll_fn`]: fn.poll_fn.html
40+
#[must_use = "futures do nothing unless you `.await` or poll them"]
41+
#[unstable(feature = "future_poll_fn", issue = "72302")]
42+
pub struct PollFn<F> {
43+
f: F,
44+
}
45+
46+
#[unstable(feature = "future_poll_fn", issue = "72302")]
47+
impl<F> Unpin for PollFn<F> {}
48+
49+
#[unstable(feature = "future_poll_fn", issue = "72302")]
50+
impl<F> fmt::Debug for PollFn<F> {
51+
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
52+
f.debug_struct("PollFn").finish()
53+
}
54+
}
55+
56+
#[unstable(feature = "future_poll_fn", issue = "72302")]
57+
impl<T, F> Future for PollFn<F>
58+
where
59+
F: FnMut(&mut Context<'_>) -> Poll<T>,
60+
{
61+
type Output = T;
62+
63+
fn poll(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<T> {
64+
(&mut self.f)(cx)
65+
}
66+
}

0 commit comments

Comments
 (0)