11use core:: {
2+ mem,
23 fmt,
34 future:: Future ,
45 marker:: PhantomData ,
@@ -13,22 +14,33 @@ use core::{
1314/// take `dyn Trait` by value and `Box<dyn Trait>` is not available in no_std
1415/// contexts.
1516pub 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 ) ) ,
1919 _marker : PhantomData < & ' a ( ) > ,
2020}
2121
2222impl < T > Unpin for LocalFutureObj < ' _ , T > { }
2323
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+
2437impl < ' a , T > LocalFutureObj < ' a , T > {
2538 /// Create a `LocalFutureObj` from a custom trait object representation.
2639 #[ inline]
2740 pub fn new < F : UnsafeFutureObj < ' a , T > + ' a > ( f : F ) -> LocalFutureObj < ' a , T > {
2841 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) } ,
3244 _marker : PhantomData ,
3345 }
3446 }
@@ -61,17 +73,17 @@ impl<T> Future for LocalFutureObj<'_, T> {
6173 type Output = T ;
6274
6375 #[ 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 > {
6577 unsafe {
66- ( ( * self ) . poll_fn ) ( ( * self ) . ptr , cx)
78+ Pin :: new_unchecked ( & mut * self . future ) . poll ( cx)
6779 }
6880 }
6981}
7082
7183impl < T > Drop for LocalFutureObj < ' _ , T > {
7284 fn drop ( & mut self ) {
7385 unsafe {
74- ( self . drop_fn ) ( self . ptr )
86+ ( self . drop_fn ) ( self . future )
7587 }
7688 }
7789}
@@ -119,115 +131,174 @@ impl<T> Future for FutureObj<'_, T> {
119131}
120132
121133/// A custom implementation of a future trait object for `FutureObj`, providing
122- /// a hand-rolled vtable.
134+ /// a vtable with drop support .
123135///
124136/// This custom representation is typically used only in `no_std` contexts,
125137/// where the default `Box`-based implementation is not available.
126138///
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.
130143pub 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.
135145 ///
136146 /// # Safety
137147 ///
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 ) ;
143155
144- /// Drops the future represented by the given void pointer.
156+ /// Drops the future represented by the given fat pointer.
145157 ///
146158 /// # Safety
147159 ///
160+ /// ## Implementor
161+ ///
148162 /// 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 ) ) ;
152175}
153176
154177unsafe impl < ' a , T , F > UnsafeFutureObj < ' a , T > for & ' a mut F
155178where
156179 F : Future < Output = T > + Unpin + ' a
157180{
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 >
160183 }
161184
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 >
165192 }
166193
167- unsafe fn drop ( _ptr : * mut ( ) ) { }
194+ unsafe fn drop ( _ptr : * mut ( dyn Future < Output = T > + ' a ) ) { }
168195}
169196
170197unsafe impl < ' a , T , F > UnsafeFutureObj < ' a , T > for Pin < & ' a mut F >
171198where
172199 F : Future < Output = T > + ' a
173200{
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 > }
177203 }
178204
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 > }
182212 }
183213
184- unsafe fn drop ( _ptr : * mut ( ) ) { }
214+ unsafe fn drop ( _ptr : * mut ( dyn Future < Output = T > + ' a ) ) { }
185215}
186216
187217#[ cfg( feature = "alloc" ) ]
188218mod if_alloc {
189219 use super :: * ;
190- use core:: mem;
191220 use alloc:: boxed:: Box ;
192221
193222 unsafe impl < ' a , T , F > UnsafeFutureObj < ' a , T > for Box < F >
194223 where F : Future < Output = T > + ' a
195224 {
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 )
198227 }
199228
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 ) )
204231 }
232+ }
205233
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) )
208251 }
209252 }
210253
211254 unsafe impl < ' a , T , F > UnsafeFutureObj < ' a , T > for Pin < Box < F > >
212255 where
213256 F : Future < Output = T > + ' a
214257 {
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 ) ;
219285 ptr
220286 }
221287
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)
226296 }
297+ }
227298
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 )
231302 }
232303 }
233304
@@ -237,20 +308,32 @@ mod if_alloc {
237308 }
238309 }
239310
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 {
242313 FutureObj :: new ( boxed)
243314 }
244315 }
245316
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+
246329 impl < ' a , F : Future < Output = ( ) > + ' a > From < Pin < Box < F > > > for LocalFutureObj < ' a , ( ) > {
247330 fn from ( boxed : Pin < Box < F > > ) -> Self {
248331 LocalFutureObj :: new ( boxed)
249332 }
250333 }
251334
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 {
254337 LocalFutureObj :: new ( boxed)
255338 }
256339 }
0 commit comments