Skip to content

Commit 62374ee

Browse files
authored
Rollup merge of #70834 - yoshuawuyts:future-pending-ready, r=sfackler
Add core::future::{pending,ready} Adds two future constructors to `core`: `future::ready` and `future::pending`. These functions enable constructing futures of any type that either immediately resolve, or never resolve which is an incredible useful tool when writing documentation. These functions have prior art in both the `futures` and `async-std` crates. This implementation has been adapted from the `futures` crate. ## Examples In #70817 we propose adding the `ready!` macro. In the example we use an `async fn` which does not return a future that implements `Unpin`, which leads to the use of `unsafe`. Instead had we had `future::ready` available, we could've written the same example without using `unsafe`: ```rust use core::task::{Context, Poll}; use core::future::{self, Future}; use core::pin::Pin; pub fn do_poll(cx: &mut Context<'_>) -> Poll<()> { let mut fut = future::ready(42_u8); let num = ready!(Pin::new(fut).poll(cx)); // ... use num Poll::Ready(()) } ``` ## Why future::ready? Arguably `future::ready` and `async {}` can be considered equivalent. The main differences are that `future::ready` returns a future that implements `Unpin`, and the returned future is a concrete type. This is useful for traits that require a future as an associated type that can sometimes be a no-op ([example](https://docs.rs/http-service/0.4.0/http_service/trait.HttpService.html#associatedtype.ConnectionFuture)). The final, minor argument is that `future::ready` and `future::pending` form a counterpart to the enum members of `Poll`: `Ready` and `Pending`. These functions form a conceptual bridge between `Poll` and `Future`, and can be used as a useful teaching device. ## References - [`futures::future::ready`](https://docs.rs/futures/0.3.4/futures/future/fn.ready.html) - [`futures::future::pending`](https://docs.rs/futures/0.3.4/futures/future/fn.pending.html) - [`async_std::future::pending`](https://docs.rs/async-std/1.5.0/async_std/future/fn.pending.html) - [`async_std::future::ready`](https://docs.rs/async-std/1.5.0/async_std/future/fn.ready.html)
2 parents 7ebd87a + 029515d commit 62374ee

File tree

3 files changed

+110
-0
lines changed

3 files changed

+110
-0
lines changed

src/libcore/future/mod.rs

+8
Original file line numberDiff line numberDiff line change
@@ -10,9 +10,17 @@ use crate::{
1010
};
1111

1212
mod future;
13+
mod pending;
14+
mod ready;
15+
1316
#[stable(feature = "futures_api", since = "1.36.0")]
1417
pub use self::future::Future;
1518

19+
#[unstable(feature = "future_readiness_fns", issue = "70921")]
20+
pub use pending::{pending, Pending};
21+
#[unstable(feature = "future_readiness_fns", issue = "70921")]
22+
pub use ready::{ready, Ready};
23+
1624
/// This type is needed because:
1725
///
1826
/// a) Generators cannot implement `for<'a, 'b> Generator<&'a mut Context<'b>>`, so we need to pass

src/libcore/future/pending.rs

+57
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,57 @@
1+
use crate::future::Future;
2+
use crate::marker;
3+
use crate::pin::Pin;
4+
use crate::task::{Context, Poll};
5+
6+
/// Creates a future which never resolves, representing a computation that never
7+
/// finishes.
8+
///
9+
/// This `struct` is created by the [`pending`] function. See its
10+
/// documentation for more.
11+
///
12+
/// [`pending`]: fn.pending.html
13+
#[unstable(feature = "future_readiness_fns", issue = "70921")]
14+
#[derive(Debug)]
15+
#[must_use = "futures do nothing unless you `.await` or poll them"]
16+
pub struct Pending<T> {
17+
_data: marker::PhantomData<T>,
18+
}
19+
20+
/// Creates a future which never resolves, representing a computation that never
21+
/// finishes.
22+
///
23+
/// # Examples
24+
///
25+
/// ```no_run
26+
/// #![feature(future_readiness_fns)]
27+
/// use core::future;
28+
///
29+
/// # async fn run() {
30+
/// let future = future::pending();
31+
/// let () = future.await;
32+
/// unreachable!();
33+
/// # }
34+
/// ```
35+
#[unstable(feature = "future_readiness_fns", issue = "70921")]
36+
pub fn pending<T>() -> Pending<T> {
37+
Pending { _data: marker::PhantomData }
38+
}
39+
40+
#[unstable(feature = "future_readiness_fns", issue = "70921")]
41+
impl<T> Future for Pending<T> {
42+
type Output = T;
43+
44+
fn poll(self: Pin<&mut Self>, _: &mut Context<'_>) -> Poll<T> {
45+
Poll::Pending
46+
}
47+
}
48+
49+
#[unstable(feature = "future_readiness_fns", issue = "70921")]
50+
impl<T> Unpin for Pending<T> {}
51+
52+
#[unstable(feature = "future_readiness_fns", issue = "70921")]
53+
impl<T> Clone for Pending<T> {
54+
fn clone(&self) -> Self {
55+
pending()
56+
}
57+
}

src/libcore/future/ready.rs

+45
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
use crate::future::Future;
2+
use crate::pin::Pin;
3+
use crate::task::{Context, Poll};
4+
5+
/// Creates a future that is immediately ready with a value.
6+
///
7+
/// This `struct` is created by the [`ready`] function. See its
8+
/// documentation for more.
9+
///
10+
/// [`ready`]: fn.ready.html
11+
#[unstable(feature = "future_readiness_fns", issue = "70921")]
12+
#[derive(Debug, Clone)]
13+
#[must_use = "futures do nothing unless you `.await` or poll them"]
14+
pub struct Ready<T>(Option<T>);
15+
16+
#[unstable(feature = "future_readiness_fns", issue = "70921")]
17+
impl<T> Unpin for Ready<T> {}
18+
19+
#[unstable(feature = "future_readiness_fns", issue = "70921")]
20+
impl<T> Future for Ready<T> {
21+
type Output = T;
22+
23+
#[inline]
24+
fn poll(mut self: Pin<&mut Self>, _cx: &mut Context<'_>) -> Poll<T> {
25+
Poll::Ready(self.0.take().expect("Ready polled after completion"))
26+
}
27+
}
28+
29+
/// Creates a future that is immediately ready with a value.
30+
///
31+
/// # Examples
32+
///
33+
/// ```
34+
/// #![feature(future_readiness_fns)]
35+
/// use core::future;
36+
///
37+
/// # async fn run() {
38+
/// let a = future::ready(1);
39+
/// assert_eq!(a.await, 1);
40+
/// # }
41+
/// ```
42+
#[unstable(feature = "future_readiness_fns", issue = "70921")]
43+
pub fn ready<T>(t: T) -> Ready<T> {
44+
Ready(Some(t))
45+
}

0 commit comments

Comments
 (0)