From 6d3a82f811ddc79a1fa11d5676a63a9cd0a28a3e Mon Sep 17 00:00:00 2001 From: Ibraheem Ahmed Date: Tue, 7 Dec 2021 23:42:25 -0500 Subject: [PATCH] implement `core::future::lazy` --- library/core/src/future/lazy.rs | 54 +++++++++++++++++++++++++++++++++ library/core/src/future/mod.rs | 4 +++ 2 files changed, 58 insertions(+) create mode 100644 library/core/src/future/lazy.rs diff --git a/library/core/src/future/lazy.rs b/library/core/src/future/lazy.rs new file mode 100644 index 0000000000000..66bdbf65a867c --- /dev/null +++ b/library/core/src/future/lazy.rs @@ -0,0 +1,54 @@ +use core::future::Future; +use core::pin::Pin; +use core::task::{Context, Poll}; + +/// A future that lazily executes a closure. +#[derive(Debug, Clone)] +#[must_use = "futures do nothing unless you `.await` or poll them"] +#[unstable(feature = "future_lazy", issue = "91647")] +pub struct Lazy(Option); + +#[unstable(feature = "future_lazy", issue = "91647")] +impl Unpin for Lazy {} + +/// Creates a new future that lazily executes a closure. +/// +/// The provided closure is only run once the future is polled. +/// +/// # Examples +/// +/// ``` +/// #![feature(future_lazy)] +/// +/// # let _ = async { +/// use std::future; +/// +/// let a = future::lazy(|_| 1); +/// assert_eq!(a.await, 1); +/// +/// let b = future::lazy(|_| -> i32 { +/// panic!("oh no!") +/// }); +/// drop(b); // closure is never run +/// # }; +/// ``` +#[unstable(feature = "future_lazy", issue = "91647")] +pub fn lazy(f: F) -> Lazy +where + F: FnOnce(&mut Context<'_>) -> R, +{ + Lazy(Some(f)) +} + +#[unstable(feature = "future_lazy", issue = "91647")] +impl Future for Lazy +where + F: FnOnce(&mut Context<'_>) -> R, +{ + type Output = R; + + fn poll(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll { + let f = self.0.take().expect("`Lazy` polled after completion"); + Poll::Ready((f)(cx)) + } +} diff --git a/library/core/src/future/mod.rs b/library/core/src/future/mod.rs index 7a3af70d6d97c..cccad931cd0e2 100644 --- a/library/core/src/future/mod.rs +++ b/library/core/src/future/mod.rs @@ -11,6 +11,7 @@ use crate::{ mod future; mod into_future; +mod lazy; mod pending; mod poll_fn; mod ready; @@ -29,6 +30,9 @@ pub use ready::{ready, Ready}; #[unstable(feature = "future_poll_fn", issue = "72302")] pub use poll_fn::{poll_fn, PollFn}; +#[unstable(feature = "future_lazy", issue = "91647")] +pub use self::lazy::{lazy, Lazy}; + /// This type is needed because: /// /// a) Generators cannot implement `for<'a, 'b> Generator<&'a mut Context<'b>>`, so we need to pass