Skip to content

Commit d3984e1

Browse files
authored
Rollup merge of #89651 - ibraheemdev:poll-ready, r=dtolnay
Add `Poll::ready` and revert stabilization of `task::ready!` This PR adds an inherent `ready` method to `Poll` that can be used with the `?` operator as an alternative to the `task::ready!` macro: ```rust let val = ready!(fut.poll(cx)); let val = fut.poll(cx).ready()?; ``` I think this form is a nice, non-breaking middle ground between changing the `impl Try for Poll`, and adding a separate macro. It looks better than `ready!` in my opinion, and it composes well: ```rust let elem = ready!(fut.poll(cx)).pop().unwrap(); let elem = fut.poll(cx).ready()?.pop().unwrap(); ``` The planned stabilization of `ready!` in 1.56 has been reverted because I think this alternate approach is worth considering. r? rust-lang/libs
2 parents b80dd9e + a1e03fc commit d3984e1

File tree

4 files changed

+97
-4
lines changed

4 files changed

+97
-4
lines changed

RELEASES.md

-2
Original file line numberDiff line numberDiff line change
@@ -64,7 +64,6 @@ Stabilised APIs
6464
- [`VecDeque::shrink_to`]
6565
- [`HashMap::shrink_to`]
6666
- [`HashSet::shrink_to`]
67-
- [`task::ready!`]
6867

6968
These APIs are now usable in const contexts:
7069

@@ -128,7 +127,6 @@ and related tools.
128127
[`VecDeque::shrink_to`]: https://doc.rust-lang.org/stable/std/collections/struct.VecDeque.html#method.shrink_to
129128
[`HashMap::shrink_to`]: https://doc.rust-lang.org/stable/std/collections/hash_map/struct.HashMap.html#method.shrink_to
130129
[`HashSet::shrink_to`]: https://doc.rust-lang.org/stable/std/collections/hash_set/struct.HashSet.html#method.shrink_to
131-
[`task::ready!`]: https://doc.rust-lang.org/stable/std/task/macro.ready.html
132130
[`std::mem::transmute`]: https://doc.rust-lang.org/stable/std/mem/fn.transmute.html
133131
[`slice::first`]: https://doc.rust-lang.org/stable/std/primitive.slice.html#method.first
134132
[`slice::split_first`]: https://doc.rust-lang.org/stable/std/primitive.slice.html#method.split_first

library/core/src/task/mod.rs

+3-1
Original file line numberDiff line numberDiff line change
@@ -11,5 +11,7 @@ mod wake;
1111
pub use self::wake::{Context, RawWaker, RawWakerVTable, Waker};
1212

1313
mod ready;
14-
#[stable(feature = "ready_macro", since = "1.56.0")]
14+
#[unstable(feature = "ready_macro", issue = "70922")]
1515
pub use ready::ready;
16+
#[unstable(feature = "poll_ready", issue = "89780")]
17+
pub use ready::Ready;

library/core/src/task/poll.rs

+33
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
use crate::convert;
44
use crate::ops::{self, ControlFlow};
55
use crate::result::Result;
6+
use crate::task::Ready;
67

78
/// Indicates whether a value is available or if the current task has been
89
/// scheduled to receive a wakeup instead.
@@ -92,6 +93,38 @@ impl<T> Poll<T> {
9293
pub const fn is_pending(&self) -> bool {
9394
!self.is_ready()
9495
}
96+
97+
/// Extracts the successful type of a [`Poll<T>`].
98+
///
99+
/// When combined with the `?` operator, this function will
100+
/// propogate any [`Poll::Pending`] values to the caller, and
101+
/// extract the `T` from [`Poll::Ready`].
102+
///
103+
/// # Examples
104+
///
105+
/// ```rust
106+
/// #![feature(poll_ready)]
107+
///
108+
/// use std::task::{Context, Poll};
109+
/// use std::future::{self, Future};
110+
/// use std::pin::Pin;
111+
///
112+
/// pub fn do_poll(cx: &mut Context<'_>) -> Poll<()> {
113+
/// let mut fut = future::ready(42);
114+
/// let fut = Pin::new(&mut fut);
115+
///
116+
/// let num = fut.poll(cx).ready()?;
117+
/// # drop(num);
118+
/// // ... use num
119+
///
120+
/// Poll::Ready(())
121+
/// }
122+
/// ```
123+
#[inline]
124+
#[unstable(feature = "poll_ready", issue = "89780")]
125+
pub fn ready(self) -> Ready<T> {
126+
Ready(self)
127+
}
95128
}
96129

97130
impl<T, E> Poll<Result<T, E>> {

library/core/src/task/ready.rs

+61-1
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,8 @@
1+
use core::convert;
2+
use core::fmt;
3+
use core::ops::{ControlFlow, FromResidual, Try};
4+
use core::task::Poll;
5+
16
/// Extracts the successful type of a [`Poll<T>`].
27
///
38
/// This macro bakes in propagation of [`Pending`] signals by returning early.
@@ -8,6 +13,8 @@
813
/// # Examples
914
///
1015
/// ```
16+
/// #![feature(ready_macro)]
17+
///
1118
/// use std::task::{ready, Context, Poll};
1219
/// use std::future::{self, Future};
1320
/// use std::pin::Pin;
@@ -27,6 +34,7 @@
2734
/// The `ready!` call expands to:
2835
///
2936
/// ```
37+
/// # #![feature(ready_macro)]
3038
/// # use std::task::{Context, Poll};
3139
/// # use std::future::{self, Future};
3240
/// # use std::pin::Pin;
@@ -45,7 +53,7 @@
4553
/// # Poll::Ready(())
4654
/// # }
4755
/// ```
48-
#[stable(feature = "ready_macro", since = "1.56.0")]
56+
#[unstable(feature = "ready_macro", issue = "70922")]
4957
#[rustc_macro_transparency = "semitransparent"]
5058
pub macro ready($e:expr) {
5159
match $e {
@@ -55,3 +63,55 @@ pub macro ready($e:expr) {
5563
}
5664
}
5765
}
66+
67+
/// Extracts the successful type of a [`Poll<T>`].
68+
///
69+
/// See [`Poll::ready`] for details.
70+
#[unstable(feature = "poll_ready", issue = "89780")]
71+
pub struct Ready<T>(pub(crate) Poll<T>);
72+
73+
#[unstable(feature = "poll_ready", issue = "89780")]
74+
impl<T> Try for Ready<T> {
75+
type Output = T;
76+
type Residual = Ready<convert::Infallible>;
77+
78+
#[inline]
79+
fn from_output(output: Self::Output) -> Self {
80+
Ready(Poll::Ready(output))
81+
}
82+
83+
#[inline]
84+
fn branch(self) -> ControlFlow<Self::Residual, Self::Output> {
85+
match self.0 {
86+
Poll::Ready(v) => ControlFlow::Continue(v),
87+
Poll::Pending => ControlFlow::Break(Ready(Poll::Pending)),
88+
}
89+
}
90+
}
91+
92+
#[unstable(feature = "poll_ready", issue = "89780")]
93+
impl<T> FromResidual for Ready<T> {
94+
#[inline]
95+
fn from_residual(residual: Ready<convert::Infallible>) -> Self {
96+
match residual.0 {
97+
Poll::Pending => Ready(Poll::Pending),
98+
}
99+
}
100+
}
101+
102+
#[unstable(feature = "poll_ready", issue = "89780")]
103+
impl<T> FromResidual<Ready<convert::Infallible>> for Poll<T> {
104+
#[inline]
105+
fn from_residual(residual: Ready<convert::Infallible>) -> Self {
106+
match residual.0 {
107+
Poll::Pending => Poll::Pending,
108+
}
109+
}
110+
}
111+
112+
#[unstable(feature = "poll_ready", issue = "89780")]
113+
impl<T> fmt::Debug for Ready<T> {
114+
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
115+
f.debug_tuple("Ready").finish()
116+
}
117+
}

0 commit comments

Comments
 (0)