use core::{ fmt, future::Future, marker::PhantomData, mem, pin::Pin, task::{Context, Poll}, }; /// A custom trait object for polling futures, roughly akin to /// `Box + 'a>`. /// /// This custom trait object was introduced as currently it is not possible to /// take `dyn Trait` by value and `Box` is not available in no_std /// contexts. pub struct LocalFutureObj<'a, T> { future: *mut (dyn Future + 'static), drop_fn: unsafe fn(*mut (dyn Future + 'static)), _marker: PhantomData<&'a ()>, } // As LocalFutureObj only holds pointers, even if we move it, the pointed to values won't move, // so this is safe as long as we don't provide any way for a user to directly access the pointers // and move their values. impl Unpin for LocalFutureObj<'_, T> {} #[allow(single_use_lifetimes)] #[allow(clippy::transmute_ptr_to_ptr)] unsafe fn remove_future_lifetime<'a, T>( ptr: *mut (dyn Future + 'a), ) -> *mut (dyn Future + 'static) { mem::transmute(ptr) } #[allow(single_use_lifetimes)] unsafe fn remove_drop_lifetime<'a, T>( ptr: unsafe fn(*mut (dyn Future + 'a)), ) -> unsafe fn(*mut (dyn Future + 'static)) { mem::transmute(ptr) } impl<'a, T> LocalFutureObj<'a, T> { /// Create a `LocalFutureObj` from a custom trait object representation. #[inline] pub fn new + 'a>(f: F) -> Self { Self { future: unsafe { remove_future_lifetime(f.into_raw()) }, drop_fn: unsafe { remove_drop_lifetime(F::drop) }, _marker: PhantomData, } } /// Converts the `LocalFutureObj` into a `FutureObj`. /// /// # Safety /// /// To make this operation safe one has to ensure that the `UnsafeFutureObj` /// instance from which this `LocalFutureObj` was created actually /// implements `Send`. #[inline] pub unsafe fn into_future_obj(self) -> FutureObj<'a, T> { FutureObj(self) } } impl fmt::Debug for LocalFutureObj<'_, T> { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { f.debug_struct("LocalFutureObj").finish() } } impl<'a, T> From> for LocalFutureObj<'a, T> { #[inline] fn from(f: FutureObj<'a, T>) -> Self { f.0 } } impl Future for LocalFutureObj<'_, T> { type Output = T; #[inline] fn poll(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll { unsafe { Pin::new_unchecked(&mut *self.future).poll(cx) } } } impl Drop for LocalFutureObj<'_, T> { fn drop(&mut self) { unsafe { (self.drop_fn)(self.future) } } } /// A custom trait object for polling futures, roughly akin to /// `Box + Send + 'a>`. /// /// This custom trait object was introduced as currently it is not possible to /// take `dyn Trait` by value and `Box` is not available in no_std /// contexts. /// /// You should generally not need to use this type outside of `no_std` or when /// implementing `Spawn`, consider using `BoxFuture` instead. pub struct FutureObj<'a, T>(LocalFutureObj<'a, T>); impl Unpin for FutureObj<'_, T> {} unsafe impl Send for FutureObj<'_, T> {} impl<'a, T> FutureObj<'a, T> { /// Create a `FutureObj` from a custom trait object representation. #[inline] pub fn new + Send>(f: F) -> Self { Self(LocalFutureObj::new(f)) } } impl fmt::Debug for FutureObj<'_, T> { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { f.debug_struct("FutureObj").finish() } } impl Future for FutureObj<'_, T> { type Output = T; #[inline] fn poll(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll { Pin::new(&mut self.0).poll(cx) } } /// A custom implementation of a future trait object for `FutureObj`, providing /// a vtable with drop support. /// /// This custom representation is typically used only in `no_std` contexts, /// where the default `Box`-based implementation is not available. /// /// # Safety /// /// See the safety notes on individual methods for what guarantees an /// implementor must provide. pub unsafe trait UnsafeFutureObj<'a, T>: 'a { /// Convert an owned instance into a (conceptually owned) fat pointer. /// /// # Safety /// /// ## Implementor /// /// The trait implementor must guarantee that it is safe to convert the /// provided `*mut (dyn Future + 'a)` into a `Pin<&mut (dyn /// Future + 'a)>` and call methods on it, non-reentrantly, /// until `UnsafeFutureObj::drop` is called with it. #[allow(clippy::unnecessary_safety_doc)] fn into_raw(self) -> *mut (dyn Future + 'a); /// Drops the future represented by the given fat pointer. /// /// # Safety /// /// ## Implementor /// /// The trait implementor must guarantee that it is safe to call this /// function once per `into_raw` invocation. /// /// ## Caller /// /// The caller must ensure: /// /// * the pointer passed was obtained from an `into_raw` invocation from /// this same trait object /// * the pointer is not currently in use as a `Pin<&mut (dyn Future + 'a)>` /// * the pointer must not be used again after this function is called unsafe fn drop(ptr: *mut (dyn Future + 'a)); } unsafe impl<'a, T, F> UnsafeFutureObj<'a, T> for &'a mut F where F: Future + Unpin + 'a, { fn into_raw(self) -> *mut (dyn Future + 'a) { self as *mut dyn Future } unsafe fn drop(_ptr: *mut (dyn Future + 'a)) {} } unsafe impl<'a, T> UnsafeFutureObj<'a, T> for &'a mut (dyn Future + Unpin + 'a) { fn into_raw(self) -> *mut (dyn Future + 'a) { self as *mut dyn Future } unsafe fn drop(_ptr: *mut (dyn Future + 'a)) {} } unsafe impl<'a, T, F> UnsafeFutureObj<'a, T> for Pin<&'a mut F> where F: Future + 'a, { fn into_raw(self) -> *mut (dyn Future + 'a) { unsafe { self.get_unchecked_mut() as *mut dyn Future } } unsafe fn drop(_ptr: *mut (dyn Future + 'a)) {} } unsafe impl<'a, T> UnsafeFutureObj<'a, T> for Pin<&'a mut (dyn Future + 'a)> { fn into_raw(self) -> *mut (dyn Future + 'a) { unsafe { self.get_unchecked_mut() as *mut dyn Future } } unsafe fn drop(_ptr: *mut (dyn Future + 'a)) {} } #[cfg(feature = "alloc")] mod if_alloc { use super::*; use alloc::boxed::Box; unsafe impl<'a, T, F> UnsafeFutureObj<'a, T> for Box where F: Future + 'a, { fn into_raw(self) -> *mut (dyn Future + 'a) { Box::into_raw(self) } unsafe fn drop(ptr: *mut (dyn Future + 'a)) { drop(Box::from_raw(ptr.cast::())) } } unsafe impl<'a, T: 'a> UnsafeFutureObj<'a, T> for Box + 'a> { fn into_raw(self) -> *mut (dyn Future + 'a) { Box::into_raw(self) } unsafe fn drop(ptr: *mut (dyn Future + 'a)) { drop(Box::from_raw(ptr)) } } unsafe impl<'a, T: 'a> UnsafeFutureObj<'a, T> for Box + Send + 'a> { fn into_raw(self) -> *mut (dyn Future + 'a) { Box::into_raw(self) } unsafe fn drop(ptr: *mut (dyn Future + 'a)) { drop(Box::from_raw(ptr)) } } unsafe impl<'a, T, F> UnsafeFutureObj<'a, T> for Pin> where F: Future + 'a, { fn into_raw(self) -> *mut (dyn Future + 'a) { let mut this = mem::ManuallyDrop::new(self); unsafe { this.as_mut().get_unchecked_mut() as *mut _ } } unsafe fn drop(ptr: *mut (dyn Future + 'a)) { drop(Pin::from(Box::from_raw(ptr))) } } unsafe impl<'a, T: 'a> UnsafeFutureObj<'a, T> for Pin + 'a>> { fn into_raw(self) -> *mut (dyn Future + 'a) { let mut this = mem::ManuallyDrop::new(self); unsafe { this.as_mut().get_unchecked_mut() as *mut _ } } unsafe fn drop(ptr: *mut (dyn Future + 'a)) { drop(Pin::from(Box::from_raw(ptr))) } } unsafe impl<'a, T: 'a> UnsafeFutureObj<'a, T> for Pin + Send + 'a>> { fn into_raw(self) -> *mut (dyn Future + 'a) { let mut this = mem::ManuallyDrop::new(self); unsafe { this.as_mut().get_unchecked_mut() as *mut _ } } unsafe fn drop(ptr: *mut (dyn Future + 'a)) { drop(Pin::from(Box::from_raw(ptr))) } } impl<'a, F: Future + Send + 'a> From> for FutureObj<'a, ()> { fn from(boxed: Box) -> Self { Self::new(boxed) } } impl<'a> From + Send + 'a>> for FutureObj<'a, ()> { fn from(boxed: Box + Send + 'a>) -> Self { Self::new(boxed) } } impl<'a, F: Future + Send + 'a> From>> for FutureObj<'a, ()> { fn from(boxed: Pin>) -> Self { Self::new(boxed) } } impl<'a> From + Send + 'a>>> for FutureObj<'a, ()> { fn from(boxed: Pin + Send + 'a>>) -> Self { Self::new(boxed) } } impl<'a, F: Future + 'a> From> for LocalFutureObj<'a, ()> { fn from(boxed: Box) -> Self { Self::new(boxed) } } impl<'a> From + 'a>> for LocalFutureObj<'a, ()> { fn from(boxed: Box + 'a>) -> Self { Self::new(boxed) } } impl<'a, F: Future + 'a> From>> for LocalFutureObj<'a, ()> { fn from(boxed: Pin>) -> Self { Self::new(boxed) } } impl<'a> From + 'a>>> for LocalFutureObj<'a, ()> { fn from(boxed: Pin + 'a>>) -> Self { Self::new(boxed) } } }