@@ -14,9 +14,12 @@ use crate::value::Value;
1414
1515#[ cfg( feature = "async" ) ]
1616use {
17+ crate :: thread:: AsyncThread ,
1718 crate :: traits:: LuaNativeAsyncFn ,
1819 crate :: types:: AsyncCallback ,
1920 std:: future:: { self , Future } ,
21+ std:: pin:: Pin ,
22+ std:: task:: { Context , Poll } ,
2023} ;
2124
2225/// Handle to an internal Lua function.
@@ -128,7 +131,8 @@ impl Function {
128131 /// Returns a future that, when polled, calls `self`, passing `args` as function arguments,
129132 /// and drives the execution.
130133 ///
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.
132136 ///
133137 /// Requires `feature = "async"`
134138 ///
@@ -155,19 +159,18 @@ impl Function {
155159 /// [`AsyncThread`]: crate::AsyncThread
156160 #[ cfg( feature = "async" ) ]
157161 #[ 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 >
159163 where
160164 R : FromLuaMulti ,
161165 {
162166 let lua = self . 0 . lua . lock ( ) ;
163- let thread_res = unsafe {
167+ AsyncCallFuture ( unsafe {
164168 lua. create_recycled_thread ( self ) . and_then ( |th| {
165169 let mut th = th. into_async ( args) ?;
166170 th. set_recyclable ( true ) ;
167171 Ok ( th)
168172 } )
169- } ;
170- async move { thread_res?. await }
173+ } )
171174 }
172175
173176 /// Returns a function that, when called, calls `self`, passing `args` as the first set of
@@ -644,6 +647,26 @@ impl LuaType for Function {
644647 const TYPE_ID : c_int = ffi:: LUA_TFUNCTION ;
645648}
646649
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+
647670#[ cfg( test) ]
648671mod assertions {
649672 use super :: * ;
@@ -652,4 +675,7 @@ mod assertions {
652675 static_assertions:: assert_not_impl_any!( Function : Send ) ;
653676 #[ cfg( feature = "send" ) ]
654677 static_assertions:: assert_impl_all!( Function : Send , Sync ) ;
678+
679+ #[ cfg( all( feature = "async" , feature = "send" ) ) ]
680+ static_assertions:: assert_impl_all!( AsyncCallFuture <( ) >: Send ) ;
655681}
0 commit comments