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