diff --git a/futures-core/src/future/mod.rs b/futures-core/src/future/mod.rs index 110a8289fe..ae654aa17c 100644 --- a/futures-core/src/future/mod.rs +++ b/futures-core/src/future/mod.rs @@ -10,13 +10,17 @@ mod future_obj; pub use self::future_obj::{FutureObj, LocalFutureObj, UnsafeFutureObj}; #[cfg(feature = "alloc")] +#[must_use = "futures do nothing unless polled"] +#[allow(missing_debug_implementations)] /// An owned dynamically typed [`Future`] for use in cases where you can't /// statically type your result or need to add some indirection. -pub type BoxFuture<'a, T> = Pin + Send + 'a>>; +pub struct BoxFuture<'a, T>(Pin + Send + 'a>>); #[cfg(feature = "alloc")] +#[must_use = "futures do nothing unless polled"] +#[allow(missing_debug_implementations)] /// `BoxFuture`, but without the `Send` requirement. -pub type LocalBoxFuture<'a, T> = Pin + 'a>>; +pub struct LocalBoxFuture<'a, T>(Pin + 'a>>); /// A `Future` or `TryFuture` which tracks whether or not the underlying future /// should no longer be polled. @@ -81,6 +85,7 @@ impl TryFuture for F #[cfg(feature = "alloc")] mod if_alloc { + use core::mem; use alloc::boxed::Box; use super::*; @@ -96,4 +101,62 @@ mod if_alloc { ::is_terminated(&**self) } } + + impl Future for BoxFuture<'_, O> { + type Output = O; + + fn poll(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll { + let mut_pin = self.0.as_mut(); + mut_pin.poll(cx) + } + } + + impl BoxFuture<'_, O> { + /// Converts Pin> to PinnedFuture + pub fn new<'a>(f: Pin + Send + 'a>>) -> BoxFuture<'a, O> { + BoxFuture(f) + } + } + + impl Future for LocalBoxFuture<'_, O> { + type Output = O; + + fn poll(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll { + let mut_pin = self.0.as_mut(); + mut_pin.poll(cx) + } + } + + impl LocalBoxFuture<'_, O> { + /// Converts Pin> to PinnedFuture + pub fn new<'a>(f: Pin + 'a>>) -> LocalBoxFuture<'a, O> { + LocalBoxFuture(f) + } + } + + unsafe impl<'a, T> UnsafeFutureObj<'a, T> for BoxFuture<'a, T> where T: 'a + { + fn into_raw(mut self) -> *mut (dyn Future + 'a) { + let ptr = unsafe { self.0.as_mut().get_unchecked_mut() as *mut _ }; + mem::forget(self); + ptr + } + + unsafe fn drop(ptr: *mut (dyn Future + 'a)) { + drop(Pin::from(Box::from_raw(ptr))) + } + } + + unsafe impl<'a, T> UnsafeFutureObj<'a, T> for LocalBoxFuture<'a, T> where T: 'a + { + fn into_raw(mut self) -> *mut (dyn Future + 'a) { + let ptr = unsafe { self.0.as_mut().get_unchecked_mut() as *mut _ }; + mem::forget(self); + ptr + } + + unsafe fn drop(ptr: *mut (dyn Future + 'a)) { + drop(Pin::from(Box::from_raw(ptr))) + } + } } diff --git a/futures-util/src/future/mod.rs b/futures-util/src/future/mod.rs index f44bfb0cdb..08244d4b14 100644 --- a/futures-util/src/future/mod.rs +++ b/futures-util/src/future/mod.rs @@ -495,7 +495,7 @@ pub trait FutureExt: Future { fn boxed<'a>(self) -> BoxFuture<'a, Self::Output> where Self: Sized + Send + 'a { - Box::pin(self) + BoxFuture::new(Box::pin(self)) } /// Wrap the future in a Box, pinning it. @@ -505,7 +505,7 @@ pub trait FutureExt: Future { fn boxed_local<'a>(self) -> LocalBoxFuture<'a, Self::Output> where Self: Sized + 'a { - Box::pin(self) + LocalBoxFuture::new(Box::pin(self)) } /// Turns a [`Future`](Future) into a