1 use core::{
2 mem,
3 fmt,
4 future::Future,
5 marker::PhantomData,
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>(ptr: *mut (dyn Future<Output = T> + 'a))
30 -> *mut (dyn Future<Output = T> + 'static)
31 {
32 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>(ptr: unsafe fn (*mut (dyn Future<Output = T> + 'a)))
37 -> unsafe fn(*mut (dyn Future<Output = T> + 'static))
38 {
39 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")
69 .finish()
70 }
71 }
72
73 impl<'a, T> From<FutureObj<'a, T>> for LocalFutureObj<'a, T> {
74 #[inline]
from(f: FutureObj<'a, T>) -> Self75 fn from(f: FutureObj<'a, T>) -> Self {
76 f.0
77 }
78 }
79
80 impl<T> Future for LocalFutureObj<'_, T> {
81 type Output = T;
82
83 #[inline]
poll(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<T>84 fn poll(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<T> {
85 unsafe {
86 Pin::new_unchecked(&mut *self.future).poll(cx)
87 }
88 }
89 }
90
91 impl<T> Drop for LocalFutureObj<'_, T> {
drop(&mut self)92 fn drop(&mut self) {
93 unsafe {
94 (self.drop_fn)(self.future)
95 }
96 }
97 }
98
99 /// A custom trait object for polling futures, roughly akin to
100 /// `Box<dyn Future<Output = T> + Send + 'a>`.
101 ///
102 /// This custom trait object was introduced as currently it is not possible to
103 /// take `dyn Trait` by value and `Box<dyn Trait>` is not available in no_std
104 /// contexts.
105 ///
106 /// You should generally not need to use this type outside of `no_std` or when
107 /// implementing `Spawn`, consider using `BoxFuture` instead.
108 pub struct FutureObj<'a, T>(LocalFutureObj<'a, T>);
109
110 impl<T> Unpin for FutureObj<'_, T> {}
111 unsafe impl<T> Send for FutureObj<'_, T> {}
112
113 impl<'a, T> FutureObj<'a, T> {
114 /// Create a `FutureObj` from a custom trait object representation.
115 #[inline]
new<F: UnsafeFutureObj<'a, T> + Send>(f: F) -> Self116 pub fn new<F: UnsafeFutureObj<'a, T> + Send>(f: F) -> Self {
117 Self(LocalFutureObj::new(f))
118 }
119 }
120
121 impl<T> fmt::Debug for FutureObj<'_, T> {
fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result122 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
123 f.debug_struct("FutureObj")
124 .finish()
125 }
126 }
127
128 impl<T> Future for FutureObj<'_, T> {
129 type Output = T;
130
131 #[inline]
poll(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<T>132 fn poll(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<T> {
133 Pin::new( &mut self.0 ).poll(cx)
134 }
135 }
136
137 /// A custom implementation of a future trait object for `FutureObj`, providing
138 /// a vtable with drop support.
139 ///
140 /// This custom representation is typically used only in `no_std` contexts,
141 /// where the default `Box`-based implementation is not available.
142 ///
143 /// # Safety
144 ///
145 /// See the safety notes on individual methods for what guarantees an
146 /// implementor must provide.
147 pub unsafe trait UnsafeFutureObj<'a, T>: 'a {
148 /// Convert an owned instance into a (conceptually owned) fat pointer.
149 ///
150 /// # Safety
151 ///
152 /// ## Implementor
153 ///
154 /// The trait implementor must guarantee that it is safe to convert the
155 /// provided `*mut (dyn Future<Output = T> + 'a)` into a `Pin<&mut (dyn
156 /// Future<Output = T> + 'a)>` and call methods on it, non-reentrantly,
157 /// until `UnsafeFutureObj::drop` is called with it.
into_raw(self) -> *mut (dyn Future<Output = T> + 'a)158 fn into_raw(self) -> *mut (dyn Future<Output = T> + 'a);
159
160 /// Drops the future represented by the given fat pointer.
161 ///
162 /// # Safety
163 ///
164 /// ## Implementor
165 ///
166 /// The trait implementor must guarantee that it is safe to call this
167 /// function once per `into_raw` invocation.
168 ///
169 /// ## Caller
170 ///
171 /// The caller must ensure:
172 ///
173 /// * the pointer passed was obtained from an `into_raw` invocation from
174 /// this same trait object
175 /// * the pointer is not currently in use as a `Pin<&mut (dyn Future<Output
176 /// = T> + 'a)>`
177 /// * the pointer must not be used again after this function is called
drop(ptr: *mut (dyn Future<Output = T> + 'a))178 unsafe fn drop(ptr: *mut (dyn Future<Output = T> + 'a));
179 }
180
181 unsafe impl<'a, T, F> UnsafeFutureObj<'a, T> for &'a mut F
182 where
183 F: Future<Output = T> + Unpin + 'a
184 {
into_raw(self) -> *mut (dyn Future<Output = T> + 'a)185 fn into_raw(self) -> *mut (dyn Future<Output = T> + 'a) {
186 self as *mut dyn Future<Output = T>
187 }
188
drop(_ptr: *mut (dyn Future<Output = T> + 'a))189 unsafe fn drop(_ptr: *mut (dyn Future<Output = T> + 'a)) {}
190 }
191
192 unsafe impl<'a, T> UnsafeFutureObj<'a, T> for &'a mut (dyn Future<Output = T> + Unpin + 'a)
193 {
into_raw(self) -> *mut (dyn Future<Output = T> + 'a)194 fn into_raw(self) -> *mut (dyn Future<Output = T> + 'a) {
195 self as *mut dyn Future<Output = T>
196 }
197
drop(_ptr: *mut (dyn Future<Output = T> + 'a))198 unsafe fn drop(_ptr: *mut (dyn Future<Output = T> + 'a)) {}
199 }
200
201 unsafe impl<'a, T, F> UnsafeFutureObj<'a, T> for Pin<&'a mut F>
202 where
203 F: Future<Output = T> + 'a
204 {
into_raw(self) -> *mut (dyn Future<Output = T> + 'a)205 fn into_raw(self) -> *mut (dyn Future<Output = T> + 'a) {
206 unsafe { self.get_unchecked_mut() as *mut dyn Future<Output = T> }
207 }
208
drop(_ptr: *mut (dyn Future<Output = T> + 'a))209 unsafe fn drop(_ptr: *mut (dyn Future<Output = T> + 'a)) {}
210 }
211
212 unsafe impl<'a, T> UnsafeFutureObj<'a, T> for Pin<&'a mut (dyn Future<Output = T> + 'a)>
213 {
into_raw(self) -> *mut (dyn Future<Output = T> + 'a)214 fn into_raw(self) -> *mut (dyn Future<Output = T> + 'a) {
215 unsafe { self.get_unchecked_mut() as *mut dyn Future<Output = T> }
216 }
217
drop(_ptr: *mut (dyn Future<Output = T> + 'a))218 unsafe fn drop(_ptr: *mut (dyn Future<Output = T> + 'a)) {}
219 }
220
221 #[cfg(feature = "alloc")]
222 mod if_alloc {
223 use super::*;
224 use alloc::boxed::Box;
225
226 unsafe impl<'a, T, F> UnsafeFutureObj<'a, T> for Box<F>
227 where F: Future<Output = T> + 'a
228 {
into_raw(self) -> *mut (dyn Future<Output = T> + 'a)229 fn into_raw(self) -> *mut (dyn Future<Output = T> + 'a) {
230 Box::into_raw(self)
231 }
232
drop(ptr: *mut (dyn Future<Output = T> + 'a))233 unsafe fn drop(ptr: *mut (dyn Future<Output = T> + 'a)) {
234 drop(Box::from_raw(ptr as *mut F))
235 }
236 }
237
238 unsafe impl<'a, T: 'a> UnsafeFutureObj<'a, T> for Box<dyn Future<Output = T> + 'a> {
into_raw(self) -> *mut (dyn Future<Output = T> + 'a)239 fn into_raw(self) -> *mut (dyn Future<Output = T> + 'a) {
240 Box::into_raw(self)
241 }
242
drop(ptr: *mut (dyn Future<Output = T> + 'a))243 unsafe fn drop(ptr: *mut (dyn Future<Output = T> + 'a)) {
244 drop(Box::from_raw(ptr))
245 }
246 }
247
248 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)249 fn into_raw(self) -> *mut (dyn Future<Output = T> + 'a) {
250 Box::into_raw(self)
251 }
252
drop(ptr: *mut (dyn Future<Output = T> + 'a))253 unsafe fn drop(ptr: *mut (dyn Future<Output = T> + 'a)) {
254 drop(Box::from_raw(ptr))
255 }
256 }
257
258 unsafe impl<'a, T, F> UnsafeFutureObj<'a, T> for Pin<Box<F>>
259 where
260 F: Future<Output = T> + 'a
261 {
into_raw(mut self) -> *mut (dyn Future<Output = T> + 'a)262 fn into_raw(mut self) -> *mut (dyn Future<Output = T> + 'a) {
263 let ptr = unsafe { self.as_mut().get_unchecked_mut() as *mut _ };
264 mem::forget(self);
265 ptr
266 }
267
drop(ptr: *mut (dyn Future<Output = T> + 'a))268 unsafe fn drop(ptr: *mut (dyn Future<Output = T> + 'a)) {
269 drop(Pin::from(Box::from_raw(ptr)))
270 }
271 }
272
273 unsafe impl<'a, T: 'a> UnsafeFutureObj<'a, T> for Pin<Box<dyn Future<Output = T> + 'a>> {
into_raw(mut self) -> *mut (dyn Future<Output = T> + 'a)274 fn into_raw(mut self) -> *mut (dyn Future<Output = T> + 'a) {
275 let ptr = unsafe { self.as_mut().get_unchecked_mut() as *mut _ };
276 mem::forget(self);
277 ptr
278 }
279
drop(ptr: *mut (dyn Future<Output = T> + 'a))280 unsafe fn drop(ptr: *mut (dyn Future<Output = T> + 'a)) {
281 drop(Pin::from(Box::from_raw(ptr)))
282 }
283 }
284
285 unsafe impl<'a, T: 'a> UnsafeFutureObj<'a, T> for Pin<Box<dyn Future<Output = T> + Send + 'a>> {
into_raw(mut self) -> *mut (dyn Future<Output = T> + 'a)286 fn into_raw(mut self) -> *mut (dyn Future<Output = T> + 'a) {
287 let ptr = unsafe { self.as_mut().get_unchecked_mut() as *mut _ };
288 mem::forget(self);
289 ptr
290 }
291
drop(ptr: *mut (dyn Future<Output = T> + 'a))292 unsafe fn drop(ptr: *mut (dyn Future<Output = T> + 'a)) {
293 drop(Pin::from(Box::from_raw(ptr)))
294 }
295 }
296
297 impl<'a, F: Future<Output = ()> + Send + 'a> From<Box<F>> for FutureObj<'a, ()> {
from(boxed: Box<F>) -> Self298 fn from(boxed: Box<F>) -> Self {
299 Self::new(boxed)
300 }
301 }
302
303 impl<'a> From<Box<dyn Future<Output = ()> + Send + 'a>> for FutureObj<'a, ()> {
from(boxed: Box<dyn Future<Output = ()> + Send + 'a>) -> Self304 fn from(boxed: Box<dyn Future<Output = ()> + Send + 'a>) -> Self {
305 Self::new(boxed)
306 }
307 }
308
309 impl<'a, F: Future<Output = ()> + Send + 'a> From<Pin<Box<F>>> for FutureObj<'a, ()> {
from(boxed: Pin<Box<F>>) -> Self310 fn from(boxed: Pin<Box<F>>) -> Self {
311 Self::new(boxed)
312 }
313 }
314
315 impl<'a> From<Pin<Box<dyn Future<Output = ()> + Send + 'a>>> for FutureObj<'a, ()> {
from(boxed: Pin<Box<dyn Future<Output = ()> + Send + 'a>>) -> Self316 fn from(boxed: Pin<Box<dyn Future<Output = ()> + Send + 'a>>) -> Self {
317 Self::new(boxed)
318 }
319 }
320
321 impl<'a, F: Future<Output = ()> + 'a> From<Box<F>> for LocalFutureObj<'a, ()> {
from(boxed: Box<F>) -> Self322 fn from(boxed: Box<F>) -> Self {
323 Self::new(boxed)
324 }
325 }
326
327 impl<'a> From<Box<dyn Future<Output = ()> + 'a>> for LocalFutureObj<'a, ()> {
from(boxed: Box<dyn Future<Output = ()> + 'a>) -> Self328 fn from(boxed: Box<dyn Future<Output = ()> + 'a>) -> Self {
329 Self::new(boxed)
330 }
331 }
332
333 impl<'a, F: Future<Output = ()> + 'a> From<Pin<Box<F>>> for LocalFutureObj<'a, ()> {
from(boxed: Pin<Box<F>>) -> Self334 fn from(boxed: Pin<Box<F>>) -> Self {
335 Self::new(boxed)
336 }
337 }
338
339 impl<'a> From<Pin<Box<dyn Future<Output = ()> + 'a>>> for LocalFutureObj<'a, ()> {
from(boxed: Pin<Box<dyn Future<Output = ()> + 'a>>) -> Self340 fn from(boxed: Pin<Box<dyn Future<Output = ()> + 'a>>) -> Self {
341 Self::new(boxed)
342 }
343 }
344 }
345