11use core:: {
2+ mem,
23 fmt,
34 future:: Future ,
45 marker:: PhantomData ,
@@ -13,22 +14,32 @@ 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+ 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+
2436impl < ' a , T > LocalFutureObj < ' a , T > {
2537 /// Create a `LocalFutureObj` from a custom trait object representation.
2638 #[ inline]
2739 pub fn new < F : UnsafeFutureObj < ' a , T > + ' a > ( f : F ) -> LocalFutureObj < ' a , T > {
2840 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) } ,
3243 _marker : PhantomData ,
3344 }
3445 }
@@ -61,17 +72,17 @@ impl<T> Future for LocalFutureObj<'_, T> {
6172 type Output = T ;
6273
6374 #[ 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 > {
6576 unsafe {
66- ( ( * self ) . poll_fn ) ( ( * self ) . ptr , cx)
77+ Pin :: new_unchecked ( & mut * self . future ) . poll ( cx)
6778 }
6879 }
6980}
7081
7182impl < T > Drop for LocalFutureObj < ' _ , T > {
7283 fn drop ( & mut self ) {
7384 unsafe {
74- ( self . drop_fn ) ( self . ptr )
85+ ( self . drop_fn ) ( self . future )
7586 }
7687 }
7788}
@@ -119,115 +130,174 @@ impl<T> Future for FutureObj<'_, T> {
119130}
120131
121132/// A custom implementation of a future trait object for `FutureObj`, providing
122- /// a hand-rolled vtable.
133+ /// a vtable with drop support .
123134///
124135/// This custom representation is typically used only in `no_std` contexts,
125136/// where the default `Box`-based implementation is not available.
126137///
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.
130142pub 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.
135144 ///
136145 /// # Safety
137146 ///
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 ) ;
143154
144- /// Drops the future represented by the given void pointer.
155+ /// Drops the future represented by the given fat pointer.
145156 ///
146157 /// # Safety
147158 ///
159+ /// ## Implementor
160+ ///
148161 /// 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 ) ) ;
152174}
153175
154176unsafe impl < ' a , T , F > UnsafeFutureObj < ' a , T > for & ' a mut F
155177where
156178 F : Future < Output = T > + Unpin + ' a
157179{
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 >
160182 }
161183
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 >
165191 }
166192
167- unsafe fn drop ( _ptr : * mut ( ) ) { }
193+ unsafe fn drop ( _ptr : * mut ( dyn Future < Output = T > + ' a ) ) { }
168194}
169195
170196unsafe impl < ' a , T , F > UnsafeFutureObj < ' a , T > for Pin < & ' a mut F >
171197where
172198 F : Future < Output = T > + ' a
173199{
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 { self . get_unchecked_mut ( ) as * mut dyn Future < Output = T > }
177202 }
178203
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 { self . get_unchecked_mut ( ) as * mut dyn Future < Output = T > }
182211 }
183212
184- unsafe fn drop ( _ptr : * mut ( ) ) { }
213+ unsafe fn drop ( _ptr : * mut ( dyn Future < Output = T > + ' a ) ) { }
185214}
186215
187216#[ cfg( feature = "alloc" ) ]
188217mod if_alloc {
189218 use super :: * ;
190- use core:: mem;
191219 use alloc:: boxed:: Box ;
192220
193221 unsafe impl < ' a , T , F > UnsafeFutureObj < ' a , T > for Box < F >
194222 where F : Future < Output = T > + ' a
195223 {
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 )
198226 }
199227
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 ) )
204230 }
231+ }
205232
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) )
208250 }
209251 }
210252
211253 unsafe impl < ' a , T , F > UnsafeFutureObj < ' a , T > for Pin < Box < F > >
212254 where
213255 F : Future < Output = T > + ' a
214256 {
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
257+ fn into_raw ( mut self ) -> * mut ( dyn Future < Output = T > + ' a ) {
258+ let ptr = unsafe { self . as_mut ( ) . get_unchecked_mut ( ) as * mut _ } ;
259+ mem:: forget ( self ) ;
260+ ptr
261+ }
262+
263+ unsafe fn drop ( ptr : * mut ( dyn Future < Output = T > + ' a ) ) {
264+ drop ( Pin :: from ( Box :: from_raw ( ptr) ) )
265+ }
266+ }
267+
268+ unsafe impl < ' a , T : ' a > UnsafeFutureObj < ' a , T > for Pin < Box < dyn Future < Output = T > + ' a > > {
269+ fn into_raw ( mut self ) -> * mut ( dyn Future < Output = T > + ' a ) {
270+ let ptr = unsafe { self . as_mut ( ) . get_unchecked_mut ( ) as * mut _ } ;
271+ mem:: forget ( self ) ;
272+ ptr
273+ }
274+
275+ unsafe fn drop ( ptr : * mut ( dyn Future < Output = T > + ' a ) ) {
276+ drop ( Pin :: from ( Box :: from_raw ( ptr) ) )
277+ }
278+ }
279+
280+ unsafe impl < ' a , T : ' a > UnsafeFutureObj < ' a , T > for Pin < Box < dyn Future < Output = T > + Send + ' a > > {
281+ fn into_raw ( mut self ) -> * mut ( dyn Future < Output = T > + ' a ) {
282+ let ptr = unsafe { self . as_mut ( ) . get_unchecked_mut ( ) as * mut _ } ;
283+ mem:: forget ( self ) ;
219284 ptr
220285 }
221286
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)
287+ unsafe fn drop ( ptr : * mut ( dyn Future < Output = T > + ' a ) ) {
288+ drop ( Pin :: from ( Box :: from_raw ( ptr) ) )
289+ }
290+ }
291+
292+ impl < ' a , F : Future < Output = ( ) > + Send + ' a > From < Box < F > > for FutureObj < ' a , ( ) > {
293+ fn from ( boxed : Box < F > ) -> Self {
294+ FutureObj :: new ( boxed)
226295 }
296+ }
227297
228- unsafe fn drop ( ptr : * mut ( ) ) {
229- # [ allow ( clippy :: cast_ptr_alignment ) ]
230- drop ( Pin :: from ( Box :: from_raw ( ptr as * mut F ) ) ) ;
298+ impl < ' a > From < Box < dyn Future < Output = ( ) > + Send + ' a > > for FutureObj < ' a , ( ) > {
299+ fn from ( boxed : Box < dyn Future < Output = ( ) > + Send + ' a > ) -> Self {
300+ FutureObj :: new ( boxed )
231301 }
232302 }
233303
@@ -237,20 +307,32 @@ mod if_alloc {
237307 }
238308 }
239309
240- impl < ' a , F : Future < Output = ( ) > + Send + ' a > From < Box < F > > for FutureObj < ' a , ( ) > {
241- fn from ( boxed : Box < F > ) -> Self {
310+ impl < ' a > From < Pin < Box < dyn Future < Output = ( ) > + Send + ' a > > > for FutureObj < ' a , ( ) > {
311+ fn from ( boxed : Pin < Box < dyn Future < Output = ( ) > + Send + ' a > > ) -> Self {
242312 FutureObj :: new ( boxed)
243313 }
244314 }
245315
316+ impl < ' a , F : Future < Output = ( ) > + ' a > From < Box < F > > for LocalFutureObj < ' a , ( ) > {
317+ fn from ( boxed : Box < F > ) -> Self {
318+ LocalFutureObj :: new ( boxed)
319+ }
320+ }
321+
322+ impl < ' a > From < Box < dyn Future < Output = ( ) > + ' a > > for LocalFutureObj < ' a , ( ) > {
323+ fn from ( boxed : Box < dyn Future < Output = ( ) > + ' a > ) -> Self {
324+ LocalFutureObj :: new ( boxed)
325+ }
326+ }
327+
246328 impl < ' a , F : Future < Output = ( ) > + ' a > From < Pin < Box < F > > > for LocalFutureObj < ' a , ( ) > {
247329 fn from ( boxed : Pin < Box < F > > ) -> Self {
248330 LocalFutureObj :: new ( boxed)
249331 }
250332 }
251333
252- impl < ' a , F : Future < Output = ( ) > + ' a > From < Box < F > > for LocalFutureObj < ' a , ( ) > {
253- fn from ( boxed : Box < F > ) -> Self {
334+ impl < ' a > From < Pin < Box < dyn Future < Output = ( ) > + ' a > > > for LocalFutureObj < ' a , ( ) > {
335+ fn from ( boxed : Pin < Box < dyn Future < Output = ( ) > + ' a > > ) -> Self {
254336 LocalFutureObj :: new ( boxed)
255337 }
256338 }
0 commit comments