about summary refs log tree commit diff
diff options
context:
space:
mode:
authorIbraheem Ahmed <ibrah1440@gmail.com>2021-10-07 15:47:28 -0400
committerIbraheem Ahmed <ibrah1440@gmail.com>2021-10-07 15:47:28 -0400
commita57c18b5e182f32218ace2620163d86b9412182d (patch)
tree974b96bf9a703bda1cb6a32ed9777f6217f49dce
parent0157cc977fd71297ce73e2f249321f5ba2555d42 (diff)
downloadrust-a57c18b5e182f32218ace2620163d86b9412182d.tar.gz
rust-a57c18b5e182f32218ace2620163d86b9412182d.zip
add `Poll::ready`
-rw-r--r--library/core/src/task/mod.rs2
-rw-r--r--library/core/src/task/poll.rs33
-rw-r--r--library/core/src/task/ready.rs57
3 files changed, 92 insertions, 0 deletions
diff --git a/library/core/src/task/mod.rs b/library/core/src/task/mod.rs
index 5f077f77bbc..a872320aca6 100644
--- a/library/core/src/task/mod.rs
+++ b/library/core/src/task/mod.rs
@@ -13,3 +13,5 @@ pub use self::wake::{Context, RawWaker, RawWakerVTable, Waker};
 mod ready;
 #[stable(feature = "ready_macro", since = "1.56.0")]
 pub use ready::ready;
+#[unstable(feature = "poll_ready", issue = "none")]
+pub use ready::Ready;
diff --git a/library/core/src/task/poll.rs b/library/core/src/task/poll.rs
index 57416aeb701..924c424548f 100644
--- a/library/core/src/task/poll.rs
+++ b/library/core/src/task/poll.rs
@@ -3,6 +3,7 @@
 use crate::convert;
 use crate::ops::{self, ControlFlow};
 use crate::result::Result;
+use crate::task::Ready;
 
 /// Indicates whether a value is available or if the current task has been
 /// scheduled to receive a wakeup instead.
@@ -92,6 +93,38 @@ impl<T> Poll<T> {
     pub const fn is_pending(&self) -> bool {
         !self.is_ready()
     }
+
+    /// Extracts the successful type of a [`Poll<T>`].
+    ///
+    /// When combined with the `?` operator, this function will
+    /// propogate any [`Poll::Pending`] values to the caller, and
+    /// extract the `T` from [`Poll::Ready`].
+    ///
+    /// # Examples
+    ///
+    /// ```rust
+    /// #![feature(poll_ready)]
+    ///
+    /// use std::task::{Context, Poll};
+    /// use std::future::{self, Future};
+    /// use std::pin::Pin;
+    ///
+    /// pub fn do_poll(cx: &mut Context<'_>) -> Poll<()> {
+    ///     let mut fut = future::ready(42);
+    ///     let fut = Pin::new(&mut fut);
+    ///
+    ///     let num = fut.poll(cx).ready()?;
+    ///     # drop(num);
+    ///     // ... use num
+    ///
+    ///     Poll::Ready(())
+    /// }
+    /// ```
+    #[inline]
+    #[unstable(feature = "poll_ready", issue = "none")]
+    pub fn ready(self) -> Ready<T> {
+        Ready(self)
+    }
 }
 
 impl<T, E> Poll<Result<T, E>> {
diff --git a/library/core/src/task/ready.rs b/library/core/src/task/ready.rs
index 2834ca5fe22..8b6e259134e 100644
--- a/library/core/src/task/ready.rs
+++ b/library/core/src/task/ready.rs
@@ -1,3 +1,8 @@
+use core::convert;
+use core::fmt;
+use core::ops::{ControlFlow, FromResidual, Try};
+use core::task::Poll;
+
 /// Extracts the successful type of a [`Poll<T>`].
 ///
 /// This macro bakes in propagation of [`Pending`] signals by returning early.
@@ -55,3 +60,55 @@ pub macro ready($e:expr) {
         }
     }
 }
+
+/// Extracts the successful type of a [`Poll<T>`].
+///
+/// See [`Poll::ready`] for details.
+#[unstable(feature = "poll_ready", issue = "none")]
+pub struct Ready<T>(pub(crate) Poll<T>);
+
+#[unstable(feature = "poll_ready", issue = "none")]
+impl<T> Try for Ready<T> {
+    type Output = T;
+    type Residual = Ready<convert::Infallible>;
+
+    #[inline]
+    fn from_output(output: Self::Output) -> Self {
+        Ready(Poll::Ready(output))
+    }
+
+    #[inline]
+    fn branch(self) -> ControlFlow<Self::Residual, Self::Output> {
+        match self.0 {
+            Poll::Ready(v) => ControlFlow::Continue(v),
+            Poll::Pending => ControlFlow::Break(Ready(Poll::Pending)),
+        }
+    }
+}
+
+#[unstable(feature = "poll_ready", issue = "none")]
+impl<T> FromResidual for Ready<T> {
+    #[inline]
+    fn from_residual(residual: Ready<convert::Infallible>) -> Self {
+        match residual.0 {
+            Poll::Pending => Ready(Poll::Pending),
+        }
+    }
+}
+
+#[unstable(feature = "poll_ready", issue = "none")]
+impl<T> FromResidual<Ready<convert::Infallible>> for Poll<T> {
+    #[inline]
+    fn from_residual(residual: Ready<convert::Infallible>) -> Self {
+        match residual.0 {
+            Poll::Pending => Poll::Pending,
+        }
+    }
+}
+
+#[unstable(feature = "poll_ready", issue = "none")]
+impl<T> fmt::Debug for Ready<T> {
+    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+        f.debug_tuple("Ready").finish()
+    }
+}