1
1
use core:: {
2
+ mem,
2
3
fmt,
3
4
future:: Future ,
4
5
marker:: PhantomData ,
@@ -13,22 +14,33 @@ use core::{
13
14
/// take `dyn Trait` by value and `Box<dyn Trait>` is not available in no_std
14
15
/// contexts.
15
16
pub struct LocalFutureObj < ' a , T > {
16
- ptr : * mut ( ) ,
17
- poll_fn : unsafe fn ( * mut ( ) , & mut Context < ' _ > ) -> Poll < T > ,
18
- drop_fn : unsafe fn ( * mut ( ) ) ,
17
+ future : * mut ( dyn Future < Output = T > + ' static ) ,
18
+ drop_fn : unsafe fn ( * mut ( dyn Future < Output = T > + ' static ) ) ,
19
19
_marker : PhantomData < & ' a ( ) > ,
20
20
}
21
21
22
22
impl < T > Unpin for LocalFutureObj < ' _ , T > { }
23
23
24
+ #[ allow( clippy:: transmute_ptr_to_ptr) ]
25
+ unsafe fn remove_future_lifetime < ' a , T > ( ptr : * mut ( dyn Future < Output = T > + ' a ) )
26
+ -> * mut ( dyn Future < Output = T > + ' static )
27
+ {
28
+ mem:: transmute ( ptr)
29
+ }
30
+
31
+ unsafe fn remove_drop_lifetime < ' a , T > ( ptr : unsafe fn ( * mut ( dyn Future < Output = T > + ' a ) ) )
32
+ -> unsafe fn ( * mut ( dyn Future < Output = T > + ' static ) )
33
+ {
34
+ mem:: transmute ( ptr)
35
+ }
36
+
24
37
impl < ' a , T > LocalFutureObj < ' a , T > {
25
38
/// Create a `LocalFutureObj` from a custom trait object representation.
26
39
#[ inline]
27
40
pub fn new < F : UnsafeFutureObj < ' a , T > + ' a > ( f : F ) -> LocalFutureObj < ' a , T > {
28
41
LocalFutureObj {
29
- ptr : f. into_raw ( ) ,
30
- poll_fn : F :: poll,
31
- drop_fn : F :: drop,
42
+ future : unsafe { remove_future_lifetime ( f. into_raw ( ) ) } ,
43
+ drop_fn : unsafe { remove_drop_lifetime ( F :: drop) } ,
32
44
_marker : PhantomData ,
33
45
}
34
46
}
@@ -61,17 +73,17 @@ impl<T> Future for LocalFutureObj<'_, T> {
61
73
type Output = T ;
62
74
63
75
#[ inline]
64
- fn poll ( self : Pin < & mut Self > , cx : & mut Context < ' _ > ) -> Poll < T > {
76
+ fn poll ( mut self : Pin < & mut Self > , cx : & mut Context < ' _ > ) -> Poll < T > {
65
77
unsafe {
66
- ( ( * self ) . poll_fn ) ( ( * self ) . ptr , cx)
78
+ Pin :: new_unchecked ( & mut * self . future ) . poll ( cx)
67
79
}
68
80
}
69
81
}
70
82
71
83
impl < T > Drop for LocalFutureObj < ' _ , T > {
72
84
fn drop ( & mut self ) {
73
85
unsafe {
74
- ( self . drop_fn ) ( self . ptr )
86
+ ( self . drop_fn ) ( self . future )
75
87
}
76
88
}
77
89
}
@@ -119,115 +131,174 @@ impl<T> Future for FutureObj<'_, T> {
119
131
}
120
132
121
133
/// A custom implementation of a future trait object for `FutureObj`, providing
122
- /// a hand-rolled vtable.
134
+ /// a vtable with drop support .
123
135
///
124
136
/// This custom representation is typically used only in `no_std` contexts,
125
137
/// where the default `Box`-based implementation is not available.
126
138
///
127
- /// The implementor must guarantee that it is safe to call `poll` repeatedly (in
128
- /// a non-concurrent fashion) with the result of `into_raw` until `drop` is
129
- /// called.
139
+ /// # Safety
140
+ ///
141
+ /// See the safety notes on individual methods for what guarantees an
142
+ /// implementor must provide.
130
143
pub unsafe trait UnsafeFutureObj < ' a , T > : ' a {
131
- /// Convert an owned instance into a (conceptually owned) void pointer.
132
- fn into_raw ( self ) -> * mut ( ) ;
133
-
134
- /// Poll the future represented by the given void pointer.
144
+ /// Convert an owned instance into a (conceptually owned) fat pointer.
135
145
///
136
146
/// # Safety
137
147
///
138
- /// The trait implementor must guarantee that it is safe to repeatedly call
139
- /// `poll` with the result of `into_raw` until `drop` is called; such calls
140
- /// are not, however, allowed to race with each other or with calls to
141
- /// `drop`.
142
- unsafe fn poll ( ptr : * mut ( ) , cx : & mut Context < ' _ > ) -> Poll < T > ;
148
+ /// ## Implementor
149
+ ///
150
+ /// The trait implementor must guarantee that it is safe to convert the
151
+ /// provided `*mut (dyn Future<Output = T> + 'a)` into a `Pin<&mut (dyn
152
+ /// Future<Output = T> + 'a)>` and call methods on it, non-reentrantly,
153
+ /// until `UnsafeFutureObj::drop` is called with it.
154
+ fn into_raw ( self ) -> * mut ( dyn Future < Output = T > + ' a ) ;
143
155
144
- /// Drops the future represented by the given void pointer.
156
+ /// Drops the future represented by the given fat pointer.
145
157
///
146
158
/// # Safety
147
159
///
160
+ /// ## Implementor
161
+ ///
148
162
/// The trait implementor must guarantee that it is safe to call this
149
- /// function once per `into_raw` invocation; that call cannot race with
150
- /// other calls to `drop` or `poll`.
151
- unsafe fn drop ( ptr : * mut ( ) ) ;
163
+ /// function once per `into_raw` invocation.
164
+ ///
165
+ /// ## Caller
166
+ ///
167
+ /// The caller must ensure:
168
+ ///
169
+ /// * the pointer passed was obtained from an `into_raw` invocation from
170
+ /// this same trait object
171
+ /// * the pointer is not currently in use as a `Pin<&mut (dyn Future<Output
172
+ /// = T> + 'a)>`
173
+ /// * the pointer must not be used again after this function is called
174
+ unsafe fn drop ( ptr : * mut ( dyn Future < Output = T > + ' a ) ) ;
152
175
}
153
176
154
177
unsafe impl < ' a , T , F > UnsafeFutureObj < ' a , T > for & ' a mut F
155
178
where
156
179
F : Future < Output = T > + Unpin + ' a
157
180
{
158
- fn into_raw ( self ) -> * mut ( ) {
159
- self as * mut F as * mut ( )
181
+ fn into_raw ( self ) -> * mut ( dyn Future < Output = T > + ' a ) {
182
+ self as * mut dyn Future < Output = T >
160
183
}
161
184
162
- unsafe fn poll ( ptr : * mut ( ) , cx : & mut Context < ' _ > ) -> Poll < T > {
163
- let p: Pin < & mut F > = Pin :: new_unchecked ( & mut * ( ptr as * mut F ) ) ;
164
- F :: poll ( p, cx)
185
+ unsafe fn drop ( _ptr : * mut ( dyn Future < Output = T > + ' a ) ) { }
186
+ }
187
+
188
+ unsafe impl < ' a , T > UnsafeFutureObj < ' a , T > for & ' a mut ( dyn Future < Output = T > + Unpin + ' a )
189
+ {
190
+ fn into_raw ( self ) -> * mut ( dyn Future < Output = T > + ' a ) {
191
+ self as * mut dyn Future < Output = T >
165
192
}
166
193
167
- unsafe fn drop ( _ptr : * mut ( ) ) { }
194
+ unsafe fn drop ( _ptr : * mut ( dyn Future < Output = T > + ' a ) ) { }
168
195
}
169
196
170
197
unsafe impl < ' a , T , F > UnsafeFutureObj < ' a , T > for Pin < & ' a mut F >
171
198
where
172
199
F : Future < Output = T > + ' a
173
200
{
174
- fn into_raw ( mut self ) -> * mut ( ) {
175
- let mut_ref: & mut F = unsafe { Pin :: get_unchecked_mut ( self . as_mut ( ) ) } ;
176
- mut_ref as * mut F as * mut ( )
201
+ fn into_raw ( self ) -> * mut ( dyn Future < Output = T > + ' a ) {
202
+ unsafe { self . get_unchecked_mut ( ) as * mut dyn Future < Output = T > }
177
203
}
178
204
179
- unsafe fn poll ( ptr : * mut ( ) , cx : & mut Context < ' _ > ) -> Poll < T > {
180
- let future: Pin < & mut F > = Pin :: new_unchecked ( & mut * ( ptr as * mut F ) ) ;
181
- F :: poll ( future, cx)
205
+ unsafe fn drop ( _ptr : * mut ( dyn Future < Output = T > + ' a ) ) { }
206
+ }
207
+
208
+ unsafe impl < ' a , T > UnsafeFutureObj < ' a , T > for Pin < & ' a mut ( dyn Future < Output = T > + ' a ) >
209
+ {
210
+ fn into_raw ( self ) -> * mut ( dyn Future < Output = T > + ' a ) {
211
+ unsafe { self . get_unchecked_mut ( ) as * mut dyn Future < Output = T > }
182
212
}
183
213
184
- unsafe fn drop ( _ptr : * mut ( ) ) { }
214
+ unsafe fn drop ( _ptr : * mut ( dyn Future < Output = T > + ' a ) ) { }
185
215
}
186
216
187
217
#[ cfg( feature = "alloc" ) ]
188
218
mod if_alloc {
189
219
use super :: * ;
190
- use core:: mem;
191
220
use alloc:: boxed:: Box ;
192
221
193
222
unsafe impl < ' a , T , F > UnsafeFutureObj < ' a , T > for Box < F >
194
223
where F : Future < Output = T > + ' a
195
224
{
196
- fn into_raw ( self ) -> * mut ( ) {
197
- Box :: into_raw ( self ) as * mut ( )
225
+ fn into_raw ( self ) -> * mut ( dyn Future < Output = T > + ' a ) {
226
+ Box :: into_raw ( self )
198
227
}
199
228
200
- unsafe fn poll ( ptr : * mut ( ) , cx : & mut Context < ' _ > ) -> Poll < T > {
201
- let ptr = ptr as * mut F ;
202
- let pin: Pin < & mut F > = Pin :: new_unchecked ( & mut * ptr) ;
203
- F :: poll ( pin, cx)
229
+ unsafe fn drop ( ptr : * mut ( dyn Future < Output = T > + ' a ) ) {
230
+ drop ( Box :: from_raw ( ptr as * mut F ) )
204
231
}
232
+ }
205
233
206
- unsafe fn drop ( ptr : * mut ( ) ) {
207
- drop ( Box :: from_raw ( ptr as * mut F ) )
234
+ unsafe impl < ' a , T : ' a > UnsafeFutureObj < ' a , T > for Box < dyn Future < Output = T > + ' a > {
235
+ fn into_raw ( self ) -> * mut ( dyn Future < Output = T > + ' a ) {
236
+ Box :: into_raw ( self )
237
+ }
238
+
239
+ unsafe fn drop ( ptr : * mut ( dyn Future < Output = T > + ' a ) ) {
240
+ drop ( Box :: from_raw ( ptr) )
241
+ }
242
+ }
243
+
244
+ unsafe impl < ' a , T : ' a > UnsafeFutureObj < ' a , T > for Box < dyn Future < Output = T > + Send + ' a > {
245
+ fn into_raw ( self ) -> * mut ( dyn Future < Output = T > + ' a ) {
246
+ Box :: into_raw ( self )
247
+ }
248
+
249
+ unsafe fn drop ( ptr : * mut ( dyn Future < Output = T > + ' a ) ) {
250
+ drop ( Box :: from_raw ( ptr) )
208
251
}
209
252
}
210
253
211
254
unsafe impl < ' a , T , F > UnsafeFutureObj < ' a , T > for Pin < Box < F > >
212
255
where
213
256
F : Future < Output = T > + ' a
214
257
{
215
- fn into_raw ( mut self ) -> * mut ( ) {
216
- let mut_ref: & mut F = unsafe { Pin :: get_unchecked_mut ( self . as_mut ( ) ) } ;
217
- let ptr = mut_ref as * mut F as * mut ( ) ;
218
- mem:: forget ( self ) ; // Don't drop the box
258
+ fn into_raw ( mut self ) -> * mut ( dyn Future < Output = T > + ' a ) {
259
+ let ptr = unsafe { self . as_mut ( ) . get_unchecked_mut ( ) as * mut _ } ;
260
+ mem:: forget ( self ) ;
261
+ ptr
262
+ }
263
+
264
+ unsafe fn drop ( ptr : * mut ( dyn Future < Output = T > + ' a ) ) {
265
+ drop ( Pin :: from ( Box :: from_raw ( ptr) ) )
266
+ }
267
+ }
268
+
269
+ unsafe impl < ' a , T : ' a > UnsafeFutureObj < ' a , T > for Pin < Box < dyn Future < Output = T > + ' a > > {
270
+ fn into_raw ( mut self ) -> * mut ( dyn Future < Output = T > + ' a ) {
271
+ let ptr = unsafe { self . as_mut ( ) . get_unchecked_mut ( ) as * mut _ } ;
272
+ mem:: forget ( self ) ;
273
+ ptr
274
+ }
275
+
276
+ unsafe fn drop ( ptr : * mut ( dyn Future < Output = T > + ' a ) ) {
277
+ drop ( Pin :: from ( Box :: from_raw ( ptr) ) )
278
+ }
279
+ }
280
+
281
+ unsafe impl < ' a , T : ' a > UnsafeFutureObj < ' a , T > for Pin < Box < dyn Future < Output = T > + Send + ' a > > {
282
+ fn into_raw ( mut self ) -> * mut ( dyn Future < Output = T > + ' a ) {
283
+ let ptr = unsafe { self . as_mut ( ) . get_unchecked_mut ( ) as * mut _ } ;
284
+ mem:: forget ( self ) ;
219
285
ptr
220
286
}
221
287
222
- unsafe fn poll ( ptr : * mut ( ) , cx : & mut Context < ' _ > ) -> Poll < T > {
223
- let ptr = ptr as * mut F ;
224
- let pin: Pin < & mut F > = Pin :: new_unchecked ( & mut * ptr) ;
225
- F :: poll ( pin, cx)
288
+ unsafe fn drop ( ptr : * mut ( dyn Future < Output = T > + ' a ) ) {
289
+ drop ( Pin :: from ( Box :: from_raw ( ptr) ) )
290
+ }
291
+ }
292
+
293
+ impl < ' a , F : Future < Output = ( ) > + Send + ' a > From < Box < F > > for FutureObj < ' a , ( ) > {
294
+ fn from ( boxed : Box < F > ) -> Self {
295
+ FutureObj :: new ( boxed)
226
296
}
297
+ }
227
298
228
- unsafe fn drop ( ptr : * mut ( ) ) {
229
- # [ allow ( clippy :: cast_ptr_alignment ) ]
230
- drop ( Pin :: from ( Box :: from_raw ( ptr as * mut F ) ) ) ;
299
+ impl < ' a > From < Box < dyn Future < Output = ( ) > + Send + ' a > > for FutureObj < ' a , ( ) > {
300
+ fn from ( boxed : Box < dyn Future < Output = ( ) > + Send + ' a > ) -> Self {
301
+ FutureObj :: new ( boxed )
231
302
}
232
303
}
233
304
@@ -237,20 +308,32 @@ mod if_alloc {
237
308
}
238
309
}
239
310
240
- impl < ' a , F : Future < Output = ( ) > + Send + ' a > From < Box < F > > for FutureObj < ' a , ( ) > {
241
- fn from ( boxed : Box < F > ) -> Self {
311
+ impl < ' a > From < Pin < Box < dyn Future < Output = ( ) > + Send + ' a > > > for FutureObj < ' a , ( ) > {
312
+ fn from ( boxed : Pin < Box < dyn Future < Output = ( ) > + Send + ' a > > ) -> Self {
242
313
FutureObj :: new ( boxed)
243
314
}
244
315
}
245
316
317
+ impl < ' a , F : Future < Output = ( ) > + ' a > From < Box < F > > for LocalFutureObj < ' a , ( ) > {
318
+ fn from ( boxed : Box < F > ) -> Self {
319
+ LocalFutureObj :: new ( boxed)
320
+ }
321
+ }
322
+
323
+ impl < ' a > From < Box < dyn Future < Output = ( ) > + ' a > > for LocalFutureObj < ' a , ( ) > {
324
+ fn from ( boxed : Box < dyn Future < Output = ( ) > + ' a > ) -> Self {
325
+ LocalFutureObj :: new ( boxed)
326
+ }
327
+ }
328
+
246
329
impl < ' a , F : Future < Output = ( ) > + ' a > From < Pin < Box < F > > > for LocalFutureObj < ' a , ( ) > {
247
330
fn from ( boxed : Pin < Box < F > > ) -> Self {
248
331
LocalFutureObj :: new ( boxed)
249
332
}
250
333
}
251
334
252
- impl < ' a , F : Future < Output = ( ) > + ' a > From < Box < F > > for LocalFutureObj < ' a , ( ) > {
253
- fn from ( boxed : Box < F > ) -> Self {
335
+ impl < ' a > From < Pin < Box < dyn Future < Output = ( ) > + ' a > > > for LocalFutureObj < ' a , ( ) > {
336
+ fn from ( boxed : Pin < Box < dyn Future < Output = ( ) > + ' a > > ) -> Self {
254
337
LocalFutureObj :: new ( boxed)
255
338
}
256
339
}
0 commit comments