Hey,
Could someone help me understand the async lifted export path in wit-bindgen, specifically this branch:
https://github.com/bytecodealliance/wit-bindgen/blob/main/crates/core/src/abi.rs#L1168
Trying to fold the code, my reading is that when sig.retptr == false and func.result.is_some(), this always emits self.lift(ty).
Should this take async_ into account? IIUC, for an async lifted export, the core return is either [] for stackful async or ['i32'] for callback/status code, and the actual component result is delivered via task.return. But this path seems to lift the core return as if it was the component result, regardless of async_.
Would a guard like this be more correct?
} else if !async_ {
if let Some(ty) = &func.result {
self.lift(ty)
}
}
At least this solved issues with async return types in jco for me but maybe I'm missing some invariant?
Thanks!
This might be another example of where wit-bindgen-core was updated to handle async for guest bindings, but not for host bindings, as @Victor Adossi discovered. I think Jco is the only thing that uses it for host bindings, so it wasn't on the radar until you and Victor started adding async support to Jco. Anyway, yeah, your proposed guard looks like a plausible improvement, although there may be other broken logic elsewhere, also.
Ah thanks for chiming in Joel -- yeah so I think we're definitely the only ones (still) who use it for guest bindings :) (maybe that will change in the future)...
That said I think this may have been something I forgot to change when I was adapting wit-bindgen-core in this case -- the code that you have there looks right to me @Tomasz Andrzejak and I think the logic is right, in the async case that should be a core return.
It may be worth just turning that area into an easier to read switch of all the relevant vars/cases.
OK, thanks! I will prepare a PR.
https://github.com/bytecodealliance/wit-bindgen/pull/1614
Last updated: Jun 01 2026 at 09:49 UTC