1 use core::{
2     fmt,
3     future::Future,
4     marker::PhantomData,
5     mem,
6     pin::Pin,
7     task::{Context, Poll},
8 };
9 
10 /// A custom trait object for polling futures, roughly akin to
11 /// `Box<dyn Future<Output = T> + 'a>`.
12 ///
13 /// This custom trait object was introduced as currently it is not possible to
14 /// take `dyn Trait` by value and `Box<dyn Trait>` is not available in no_std
15 /// contexts.
16 pub struct LocalFutureObj<'a, T> {
17     future: *mut (dyn Future<Output = T> + 'static),
18     drop_fn: unsafe fn(*mut (dyn Future<Output = T> + 'static)),
19     _marker: PhantomData<&'a ()>,
20 }
21 
22 // As LocalFutureObj only holds pointers, even if we move it, the pointed to values won't move,
23 // so this is safe as long as we don't provide any way for a user to directly access the pointers
24 // and move their values.
25 impl<T> Unpin for LocalFutureObj<'_, T> {}
26 
27 #[allow(single_use_lifetimes)]
28 #[allow(clippy::transmute_ptr_to_ptr)]
remove_future_lifetime<'a, T>( ptr: *mut (dyn Future<Output = T> + 'a), ) -> *mut (dyn Future<Output = T> + 'static)29 unsafe fn remove_future_lifetime<'a, T>(
30     ptr: *mut (dyn Future<Output = T> + 'a),
31 ) -> *mut (dyn Future<Output = T> + 'static) {
32     unsafe { mem::transmute(ptr) }
33 }
34 
35 #[allow(single_use_lifetimes)]
remove_drop_lifetime<'a, T>( ptr: unsafe fn(*mut (dyn Future<Output = T> + 'a)), ) -> unsafe fn(*mut (dyn Future<Output = T> + 'static))36 unsafe fn remove_drop_lifetime<'a, T>(
37     ptr: unsafe fn(*mut (dyn Future<Output = T> + 'a)),
38 ) -> unsafe fn(*mut (dyn Future<Output = T> + 'static)) {
39     unsafe { mem::transmute(ptr) }
40 }
41 
42 impl<'a, T> LocalFutureObj<'a, T> {
43     /// Create a `LocalFutureObj` from a custom trait object representation.
44     #[inline]
new<F: UnsafeFutureObj<'a, T> + 'a>(f: F) -> Self45     pub fn new<F: UnsafeFutureObj<'a, T> + 'a>(f: F) -> Self {
46         Self {
47             future: unsafe { remove_future_lifetime(f.into_raw()) },
48             drop_fn: unsafe { remove_drop_lifetime(F::drop) },
49             _marker: PhantomData,
50         }
51     }
52 
53     /// Converts the `LocalFutureObj` into a `FutureObj`.
54     ///
55     /// # Safety
56     ///
57     /// To make this operation safe one has to ensure that the `UnsafeFutureObj`
58     /// instance from which this `LocalFutureObj` was created actually
59     /// implements `Send`.
60     #[inline]
into_future_obj(self) -> FutureObj<'a, T>61     pub unsafe fn into_future_obj(self) -> FutureObj<'a, T> {
62         FutureObj(self)
63     }
64 }
65 
66 impl<T> fmt::Debug for LocalFutureObj<'_, T> {
fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result67     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
68         f.debug_struct("LocalFutureObj").finish()
69     }
70 }
71 
72 impl<'a, T> From<FutureObj<'a, T>> for LocalFutureObj<'a, T> {
73     #[inline]
from(f: FutureObj<'a, T>) -> Self74     fn from(f: FutureObj<'a, T>) -> Self {
75         f.0
76     }
77 }
78 
79 impl<T> Future for LocalFutureObj<'_, T> {
80     type Output = T;
81 
82     #[inline]
poll(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<T>83     fn poll(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<T> {
84         unsafe { Pin::new_unchecked(&mut *self.future).poll(cx) }
85     }
86 }
87 
88 impl<T> Drop for LocalFutureObj<'_, T> {
drop(&mut self)89     fn drop(&mut self) {
90         unsafe { (self.drop_fn)(self.future) }
91     }
92 }
93 
94 /// A custom trait object for polling futures, roughly akin to
95 /// `Box<dyn Future<Output = T> + Send + 'a>`.
96 ///
97 /// This custom trait object was introduced as currently it is not possible to
98 /// take `dyn Trait` by value and `Box<dyn Trait>` is not available in no_std
99 /// contexts.
100 ///
101 /// You should generally not need to use this type outside of `no_std` or when
102 /// implementing `Spawn`, consider using `BoxFuture` instead.
103 pub struct FutureObj<'a, T>(LocalFutureObj<'a, T>);
104 
105 impl<T> Unpin for FutureObj<'_, T> {}
106 unsafe impl<T> Send for FutureObj<'_, T> {}
107 
108 impl<'a, T> FutureObj<'a, T> {
109     /// Create a `FutureObj` from a custom trait object representation.
110     #[inline]
new<F: UnsafeFutureObj<'a, T> + Send>(f: F) -> Self111     pub fn new<F: UnsafeFutureObj<'a, T> + Send>(f: F) -> Self {
112         Self(LocalFutureObj::new(f))
113     }
114 }
115 
116 impl<T> fmt::Debug for FutureObj<'_, T> {
fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result117     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
118         f.debug_struct("FutureObj").finish()
119     }
120 }
121 
122 impl<T> Future for FutureObj<'_, T> {
123     type Output = T;
124 
125     #[inline]
poll(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<T>126     fn poll(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<T> {
127         Pin::new(&mut self.0).poll(cx)
128     }
129 }
130 
131 /// A custom implementation of a future trait object for `FutureObj`, providing
132 /// a vtable with drop support.
133 ///
134 /// This custom representation is typically used only in `no_std` contexts,
135 /// where the default `Box`-based implementation is not available.
136 ///
137 /// # Safety
138 ///
139 /// See the safety notes on individual methods for what guarantees an
140 /// implementor must provide.
141 pub unsafe trait UnsafeFutureObj<'a, T>: 'a {
142     /// Convert an owned instance into a (conceptually owned) fat pointer.
143     ///
144     /// # Safety
145     ///
146     /// ## Implementor
147     ///
148     /// The trait implementor must guarantee that it is safe to convert the
149     /// provided `*mut (dyn Future<Output = T> + 'a)` into a `Pin<&mut (dyn
150     /// Future<Output = T> + 'a)>` and call methods on it, non-reentrantly,
151     /// until `UnsafeFutureObj::drop` is called with it.
152     #[allow(clippy::unnecessary_safety_doc)]
into_raw(self) -> *mut (dyn Future<Output = T> + 'a)153     fn into_raw(self) -> *mut (dyn Future<Output = T> + 'a);
154 
155     /// Drops the future represented by the given fat pointer.
156     ///
157     /// # Safety
158     ///
159     /// ## Implementor
160     ///
161     /// The trait implementor must guarantee that it is safe to call this
162     /// function once per `into_raw` invocation.
163     ///
164     /// ## Caller
165     ///
166     /// The caller must ensure:
167     ///
168     ///  * the pointer passed was obtained from an `into_raw` invocation from
169     ///    this same trait object
170     ///  * the pointer is not currently in use as a `Pin<&mut (dyn Future<Output
171     ///    = T> + 'a)>`
172     ///  * the pointer must not be used again after this function is called
drop(ptr: *mut (dyn Future<Output = T> + 'a))173     unsafe fn drop(ptr: *mut (dyn Future<Output = T> + 'a));
174 }
175 
176 unsafe impl<'a, T, F> UnsafeFutureObj<'a, T> for &'a mut F
177 where
178     F: Future<Output = T> + Unpin + 'a,
179 {
into_raw(self) -> *mut (dyn Future<Output = T> + 'a)180     fn into_raw(self) -> *mut (dyn Future<Output = T> + 'a) {
181         self as *mut dyn Future<Output = T>
182     }
183 
drop(_ptr: *mut (dyn Future<Output = T> + 'a))184     unsafe fn drop(_ptr: *mut (dyn Future<Output = T> + 'a)) {}
185 }
186 
187 unsafe impl<'a, T> UnsafeFutureObj<'a, T> for &'a mut (dyn Future<Output = T> + Unpin + 'a) {
into_raw(self) -> *mut (dyn Future<Output = T> + 'a)188     fn into_raw(self) -> *mut (dyn Future<Output = T> + 'a) {
189         self as *mut dyn Future<Output = T>
190     }
191 
drop(_ptr: *mut (dyn Future<Output = T> + 'a))192     unsafe fn drop(_ptr: *mut (dyn Future<Output = T> + 'a)) {}
193 }
194 
195 unsafe impl<'a, T, F> UnsafeFutureObj<'a, T> for Pin<&'a mut F>
196 where
197     F: Future<Output = T> + 'a,
198 {
into_raw(self) -> *mut (dyn Future<Output = T> + 'a)199     fn into_raw(self) -> *mut (dyn Future<Output = T> + 'a) {
200         unsafe { self.get_unchecked_mut() as *mut dyn Future<Output = T> }
201     }
202 
drop(_ptr: *mut (dyn Future<Output = T> + 'a))203     unsafe fn drop(_ptr: *mut (dyn Future<Output = T> + 'a)) {}
204 }
205 
206 unsafe impl<'a, T> UnsafeFutureObj<'a, T> for Pin<&'a mut (dyn Future<Output = T> + 'a)> {
into_raw(self) -> *mut (dyn Future<Output = T> + 'a)207     fn into_raw(self) -> *mut (dyn Future<Output = T> + 'a) {
208         unsafe { self.get_unchecked_mut() as *mut dyn Future<Output = T> }
209     }
210 
drop(_ptr: *mut (dyn Future<Output = T> + 'a))211     unsafe fn drop(_ptr: *mut (dyn Future<Output = T> + 'a)) {}
212 }
213 
214 #[cfg(feature = "alloc")]
215 mod if_alloc {
216     use super::*;
217     use alloc::boxed::Box;
218 
219     unsafe impl<'a, T, F> UnsafeFutureObj<'a, T> for Box<F>
220     where
221         F: Future<Output = T> + 'a,
222     {
into_raw(self) -> *mut (dyn Future<Output = T> + 'a)223         fn into_raw(self) -> *mut (dyn Future<Output = T> + 'a) {
224             Box::into_raw(self)
225         }
226 
drop(ptr: *mut (dyn Future<Output = T> + 'a))227         unsafe fn drop(ptr: *mut (dyn Future<Output = T> + 'a)) {
228             drop(unsafe { Box::from_raw(ptr.cast::<F>()) })
229         }
230     }
231 
232     unsafe impl<'a, T: 'a> UnsafeFutureObj<'a, T> for Box<dyn Future<Output = T> + 'a> {
into_raw(self) -> *mut (dyn Future<Output = T> + 'a)233         fn into_raw(self) -> *mut (dyn Future<Output = T> + 'a) {
234             Box::into_raw(self)
235         }
236 
drop(ptr: *mut (dyn Future<Output = T> + 'a))237         unsafe fn drop(ptr: *mut (dyn Future<Output = T> + 'a)) {
238             drop(unsafe { Box::from_raw(ptr) })
239         }
240     }
241 
242     unsafe impl<'a, T: 'a> UnsafeFutureObj<'a, T> for Box<dyn Future<Output = T> + Send + 'a> {
into_raw(self) -> *mut (dyn Future<Output = T> + 'a)243         fn into_raw(self) -> *mut (dyn Future<Output = T> + 'a) {
244             Box::into_raw(self)
245         }
246 
drop(ptr: *mut (dyn Future<Output = T> + 'a))247         unsafe fn drop(ptr: *mut (dyn Future<Output = T> + 'a)) {
248             drop(unsafe { Box::from_raw(ptr) })
249         }
250     }
251 
252     unsafe impl<'a, T, F> UnsafeFutureObj<'a, T> for Pin<Box<F>>
253     where
254         F: Future<Output = T> + 'a,
255     {
into_raw(self) -> *mut (dyn Future<Output = T> + 'a)256         fn into_raw(self) -> *mut (dyn Future<Output = T> + 'a) {
257             let mut this = mem::ManuallyDrop::new(self);
258             unsafe { this.as_mut().get_unchecked_mut() as *mut _ }
259         }
260 
drop(ptr: *mut (dyn Future<Output = T> + 'a))261         unsafe fn drop(ptr: *mut (dyn Future<Output = T> + 'a)) {
262             drop(Pin::from(unsafe { Box::from_raw(ptr) }))
263         }
264     }
265 
266     unsafe impl<'a, T: 'a> UnsafeFutureObj<'a, T> for Pin<Box<dyn Future<Output = T> + 'a>> {
into_raw(self) -> *mut (dyn Future<Output = T> + 'a)267         fn into_raw(self) -> *mut (dyn Future<Output = T> + 'a) {
268             let mut this = mem::ManuallyDrop::new(self);
269             unsafe { this.as_mut().get_unchecked_mut() as *mut _ }
270         }
271 
drop(ptr: *mut (dyn Future<Output = T> + 'a))272         unsafe fn drop(ptr: *mut (dyn Future<Output = T> + 'a)) {
273             drop(Pin::from(unsafe { Box::from_raw(ptr) }))
274         }
275     }
276 
277     unsafe impl<'a, T: 'a> UnsafeFutureObj<'a, T> for Pin<Box<dyn Future<Output = T> + Send + 'a>> {
into_raw(self) -> *mut (dyn Future<Output = T> + 'a)278         fn into_raw(self) -> *mut (dyn Future<Output = T> + 'a) {
279             let mut this = mem::ManuallyDrop::new(self);
280             unsafe { this.as_mut().get_unchecked_mut() as *mut _ }
281         }
282 
drop(ptr: *mut (dyn Future<Output = T> + 'a))283         unsafe fn drop(ptr: *mut (dyn Future<Output = T> + 'a)) {
284             drop(Pin::from(unsafe { Box::from_raw(ptr) }))
285         }
286     }
287 
288     impl<'a, F: Future<Output = ()> + Send + 'a> From<Box<F>> for FutureObj<'a, ()> {
from(boxed: Box<F>) -> Self289         fn from(boxed: Box<F>) -> Self {
290             Self::new(boxed)
291         }
292     }
293 
294     impl<'a> From<Box<dyn Future<Output = ()> + Send + 'a>> for FutureObj<'a, ()> {
from(boxed: Box<dyn Future<Output = ()> + Send + 'a>) -> Self295         fn from(boxed: Box<dyn Future<Output = ()> + Send + 'a>) -> Self {
296             Self::new(boxed)
297         }
298     }
299 
300     impl<'a, F: Future<Output = ()> + Send + 'a> From<Pin<Box<F>>> for FutureObj<'a, ()> {
from(boxed: Pin<Box<F>>) -> Self301         fn from(boxed: Pin<Box<F>>) -> Self {
302             Self::new(boxed)
303         }
304     }
305 
306     impl<'a> From<Pin<Box<dyn Future<Output = ()> + Send + 'a>>> for FutureObj<'a, ()> {
from(boxed: Pin<Box<dyn Future<Output = ()> + Send + 'a>>) -> Self307         fn from(boxed: Pin<Box<dyn Future<Output = ()> + Send + 'a>>) -> Self {
308             Self::new(boxed)
309         }
310     }
311 
312     impl<'a, F: Future<Output = ()> + 'a> From<Box<F>> for LocalFutureObj<'a, ()> {
from(boxed: Box<F>) -> Self313         fn from(boxed: Box<F>) -> Self {
314             Self::new(boxed)
315         }
316     }
317 
318     impl<'a> From<Box<dyn Future<Output = ()> + 'a>> for LocalFutureObj<'a, ()> {
from(boxed: Box<dyn Future<Output = ()> + 'a>) -> Self319         fn from(boxed: Box<dyn Future<Output = ()> + 'a>) -> Self {
320             Self::new(boxed)
321         }
322     }
323 
324     impl<'a, F: Future<Output = ()> + 'a> From<Pin<Box<F>>> for LocalFutureObj<'a, ()> {
from(boxed: Pin<Box<F>>) -> Self325         fn from(boxed: Pin<Box<F>>) -> Self {
326             Self::new(boxed)
327         }
328     }
329 
330     impl<'a> From<Pin<Box<dyn Future<Output = ()> + 'a>>> for LocalFutureObj<'a, ()> {
from(boxed: Pin<Box<dyn Future<Output = ()> + 'a>>) -> Self331         fn from(boxed: Pin<Box<dyn Future<Output = ()> + 'a>>) -> Self {
332             Self::new(boxed)
333         }
334     }
335 }
336