use core::{ mem, fmt, future::Future, marker::PhantomData, 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 ()>, } impl Unpin for LocalFutureObj<'_, T> {} #[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) } 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) -> LocalFutureObj<'a, T> { LocalFutureObj { future: unsafe { remove_future_lifetime(f.into_raw()) }, drop_fn: unsafe { remove_drop_lifetime(F::drop) }, _marker: PhantomData, } } /// Converts the `LocalFutureObj` into a `FutureObj` /// 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>) -> LocalFutureObj<'a, T> { 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`](crate::future::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) -> FutureObj<'a, T> { FutureObj(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(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll { let pinned_field: Pin<&mut LocalFutureObj<'_, T>> = unsafe { Pin::map_unchecked_mut(self, |x| &mut x.0) }; LocalFutureObj::poll(pinned_field, 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. 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 (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 as *mut F)) } } 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(mut self) -> *mut (dyn Future + 'a) { let ptr = unsafe { self.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: 'a> UnsafeFutureObj<'a, T> for Pin + 'a>> { fn into_raw(mut self) -> *mut (dyn Future + 'a) { let ptr = unsafe { self.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: 'a> UnsafeFutureObj<'a, T> for Pin + Send + 'a>> { fn into_raw(mut self) -> *mut (dyn Future + 'a) { let ptr = unsafe { self.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))) } } impl<'a, F: Future + Send + 'a> From> for FutureObj<'a, ()> { fn from(boxed: Box) -> Self { FutureObj::new(boxed) } } impl<'a> From + Send + 'a>> for FutureObj<'a, ()> { fn from(boxed: Box + Send + 'a>) -> Self { FutureObj::new(boxed) } } impl<'a, F: Future + Send + 'a> From>> for FutureObj<'a, ()> { fn from(boxed: Pin>) -> Self { FutureObj::new(boxed) } } impl<'a> From + Send + 'a>>> for FutureObj<'a, ()> { fn from(boxed: Pin + Send + 'a>>) -> Self { FutureObj::new(boxed) } } impl<'a, F: Future + 'a> From> for LocalFutureObj<'a, ()> { fn from(boxed: Box) -> Self { LocalFutureObj::new(boxed) } } impl<'a> From + 'a>> for LocalFutureObj<'a, ()> { fn from(boxed: Box + 'a>) -> Self { LocalFutureObj::new(boxed) } } impl<'a, F: Future + 'a> From>> for LocalFutureObj<'a, ()> { fn from(boxed: Pin>) -> Self { LocalFutureObj::new(boxed) } } impl<'a> From + 'a>>> for LocalFutureObj<'a, ()> { fn from(boxed: Pin + 'a>>) -> Self { LocalFutureObj::new(boxed) } } }