@@ -8,7 +8,6 @@ use wit_bindgen_core::{dealias, uwrite, uwriteln, wit_parser::*, Source};
88pub ( super ) struct FunctionBindgen < ' a , ' b > {
99 pub r#gen : & ' b mut InterfaceGenerator < ' a > ,
1010 params : Vec < String > ,
11- async_ : bool ,
1211 wasm_import_module : & ' b str ,
1312 pub src : Source ,
1413 blocks : Vec < String > ,
@@ -19,7 +18,6 @@ pub(super) struct FunctionBindgen<'a, 'b> {
1918 pub import_return_pointer_area_align : Alignment ,
2019 pub handle_decls : Vec < String > ,
2120 always_owned : bool ,
22- pub async_result_name : Option < String > ,
2321}
2422
2523pub const POINTER_SIZE_EXPRESSION : & str = "::core::mem::size_of::<*const u8>()" ;
@@ -28,14 +26,12 @@ impl<'a, 'b> FunctionBindgen<'a, 'b> {
2826 pub ( super ) fn new (
2927 r#gen : & ' b mut InterfaceGenerator < ' a > ,
3028 params : Vec < String > ,
31- async_ : bool ,
3229 wasm_import_module : & ' b str ,
3330 always_owned : bool ,
3431 ) -> FunctionBindgen < ' a , ' b > {
3532 FunctionBindgen {
3633 r#gen,
3734 params,
38- async_,
3935 wasm_import_module,
4036 src : Default :: default ( ) ,
4137 blocks : Vec :: new ( ) ,
@@ -46,7 +42,6 @@ impl<'a, 'b> FunctionBindgen<'a, 'b> {
4642 import_return_pointer_area_align : Default :: default ( ) ,
4743 handle_decls : Vec :: new ( ) ,
4844 always_owned,
49- async_result_name : None ,
5045 }
5146 }
5247
@@ -859,13 +854,35 @@ impl Bindgen for FunctionBindgen<'_, '_> {
859854 self . push_str ( ");\n " ) ;
860855 }
861856
862- Instruction :: CallInterface { func, .. } => {
863- if self . async_ {
864- self . push_str ( & format ! ( "let result = " ) ) ;
865- results. push ( "result" . into ( ) ) ;
866- } else {
867- self . let_results ( usize:: from ( func. result . is_some ( ) ) , results) ;
868- } ;
857+ Instruction :: CallInterface { func, async_ } => {
858+ let prev_src = mem:: replace ( self . src . as_mut_string ( ) , String :: new ( ) ) ;
859+
860+ self . let_results ( usize:: from ( func. result . is_some ( ) ) , results) ;
861+ // If this function has a result and it's async, then after
862+ // this instruction the result is going to be lowered. This
863+ // lowering must happen in terms of `&T`, so force the result
864+ // of this expression to have `&` in front.
865+ if func. result . is_some ( ) && * async_ {
866+ self . push_str ( "&" ) ;
867+ }
868+
869+ // Force evaluation of all arguments to happen in a sub-block
870+ // for this call. This is where `handle_decls` are pushed to
871+ // ensure that they're scoped to just this block. Additionally
872+ // this is where `prev_src` is pushed, just before the call.
873+ //
874+ // The purpose of this is to force `borrow<T>` arguments to get
875+ // dropped before the call to `task.return` that will happen
876+ // after an async call. For normal calls this happens because
877+ // the result of this function is returned directly, but for
878+ // async calls the return happens as part of this function as
879+ // a call to `task.return` via the `AsyncTaskReturn`
880+ // instruction.
881+ self . push_str ( "{\n " ) ;
882+ for decl in self . handle_decls . drain ( ..) {
883+ self . src . push_str ( & decl) ;
884+ }
885+ self . push_str ( & prev_src) ;
869886 let constructor_type = match & func. kind {
870887 FunctionKind :: Freestanding | FunctionKind :: AsyncFreestanding => {
871888 self . push_str ( & format ! ( "T::{}" , to_rust_ident( & func. name) ) ) ;
@@ -884,12 +901,7 @@ impl Bindgen for FunctionBindgen<'_, '_> {
884901 . as_deref ( )
885902 . unwrap ( )
886903 . to_upper_camel_case ( ) ;
887- let call = if self . async_ {
888- let async_support = self . r#gen . r#gen . async_support_path ( ) ;
889- format ! ( "{async_support}::futures::FutureExt::map(T::new" )
890- } else {
891- format ! ( "{ty}::new(T::new" , )
892- } ;
904+ let call = format ! ( "{ty}::new(T::new" ) ;
893905 self . push_str ( & call) ;
894906 Some ( ty)
895907 }
@@ -910,67 +922,19 @@ impl Bindgen for FunctionBindgen<'_, '_> {
910922 }
911923 }
912924 self . push_str ( ")" ) ;
913- if let Some ( ty) = constructor_type {
914- self . push_str ( & if self . async_ {
915- format ! ( ", {ty}::new)" )
916- } else {
917- ")" . into ( )
918- } ) ;
919- }
920- if self . async_ {
925+ if * async_ {
921926 self . push_str ( ".await" ) ;
922927 }
923- self . push_str ( ";\n " ) ;
924- }
925-
926- Instruction :: AsyncPostCallInterface { func } => {
927- let result = & operands[ 0 ] ;
928- self . async_result_name = Some ( result. clone ( ) ) ;
929- results. push ( "result" . into ( ) ) ;
930- let params = ( 0 ..usize:: from ( func. result . is_some ( ) ) )
931- . map ( |_| {
932- let tmp = self . tmp ( ) ;
933- let param = format ! ( "result{}" , tmp) ;
934- results. push ( param. clone ( ) ) ;
935- param
936- } )
937- . collect :: < Vec < _ > > ( )
938- . join ( ", " ) ;
939- let params = if func. result . is_none ( ) {
940- format ! ( "({params})" )
941- } else {
942- params
943- } ;
944- let async_support = self . r#gen . r#gen . async_support_path ( ) ;
945- // TODO: This relies on `abi::Generator` emitting
946- // `AsyncCallReturn` immediately after this instruction to
947- // complete the incomplete expression we generate here. We
948- // should refactor this so it's less fragile (e.g. have
949- // `abi::Generator` emit a `AsyncCallReturn` first, which would
950- // push a closure expression we can consume here).
951- //
952- // Also, see `InterfaceGenerator::generate_guest_export` for
953- // where we emit the open bracket corresponding to the `};` we
954- // emit here.
955- //
956- // The async-specific `Instruction`s will probably need to be
957- // refactored anyway once we start implementing support for
958- // other languages besides Rust.
959- uwriteln ! (
960- self . src,
961- "\
962- {result}
963- }};
964- let result = {async_support}::first_poll({result}, move |{params}| {{
965- "
966- ) ;
928+ if constructor_type. is_some ( ) {
929+ self . push_str ( ")" ) ;
930+ }
931+ self . push_str ( "\n };\n " ) ;
967932 }
968933
969- Instruction :: AsyncCallReturn { name, params } => {
934+ Instruction :: AsyncTaskReturn { name, params } => {
970935 let func = self . declare_import ( name, params, & [ ] ) ;
971936
972937 uwriteln ! ( self . src, "{func}({});" , operands. join( ", " ) ) ;
973- self . src . push_str ( "});\n " ) ;
974938 }
975939
976940 Instruction :: Flush { amt } => {
0 commit comments