From b496f7606b7678dd5b5972b37199ecee376e2306 Mon Sep 17 00:00:00 2001 From: Victor Adossi Date: Sat, 16 Aug 2025 15:04:03 +0900 Subject: [PATCH 1/2] fix(core): result check for async function This commit fixes a check that was incorrectly looking at the CM level function in the case of an async guest import when determining whether it had the right results. The problem with the existing logic is that it was trying to check for a constraint on the wrong function -- the guest import being lowered rather than the core function underneath that. The case that makes this obvious was something like an `run: async func()` where the CM level function clearly has no result, but the underlying core function being async lifted must of course have a i32 status code as a result. --- crates/core/src/abi.rs | 34 +++++++++------------------------- 1 file changed, 9 insertions(+), 25 deletions(-) diff --git a/crates/core/src/abi.rs b/crates/core/src/abi.rs index 9c7e50780..21e6dc4fc 100644 --- a/crates/core/src/abi.rs +++ b/crates/core/src/abi.rs @@ -1115,7 +1115,7 @@ impl<'a, B: Bindgen> Generator<'a, B> { let mut offset = 0; for (_, ty) in func.params.iter() { let types = flat_types(self.resolve, ty, Some(max_flat_params)) - .expect("direct parameter load failed to produce types during generation of fn call"); + .expect(&format!("direct parameter load failed to produce types during generation of fn call (func name: '{}')", func.name)); for _ in 0..types.len() { self.emit(&Instruction::GetArg { nth: offset }); offset += 1; @@ -1134,29 +1134,13 @@ impl<'a, B: Bindgen> Generator<'a, B> { // interface function completes, so lowering is conditional // based on slightly different logic for the `task.return` // intrinsic. - let (lower_to_memory, async_flat_results) = match (variant, async_, &func.result) { - // Async guest imports return a i32 status code - ( - AbiVariant::GuestImport | AbiVariant::GuestImportAsync, - _is_async @ true, - None, - ) => { - unreachable!("async guest imports always return a result") - } - // Async guest imports return a i32 status code - ( - AbiVariant::GuestImport | AbiVariant::GuestImportAsync, - _is_async @ true, - Some(ty), - ) => { - // For async guest imports, we know whether we must lower results - // if there are no params (i.e. the usual out pointer wasn't even required) - // and we always know the return value will be a i32 status code - assert!(matches!(ty, Type::U32 | Type::S32)); - (sig.params.is_empty(), Some(Some(vec![WasmType::I32]))) - } - // All other async cases - (_, _is_async @ true, func_result) => { + // + // Note that in the async import case teh code below deals with the CM function being lowered, + // not the core function that is underneath that (i.e. func.result may be empty, + // where the associated core function underneath must have a i32 status code result) + let (lower_to_memory, async_flat_results) = match (async_, &func.result) { + // All async cases pass along the function results and flatten where necesary + (_is_async @ true, func_result) => { let results = match &func_result { Some(ty) => flat_types(self.resolve, ty, Some(max_flat_params)), None => Some(Vec::new()), @@ -1164,7 +1148,7 @@ impl<'a, B: Bindgen> Generator<'a, B> { (results.is_none(), Some(results)) } // All other non-async cases - (_, _is_async @ false, _) => (sig.retptr, None), + (_is_async @ false, _) => (sig.retptr, None), }; // This was dynamically allocated by the caller (or async start From 60ab23f91c7ce8efe49e824ac6085dab7b7b3dc1 Mon Sep 17 00:00:00 2001 From: Victor Adossi Date: Sat, 16 Aug 2025 15:22:02 +0900 Subject: [PATCH 2/2] fix(core): remove check on guests avoiding lowering --- crates/core/src/abi.rs | 12 ------------ 1 file changed, 12 deletions(-) diff --git a/crates/core/src/abi.rs b/crates/core/src/abi.rs index 21e6dc4fc..0b0a29c72 100644 --- a/crates/core/src/abi.rs +++ b/crates/core/src/abi.rs @@ -1172,18 +1172,6 @@ impl<'a, B: Bindgen> Generator<'a, B> { // Perform memory lowing of relevant results, including out pointers as well as traditional results match (lower_to_memory, sig.retptr, variant) { - // Async guest imports with do no lowering cannot have ret pointers - // not having to do lowering implies that there was no return pointer provided - (_lower_to_memory @ false, _has_ret_ptr @ true, AbiVariant::GuestImport) - if async_ => - { - unreachable!( - "async guest import cannot avoid lowering when a ret ptr is present ({async_note} func [{func_name}], variant {variant:#?})", - async_note = async_.then_some("async").unwrap_or("sync"), - func_name = func.name, - ) - } - // For sync calls, if no lowering to memory is required and there *is* a return pointer in use // then we need to lower then simply lower the result(s) and return that directly from the function. (_lower_to_memory @ false, _, _) => {