| use std::future::Future; | 
 | use std::marker::Unpin; | 
 | use std::pin::Pin; | 
 | use std::task::{Context, Poll}; | 
 |  | 
 | use pin_project_lite::pin_project; | 
 |  | 
 | pub(crate) trait Started: Future { | 
 |     fn started(&self) -> bool; | 
 | } | 
 |  | 
 | pub(crate) fn lazy<F, R>(func: F) -> Lazy<F, R> | 
 | where | 
 |     F: FnOnce() -> R, | 
 |     R: Future + Unpin, | 
 | { | 
 |     Lazy { | 
 |         inner: Inner::Init { func }, | 
 |     } | 
 | } | 
 |  | 
 | // FIXME: allow() required due to `impl Trait` leaking types to this lint | 
 | pin_project! { | 
 |     #[allow(missing_debug_implementations)] | 
 |     pub(crate) struct Lazy<F, R> { | 
 |         #[pin] | 
 |         inner: Inner<F, R>, | 
 |     } | 
 | } | 
 |  | 
 | pin_project! { | 
 |     #[project = InnerProj] | 
 |     #[project_replace = InnerProjReplace] | 
 |     enum Inner<F, R> { | 
 |         Init { func: F }, | 
 |         Fut { #[pin] fut: R }, | 
 |         Empty, | 
 |     } | 
 | } | 
 |  | 
 | impl<F, R> Started for Lazy<F, R> | 
 | where | 
 |     F: FnOnce() -> R, | 
 |     R: Future, | 
 | { | 
 |     fn started(&self) -> bool { | 
 |         match self.inner { | 
 |             Inner::Init { .. } => false, | 
 |             Inner::Fut { .. } | Inner::Empty => true, | 
 |         } | 
 |     } | 
 | } | 
 |  | 
 | impl<F, R> Future for Lazy<F, R> | 
 | where | 
 |     F: FnOnce() -> R, | 
 |     R: Future, | 
 | { | 
 |     type Output = R::Output; | 
 |  | 
 |     fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> { | 
 |         let mut this = self.project(); | 
 |  | 
 |         if let InnerProj::Fut { fut } = this.inner.as_mut().project() { | 
 |             return fut.poll(cx); | 
 |         } | 
 |  | 
 |         match this.inner.as_mut().project_replace(Inner::Empty) { | 
 |             InnerProjReplace::Init { func } => { | 
 |                 this.inner.set(Inner::Fut { fut: func() }); | 
 |                 if let InnerProj::Fut { fut } = this.inner.project() { | 
 |                     return fut.poll(cx); | 
 |                 } | 
 |                 unreachable!() | 
 |             } | 
 |             _ => unreachable!("lazy state wrong"), | 
 |         } | 
 |     } | 
 | } |