diff --git a/src/lib.rs b/src/lib.rs index 6a4b3a9..a2ee70a 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -23,6 +23,21 @@ macro_rules! ready { }}; } +/// Pins a variable on the stack. +/// +/// TODO: Drop in favor of `core::pin::pin`, once MSRV is bumped to 1.68. +macro_rules! pin { + ($($x:ident),* $(,)?) => { + $( + let mut $x = $x; + #[allow(unused_mut)] + let mut $x = unsafe { + std::pin::Pin::new_unchecked(&mut $x) + }; + )* + } +} + mod barrier; mod mutex; mod once_cell; diff --git a/src/once_cell.rs b/src/once_cell.rs index dee540e..978f57c 100644 --- a/src/once_cell.rs +++ b/src/once_cell.rs @@ -3,7 +3,6 @@ use std::convert::Infallible; use std::fmt; use std::future::Future; use std::mem::{forget, MaybeUninit}; -use std::pin::Pin; use std::ptr; use std::sync::atomic::{AtomicUsize, Ordering}; use std::task::{Context, Poll, RawWaker, RawWakerVTable, Waker}; @@ -750,7 +749,7 @@ impl Drop for OnceCell { } /// Either return the result of a future now, or panic. -fn now_or_never(mut f: impl Future) -> T { +fn now_or_never(f: impl Future) -> T { const NOOP_WAKER: RawWakerVTable = RawWakerVTable::new(clone, wake, wake_by_ref, drop); unsafe fn wake(_: *const ()) {} @@ -760,15 +759,14 @@ fn now_or_never(mut f: impl Future) -> T { } unsafe fn drop(_: *const ()) {} - // SAFETY: We don't move the future after we pin it here. - let future = unsafe { Pin::new_unchecked(&mut f) }; + pin!(f); let waker = unsafe { Waker::from_raw(RawWaker::new(ptr::null(), &NOOP_WAKER)) }; // Poll the future exactly once. let mut cx = Context::from_waker(&waker); - match future.poll(&mut cx) { + match f.poll(&mut cx) { Poll::Ready(value) => value, Poll::Pending => unreachable!("future not ready"), }