@@ -14,9 +14,12 @@ use crate::value::Value;
14
14
15
15
#[ cfg( feature = "async" ) ]
16
16
use {
17
+ crate :: thread:: AsyncThread ,
17
18
crate :: traits:: LuaNativeAsyncFn ,
18
19
crate :: types:: AsyncCallback ,
19
20
std:: future:: { self , Future } ,
21
+ std:: pin:: Pin ,
22
+ std:: task:: { Context , Poll } ,
20
23
} ;
21
24
22
25
/// Handle to an internal Lua function.
@@ -128,7 +131,8 @@ impl Function {
128
131
/// Returns a future that, when polled, calls `self`, passing `args` as function arguments,
129
132
/// and drives the execution.
130
133
///
131
- /// Internally it wraps the function to an [`AsyncThread`].
134
+ /// Internally it wraps the function to an [`AsyncThread`]. The returned type implements
135
+ /// `Future<Output = Result<R>>` and can be awaited.
132
136
///
133
137
/// Requires `feature = "async"`
134
138
///
@@ -155,19 +159,18 @@ impl Function {
155
159
/// [`AsyncThread`]: crate::AsyncThread
156
160
#[ cfg( feature = "async" ) ]
157
161
#[ cfg_attr( docsrs, doc( cfg( feature = "async" ) ) ) ]
158
- pub fn call_async < R > ( & self , args : impl IntoLuaMulti ) -> impl Future < Output = Result < R > >
162
+ pub fn call_async < R > ( & self , args : impl IntoLuaMulti ) -> AsyncCallFuture < R >
159
163
where
160
164
R : FromLuaMulti ,
161
165
{
162
166
let lua = self . 0 . lua . lock ( ) ;
163
- let thread_res = unsafe {
167
+ AsyncCallFuture ( unsafe {
164
168
lua. create_recycled_thread ( self ) . and_then ( |th| {
165
169
let mut th = th. into_async ( args) ?;
166
170
th. set_recyclable ( true ) ;
167
171
Ok ( th)
168
172
} )
169
- } ;
170
- async move { thread_res?. await }
173
+ } )
171
174
}
172
175
173
176
/// Returns a function that, when called, calls `self`, passing `args` as the first set of
@@ -644,6 +647,26 @@ impl LuaType for Function {
644
647
const TYPE_ID : c_int = ffi:: LUA_TFUNCTION ;
645
648
}
646
649
650
+ #[ cfg( feature = "async" ) ]
651
+ pub struct AsyncCallFuture < R : FromLuaMulti > ( Result < AsyncThread < R > > ) ;
652
+
653
+ #[ cfg( feature = "async" ) ]
654
+ impl < R : FromLuaMulti > Future for AsyncCallFuture < R > {
655
+ type Output = Result < R > ;
656
+
657
+ fn poll ( self : Pin < & mut Self > , cx : & mut Context < ' _ > ) -> Poll < Self :: Output > {
658
+ // Safety: We're not moving any pinned data
659
+ let this = unsafe { self . get_unchecked_mut ( ) } ;
660
+ match & mut this. 0 {
661
+ Ok ( thread) => {
662
+ let pinned_thread = unsafe { Pin :: new_unchecked ( thread) } ;
663
+ pinned_thread. poll ( cx)
664
+ }
665
+ Err ( err) => Poll :: Ready ( Err ( err. clone ( ) ) ) ,
666
+ }
667
+ }
668
+ }
669
+
647
670
#[ cfg( test) ]
648
671
mod assertions {
649
672
use super :: * ;
@@ -652,4 +675,7 @@ mod assertions {
652
675
static_assertions:: assert_not_impl_any!( Function : Send ) ;
653
676
#[ cfg( feature = "send" ) ]
654
677
static_assertions:: assert_impl_all!( Function : Send , Sync ) ;
678
+
679
+ #[ cfg( all( feature = "async" , feature = "send" ) ) ]
680
+ static_assertions:: assert_impl_all!( AsyncCallFuture <( ) >: Send ) ;
655
681
}
0 commit comments