From 402e999bcc2989ad7c64605b4a46a0ea7af52174 Mon Sep 17 00:00:00 2001 From: Yoshua Wuyts Date: Sat, 12 Oct 2019 01:15:18 +0200 Subject: [PATCH 1/4] init FutureExt Signed-off-by: Yoshua Wuyts --- src/fs/dir_builder.rs | 3 +- src/fs/open_options.rs | 3 +- src/future/future.rs | 104 +++++++++++++++++++++++++++++++++++++++ src/future/mod.rs | 5 +- src/stream/stream/mod.rs | 2 +- src/task/blocking.rs | 2 +- src/task/mod.rs | 2 +- src/task/pool.rs | 2 +- src/task/task.rs | 2 +- src/task/task_local.rs | 2 +- 10 files changed, 115 insertions(+), 12 deletions(-) create mode 100644 src/future/future.rs diff --git a/src/fs/dir_builder.rs b/src/fs/dir_builder.rs index 1fb085021..912233d7f 100644 --- a/src/fs/dir_builder.rs +++ b/src/fs/dir_builder.rs @@ -1,6 +1,5 @@ -use cfg_if::cfg_if; +use std::future::Future; -use crate::future::Future; use crate::io; use crate::path::Path; use crate::task::blocking; diff --git a/src/fs/open_options.rs b/src/fs/open_options.rs index d7e0454f4..c1931fa02 100644 --- a/src/fs/open_options.rs +++ b/src/fs/open_options.rs @@ -1,7 +1,8 @@ +use std::future::Future; + use cfg_if::cfg_if; use crate::fs::File; -use crate::future::Future; use crate::io; use crate::path::Path; use crate::task::blocking; diff --git a/src/future/future.rs b/src/future/future.rs new file mode 100644 index 000000000..9c8b0893e --- /dev/null +++ b/src/future/future.rs @@ -0,0 +1,104 @@ +use crate::utils::extension_trait; + +cfg_if::cfg_if! { + if #[cfg(feature = "docs")] { + use crate::task::{Context, Poll}; + use std::pin::Pin; + } +} + +extension_trait! { + #[doc = r#" + A future represents an asynchronous computation. + + A future is a value that may not have finished computing yet. This kind of + "asynchronous value" makes it possible for a thread to continue doing useful + work while it waits for the value to become available. + + # The `poll` method + + The core method of future, `poll`, *attempts* to resolve the future into a + final value. This method does not block if the value is not ready. Instead, + the current task is scheduled to be woken up when it's possible to make + further progress by `poll`ing again. The `context` passed to the `poll` + method can provide a [`Waker`], which is a handle for waking up the current + task. + + When using a future, you generally won't call `poll` directly, but instead + `.await` the value. + + [`Waker`]: ../task/struct.Waker.html + "#] + pub trait Future [FutureExt: std::future::Future] { + #[doc = r#" + The type of value produced on completion. + "#] + type Output; + + #[doc = r#" + Attempt to resolve the future to a final value, registering + the current task for wakeup if the value is not yet available. + + # Return value + + This function returns: + + - [`Poll::Pending`] if the future is not ready yet + - [`Poll::Ready(val)`] with the result `val` of this future if it + finished successfully. + + Once a future has finished, clients should not `poll` it again. + + When a future is not ready yet, `poll` returns `Poll::Pending` and + stores a clone of the [`Waker`] copied from the current [`Context`]. + This [`Waker`] is then woken once the future can make progress. + For example, a future waiting for a socket to become + readable would call `.clone()` on the [`Waker`] and store it. + When a signal arrives elsewhere indicating that the socket is readable, + [`Waker::wake`] is called and the socket future's task is awoken. + Once a task has been woken up, it should attempt to `poll` the future + again, which may or may not produce a final value. + + Note that on multiple calls to `poll`, only the [`Waker`] from the + [`Context`] passed to the most recent call should be scheduled to + receive a wakeup. + + # Runtime characteristics + + Futures alone are *inert*; they must be *actively* `poll`ed to make + progress, meaning that each time the current task is woken up, it should + actively re-`poll` pending futures that it still has an interest in. + + The `poll` function is not called repeatedly in a tight loop -- instead, + it should only be called when the future indicates that it is ready to + make progress (by calling `wake()`). If you're familiar with the + `poll(2)` or `select(2)` syscalls on Unix it's worth noting that futures + typically do *not* suffer the same problems of "all wakeups must poll + all events"; they are more like `epoll(4)`. + + An implementation of `poll` should strive to return quickly, and should + not block. Returning quickly prevents unnecessarily clogging up + threads or event loops. If it is known ahead of time that a call to + `poll` may end up taking awhile, the work should be offloaded to a + thread pool (or something similar) to ensure that `poll` can return + quickly. + + # Panics + + Once a future has completed (returned `Ready` from `poll`), calling its + `poll` method again may panic, block forever, or cause other kinds of + problems; the `Future` trait places no requirements on the effects of + such a call. However, as the `poll` method is not marked `unsafe`, + Rust's usual rules apply: calls must never cause undefined behavior + (memory corruption, incorrect use of `unsafe` functions, or the like), + regardless of the future's state. + + [`Poll::Pending`]: ../task/enum.Poll.html#variant.Pending + [`Poll::Ready(val)`]: ../task/enum.Poll.html#variant.Ready + [`Context`]: ../task/struct.Context.html + [`Waker`]: ../task/struct.Waker.html + [`Waker::wake`]: ../task/struct.Waker.html#method.wake + "#] + fn poll(self: Pin<&mut Self>, cx: &mut Context) -> Poll; + } +} diff --git a/src/future/mod.rs b/src/future/mod.rs index dc9b46621..06d06336f 100644 --- a/src/future/mod.rs +++ b/src/future/mod.rs @@ -41,9 +41,6 @@ //! | `future::select` | `Result` | Return on first value //! | `future::try_select` | `Result` | Return on first `Ok`, reject on last Err -#[doc(inline)] -pub use std::future::Future; - #[doc(inline)] pub use async_macros::{join, try_join}; @@ -53,10 +50,12 @@ pub use async_macros::{select, try_select}; use cfg_if::cfg_if; +pub use future::Future; pub use pending::pending; pub use poll_fn::poll_fn; pub use ready::ready; +pub(crate) mod future; mod pending; mod poll_fn; mod ready; diff --git a/src/stream/stream/mod.rs b/src/stream/stream/mod.rs index 0e563f6d3..449674998 100644 --- a/src/stream/stream/mod.rs +++ b/src/stream/stream/mod.rs @@ -95,7 +95,7 @@ cfg_if! { use std::pin::Pin; - use crate::future::Future; + use std::future::Future; use crate::stream::FromStream; pub use merge::Merge; diff --git a/src/task/blocking.rs b/src/task/blocking.rs index 53b52c82a..fff14ed5b 100644 --- a/src/task/blocking.rs +++ b/src/task/blocking.rs @@ -1,5 +1,6 @@ //! A thread pool for running blocking functions asynchronously. +use std::future::Future; use std::sync::atomic::{AtomicU64, Ordering}; use std::thread; use std::time::Duration; @@ -7,7 +8,6 @@ use std::time::Duration; use crossbeam_channel::{bounded, Receiver, Sender}; use lazy_static::lazy_static; -use crate::future::Future; use crate::task::task::{JoinHandle, Tag}; use crate::utils::abort_on_panic; diff --git a/src/task/mod.rs b/src/task/mod.rs index 727dc5938..e1b75ffe3 100644 --- a/src/task/mod.rs +++ b/src/task/mod.rs @@ -86,7 +86,7 @@ cfg_if::cfg_if! { #[inline] pub fn blocking(future: F) -> task::JoinHandle where - F: crate::future::Future + Send + 'static, + F: std::future::Future + Send + 'static, R: Send + 'static, { blocking::spawn(future) diff --git a/src/task/pool.rs b/src/task/pool.rs index bfaa17d48..3c359ed31 100644 --- a/src/task/pool.rs +++ b/src/task/pool.rs @@ -1,3 +1,4 @@ +use std::future::Future; use std::iter; use std::thread; @@ -10,7 +11,6 @@ use super::task; use super::task_local; use super::worker; use super::{Builder, JoinHandle}; -use crate::future::Future; use crate::utils::abort_on_panic; /// Spawns a task. diff --git a/src/task/task.rs b/src/task/task.rs index 5100af44b..ca3cac142 100644 --- a/src/task/task.rs +++ b/src/task/task.rs @@ -1,4 +1,5 @@ use std::fmt; +use std::future::Future; use std::i64; use std::mem; use std::num::NonZeroU64; @@ -7,7 +8,6 @@ use std::sync::atomic::{AtomicU64, AtomicUsize, Ordering}; use std::sync::Arc; use super::task_local; -use crate::future::Future; use crate::task::{Context, Poll}; /// A handle to a task. diff --git a/src/task/task_local.rs b/src/task/task_local.rs index 8347e34b6..9198e4a21 100644 --- a/src/task/task_local.rs +++ b/src/task/task_local.rs @@ -7,8 +7,8 @@ use std::sync::Mutex; use lazy_static::lazy_static; use super::worker; -use crate::future::Future; use crate::utils::abort_on_panic; +use std::future::Future; /// Declares task-local values. /// From e2db765e41fde960c6248b4f622b4df7b21e69f8 Mon Sep 17 00:00:00 2001 From: Yoshua Wuyts Date: Sat, 12 Oct 2019 01:19:04 +0200 Subject: [PATCH 2/4] prelude Signed-off-by: Yoshua Wuyts --- src/prelude.rs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/prelude.rs b/src/prelude.rs index f808da061..6c670cc7b 100644 --- a/src/prelude.rs +++ b/src/prelude.rs @@ -28,6 +28,8 @@ pub use crate::stream::Stream; #[doc(no_inline)] pub use crate::task_local; +#[doc(hidden)] +pub use crate::future::future::FutureExt as _; #[doc(hidden)] pub use crate::io::buf_read::BufReadExt as _; #[doc(hidden)] From c78dbdd6f264344cb01724f2331d620744c1c8da Mon Sep 17 00:00:00 2001 From: Stjepan Glavina Date: Mon, 14 Oct 2019 18:41:53 +0200 Subject: [PATCH 3/4] Refactor extension_trait Signed-off-by: Yoshua Wuyts --- src/fs/dir_builder.rs | 2 ++ src/future/future.rs | 5 +++- src/io/buf_read/mod.rs | 4 ++- src/io/read/mod.rs | 4 ++- src/io/seek.rs | 6 ++-- src/io/write/mod.rs | 4 ++- src/stream/stream/mod.rs | 6 ++-- src/task/blocking.rs | 2 +- src/task/mod.rs | 2 +- src/task/pool.rs | 2 +- src/task/task.rs | 2 +- src/task/task_local.rs | 2 +- src/utils.rs | 62 +++++++++++----------------------------- 13 files changed, 45 insertions(+), 58 deletions(-) diff --git a/src/fs/dir_builder.rs b/src/fs/dir_builder.rs index 912233d7f..209624b37 100644 --- a/src/fs/dir_builder.rs +++ b/src/fs/dir_builder.rs @@ -1,5 +1,7 @@ use std::future::Future; +use cfg_if::cfg_if; + use crate::io; use crate::path::Path; use crate::task::blocking; diff --git a/src/future/future.rs b/src/future/future.rs index 9c8b0893e..689ccabca 100644 --- a/src/future/future.rs +++ b/src/future/future.rs @@ -29,7 +29,7 @@ extension_trait! { [`Waker`]: ../task/struct.Waker.html "#] - pub trait Future [FutureExt: std::future::Future] { + pub trait Future { #[doc = r#" The type of value produced on completion. "#] @@ -101,4 +101,7 @@ extension_trait! { "#] fn poll(self: Pin<&mut Self>, cx: &mut Context) -> Poll; } + + pub trait FutureExt: std::future::Future { + } } diff --git a/src/io/buf_read/mod.rs b/src/io/buf_read/mod.rs index 987522b93..dff10fab0 100644 --- a/src/io/buf_read/mod.rs +++ b/src/io/buf_read/mod.rs @@ -44,7 +44,7 @@ extension_trait! { https://docs.rs/futures-preview/0.3.0-alpha.17/futures/io/trait.AsyncBufRead.html [provided methods]: #provided-methods "#] - pub trait BufRead [BufReadExt: futures_io::AsyncBufRead] { + pub trait BufRead { #[doc = r#" Returns the contents of the internal buffer, filling it with more data from the inner reader if it is empty. @@ -67,7 +67,9 @@ extension_trait! { should no longer be returned in calls to `read`. "#] fn consume(self: Pin<&mut Self>, amt: usize); + } + pub trait BufReadExt: futures_io::AsyncBufRead { #[doc = r#" Reads all bytes into `buf` until the delimiter `byte` or EOF is reached. diff --git a/src/io/read/mod.rs b/src/io/read/mod.rs index 6fd95c120..40cb3ca0f 100644 --- a/src/io/read/mod.rs +++ b/src/io/read/mod.rs @@ -50,7 +50,7 @@ extension_trait! { [`poll_read`]: #tymethod.poll_read [`poll_read_vectored`]: #method.poll_read_vectored "#] - pub trait Read [ReadExt: futures_io::AsyncRead] { + pub trait Read { #[doc = r#" Attempt to read from the `AsyncRead` into `buf`. "#] @@ -70,7 +70,9 @@ extension_trait! { ) -> Poll> { unreachable!("this impl only appears in the rendered docs") } + } + pub trait ReadExt: futures_io::AsyncRead { #[doc = r#" Reads some bytes from the byte stream. diff --git a/src/io/seek.rs b/src/io/seek.rs index 274eee736..2d1c4d377 100644 --- a/src/io/seek.rs +++ b/src/io/seek.rs @@ -33,7 +33,7 @@ extension_trait! { https://docs.rs/futures-preview/0.3.0-alpha.17/futures/io/trait.AsyncSeek.html [provided methods]: #provided-methods "#] - pub trait Seek [SeekExt: futures_io::AsyncSeek] { + pub trait Seek { #[doc = r#" Attempt to seek to an offset, in bytes, in a stream. "#] @@ -42,7 +42,9 @@ extension_trait! { cx: &mut Context<'_>, pos: SeekFrom, ) -> Poll>; + } + pub trait SeekExt: futures_io::AsyncSeek { #[doc = r#" Seeks to a new position in a byte stream. @@ -70,7 +72,7 @@ extension_trait! { fn seek( &mut self, pos: SeekFrom, - ) -> impl Future> [SeekFuture<'_, Self>] + ) -> impl Future> + '_ [SeekFuture<'_, Self>] where Self: Unpin, { diff --git a/src/io/write/mod.rs b/src/io/write/mod.rs index 7914ccc82..be69b7e2d 100644 --- a/src/io/write/mod.rs +++ b/src/io/write/mod.rs @@ -49,7 +49,7 @@ extension_trait! { [`poll_flush`]: #tymethod.poll_flush [`poll_close`]: #tymethod.poll_close "#] - pub trait Write [WriteExt: futures_io::AsyncWrite] { + pub trait Write { #[doc = r#" Attempt to write bytes from `buf` into the object. "#] @@ -80,7 +80,9 @@ extension_trait! { Attempt to close the object. "#] fn poll_close(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll>; + } + pub trait WriteExt: futures_io::AsyncWrite { #[doc = r#" Writes some bytes into the byte stream. diff --git a/src/stream/stream/mod.rs b/src/stream/stream/mod.rs index 449674998..2ee01d78a 100644 --- a/src/stream/stream/mod.rs +++ b/src/stream/stream/mod.rs @@ -95,7 +95,7 @@ cfg_if! { use std::pin::Pin; - use std::future::Future; + use crate::future::Future; use crate::stream::FromStream; pub use merge::Merge; @@ -122,7 +122,7 @@ extension_trait! { https://docs.rs/futures-preview/0.3.0-alpha.17/futures/stream/trait.Stream.html [provided methods]: #provided-methods "#] - pub trait Stream [StreamExt: futures_core::stream::Stream] { + pub trait Stream { #[doc = r#" The type of items yielded by this stream. "#] @@ -180,7 +180,9 @@ extension_trait! { ``` "#] fn poll_next(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll>; + } + pub trait StreamExt: futures_core::stream::Stream { #[doc = r#" Advances the stream and returns the next value. diff --git a/src/task/blocking.rs b/src/task/blocking.rs index fff14ed5b..53b52c82a 100644 --- a/src/task/blocking.rs +++ b/src/task/blocking.rs @@ -1,6 +1,5 @@ //! A thread pool for running blocking functions asynchronously. -use std::future::Future; use std::sync::atomic::{AtomicU64, Ordering}; use std::thread; use std::time::Duration; @@ -8,6 +7,7 @@ use std::time::Duration; use crossbeam_channel::{bounded, Receiver, Sender}; use lazy_static::lazy_static; +use crate::future::Future; use crate::task::task::{JoinHandle, Tag}; use crate::utils::abort_on_panic; diff --git a/src/task/mod.rs b/src/task/mod.rs index e1b75ffe3..727dc5938 100644 --- a/src/task/mod.rs +++ b/src/task/mod.rs @@ -86,7 +86,7 @@ cfg_if::cfg_if! { #[inline] pub fn blocking(future: F) -> task::JoinHandle where - F: std::future::Future + Send + 'static, + F: crate::future::Future + Send + 'static, R: Send + 'static, { blocking::spawn(future) diff --git a/src/task/pool.rs b/src/task/pool.rs index 3c359ed31..bfaa17d48 100644 --- a/src/task/pool.rs +++ b/src/task/pool.rs @@ -1,4 +1,3 @@ -use std::future::Future; use std::iter; use std::thread; @@ -11,6 +10,7 @@ use super::task; use super::task_local; use super::worker; use super::{Builder, JoinHandle}; +use crate::future::Future; use crate::utils::abort_on_panic; /// Spawns a task. diff --git a/src/task/task.rs b/src/task/task.rs index ca3cac142..5100af44b 100644 --- a/src/task/task.rs +++ b/src/task/task.rs @@ -1,5 +1,4 @@ use std::fmt; -use std::future::Future; use std::i64; use std::mem; use std::num::NonZeroU64; @@ -8,6 +7,7 @@ use std::sync::atomic::{AtomicU64, AtomicUsize, Ordering}; use std::sync::Arc; use super::task_local; +use crate::future::Future; use crate::task::{Context, Poll}; /// A handle to a task. diff --git a/src/task/task_local.rs b/src/task/task_local.rs index 9198e4a21..8347e34b6 100644 --- a/src/task/task_local.rs +++ b/src/task/task_local.rs @@ -7,8 +7,8 @@ use std::sync::Mutex; use lazy_static::lazy_static; use super::worker; +use crate::future::Future; use crate::utils::abort_on_panic; -use std::future::Future; /// Declares task-local values. /// diff --git a/src/utils.rs b/src/utils.rs index bdf0f3b5d..cfbfce353 100644 --- a/src/utils.rs +++ b/src/utils.rs @@ -36,9 +36,13 @@ macro_rules! extension_trait { // - `$name`: trait name that gets rendered in the docs // - `$ext`: name of the hidden extension trait // - `$base`: base trait from the `futures` crate - $(#[$attr:meta])* - pub trait $name:ident [$ext:ident: $base:path] { - $($body:tt)* + #[doc = $doc:tt] + pub trait $name:ident { + $($body_base:tt)* + } + + pub trait $ext:ident: $base:path { + $($body_ext:tt)* } // Shim trait impls that only appear in docs. @@ -58,11 +62,11 @@ macro_rules! extension_trait { pub struct ImplFuture<'a, T>(std::marker::PhantomData<&'a T>); } - // Render a fake trait containing all methods from the base trait and the extension trait. + // Render a fake trait combining the bodies of the base trait and the extension trait. #[cfg(feature = "docs")] - $(#[$attr])* + #[doc = $doc] pub trait $name { - extension_trait!(@doc () $($body)*); + extension_trait!(@doc () $($body_base)* $($body_ext)*); } // When not rendering docs, re-export the base trait from the futures crate. @@ -70,9 +74,9 @@ macro_rules! extension_trait { pub use $base as $name; // The extension trait that adds methods to any type implementing the base trait. - $(#[$attr])* + /// Extension trait. pub trait $ext: $base { - extension_trait!(@ext () $($body)*); + extension_trait!(@ext () $($body_ext)*); } // Blanket implementation of the extension trait for any type implementing the base trait. @@ -82,47 +86,15 @@ macro_rules! extension_trait { $(#[cfg(feature = "docs")] $imp)* }; - // Parse an associated type. - (@doc ($($head:tt)*) type $name:ident; $($tail:tt)*) => { - extension_trait!(@doc ($($head)* type $name;) $($tail)*); - }; - (@ext ($($head:tt)*) type $ident:ty; $($tail:tt)*) => { - extension_trait!(@ext ($($head)*) $($tail)*); - }; - - // Parse a required method. - (@doc ($($head:tt)*) fn $name:ident $args:tt $(-> $ret:ty)?; $($tail:tt)*) => { - extension_trait!(@doc ($($head)* fn $name $args $(-> $ret)?;) $($tail)*); - }; - (@ext ($($head:tt)*) fn $name:ident $args:tt $(-> $ret:ty)?; $($tail:tt)*) => { - extension_trait!(@ext ($($head)*) $($tail)*); - }; - - // Parse a provided method that exists in the base trait. - (@doc ($($head:tt)*) fn $name:ident $args:tt $(-> $ret:ty)? { $($body:tt)* } $($tail:tt)*) => { - extension_trait!(@doc ($($head)* fn $name $args $(-> $ret)? { $($body)* }) $($tail)*); - }; - (@ext ($($head:tt)*) fn $name:ident $args:tt $(-> $ret:ty)? { $($body:tt)* } $($tail:tt)*) => { - extension_trait!(@ext ($($head)*) $($tail)*); - }; - - // Parse the return type in an extension method where the future doesn't borrow. - (@doc ($($head:tt)*) -> impl Future [$f:ty] $($tail:tt)*) => { - extension_trait!(@doc ($($head)* -> owned::ImplFuture<$out>) $($tail)*); - }; - (@ext ($($head:tt)*) -> impl Future [$f:ty] $($tail:tt)*) => { - extension_trait!(@ext ($($head)* -> $f) $($tail)*); - }; - - // Parse the return type in an extension method where the future borrows its environment. - (@doc ($($head:tt)*) -> impl Future + $lt:lifetime [$f:ty] $($tail:tt)*) => { - extension_trait!(@doc ($($head)* -> borrowed::ImplFuture<$lt, $out>) $($tail)*); + // Parse the return type in an extension method. + (@doc ($($head:tt)*) -> impl Future $(+ $lt:lifetime)? [$f:ty] $($tail:tt)*) => { + extension_trait!(@doc ($($head)* -> borrowed::ImplFuture<$($lt,)? $out>) $($tail)*); }; - (@ext ($($head:tt)*) -> impl Future + $lt:lifetime [$f:ty] $($tail:tt)*) => { + (@ext ($($head:tt)*) -> impl Future $(+ $lt:lifetime)? [$f:ty] $($tail:tt)*) => { extension_trait!(@ext ($($head)* -> $f) $($tail)*); }; - // Parse a token that doesn't fit into any of the previous patterns. + // Parse a token. (@doc ($($head:tt)*) $token:tt $($tail:tt)*) => { extension_trait!(@doc ($($head)* $token) $($tail)*); }; From 9f2a773097427b7f8265b30659ea5cd85960ec51 Mon Sep 17 00:00:00 2001 From: Stjepan Glavina Date: Tue, 15 Oct 2019 10:10:30 +0200 Subject: [PATCH 4/4] Fix rustdoc Signed-off-by: Yoshua Wuyts --- src/future/future.rs | 40 +++++++++++++++++++++++++++++++++++++++- src/task/blocking.rs | 2 +- src/task/task.rs | 2 +- src/task/task_local.rs | 2 +- src/utils.rs | 16 ++++++++++++---- 5 files changed, 54 insertions(+), 8 deletions(-) diff --git a/src/future/future.rs b/src/future/future.rs index 689ccabca..556dc1acd 100644 --- a/src/future/future.rs +++ b/src/future/future.rs @@ -2,8 +2,10 @@ use crate::utils::extension_trait; cfg_if::cfg_if! { if #[cfg(feature = "docs")] { - use crate::task::{Context, Poll}; use std::pin::Pin; + use std::ops::{Deref, DerefMut}; + + use crate::task::{Context, Poll}; } } @@ -104,4 +106,40 @@ extension_trait! { pub trait FutureExt: std::future::Future { } + + impl Future for Box { + type Output = F::Output; + + fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll { + unreachable!("this impl only appears in the rendered docs") + } + } + + impl Future for &mut F { + type Output = F::Output; + + fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll { + unreachable!("this impl only appears in the rendered docs") + } + } + + impl

Future for Pin

+ where + P: DerefMut + Unpin, +

::Target: Future, + { + type Output = <

::Target as Future>::Output; + + fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll { + unreachable!("this impl only appears in the rendered docs") + } + } + + impl Future for std::panic::AssertUnwindSafe { + type Output = F::Output; + + fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll { + unreachable!("this impl only appears in the rendered docs") + } + } } diff --git a/src/task/blocking.rs b/src/task/blocking.rs index 53b52c82a..fff14ed5b 100644 --- a/src/task/blocking.rs +++ b/src/task/blocking.rs @@ -1,5 +1,6 @@ //! A thread pool for running blocking functions asynchronously. +use std::future::Future; use std::sync::atomic::{AtomicU64, Ordering}; use std::thread; use std::time::Duration; @@ -7,7 +8,6 @@ use std::time::Duration; use crossbeam_channel::{bounded, Receiver, Sender}; use lazy_static::lazy_static; -use crate::future::Future; use crate::task::task::{JoinHandle, Tag}; use crate::utils::abort_on_panic; diff --git a/src/task/task.rs b/src/task/task.rs index 5100af44b..ca3cac142 100644 --- a/src/task/task.rs +++ b/src/task/task.rs @@ -1,4 +1,5 @@ use std::fmt; +use std::future::Future; use std::i64; use std::mem; use std::num::NonZeroU64; @@ -7,7 +8,6 @@ use std::sync::atomic::{AtomicU64, AtomicUsize, Ordering}; use std::sync::Arc; use super::task_local; -use crate::future::Future; use crate::task::{Context, Poll}; /// A handle to a task. diff --git a/src/task/task_local.rs b/src/task/task_local.rs index 8347e34b6..c72937f6f 100644 --- a/src/task/task_local.rs +++ b/src/task/task_local.rs @@ -1,13 +1,13 @@ use std::cell::UnsafeCell; use std::error::Error; use std::fmt; +use std::future::Future; use std::sync::atomic::{AtomicUsize, Ordering}; use std::sync::Mutex; use lazy_static::lazy_static; use super::worker; -use crate::future::Future; use crate::utils::abort_on_panic; /// Declares task-local values. diff --git a/src/utils.rs b/src/utils.rs index cfbfce353..76db50b82 100644 --- a/src/utils.rs +++ b/src/utils.rs @@ -20,7 +20,7 @@ pub fn abort_on_panic(f: impl FnOnce() -> T) -> T { t } -/// Defines an extension trait for a base trait from the `futures` crate. +/// Defines an extension trait for a base trait. /// /// In generated docs, the base trait will contain methods from the extension trait. In actual /// code, the base trait will be re-exported and the extension trait will be hidden. We then @@ -35,7 +35,7 @@ macro_rules! extension_trait { // Interesting patterns: // - `$name`: trait name that gets rendered in the docs // - `$ext`: name of the hidden extension trait - // - `$base`: base trait from the `futures` crate + // - `$base`: base trait #[doc = $doc:tt] pub trait $name:ident { $($body_base:tt)* @@ -87,13 +87,21 @@ macro_rules! extension_trait { }; // Parse the return type in an extension method. - (@doc ($($head:tt)*) -> impl Future $(+ $lt:lifetime)? [$f:ty] $($tail:tt)*) => { - extension_trait!(@doc ($($head)* -> borrowed::ImplFuture<$($lt,)? $out>) $($tail)*); + (@doc ($($head:tt)*) -> impl Future [$f:ty] $($tail:tt)*) => { + extension_trait!(@doc ($($head)* -> owned::ImplFuture<$out>) $($tail)*); }; (@ext ($($head:tt)*) -> impl Future $(+ $lt:lifetime)? [$f:ty] $($tail:tt)*) => { extension_trait!(@ext ($($head)* -> $f) $($tail)*); }; + // Parse the return type in an extension method. + (@doc ($($head:tt)*) -> impl Future + $lt:lifetime [$f:ty] $($tail:tt)*) => { + extension_trait!(@doc ($($head)* -> borrowed::ImplFuture<$lt, $out>) $($tail)*); + }; + (@ext ($($head:tt)*) -> impl Future + $lt:lifetime [$f:ty] $($tail:tt)*) => { + extension_trait!(@ext ($($head)* -> $f) $($tail)*); + }; + // Parse a token. (@doc ($($head:tt)*) $token:tt $($tail:tt)*) => { extension_trait!(@doc ($($head)* $token) $($tail)*);