malformed-c opened PR #13821 from malformed-c:fix-async-import-stub-and-diagnostics to bytecodealliance:main:
Fixes #13813.
func_new/func_wrapandfunc_new_async/func_wrap_asyncall construct aDynamicHostFn/StaticHostFnwithASYNC = false— onlyfunc_new_concurrent/func_wrap_concurrentconstruct one withASYNC = true. Trying to satisfy anasync func-typed import with the former (an easy mistake, sincefunc_new_async's name suggests it should work) always failed at instantiation with a bare"type mismatch with async", giving no indication of why or what to use instead.Two changes, both discussed in #13813:
- A new shared
typecheck_asynchelper (used by bothStaticHostFn::typecheckandDynamicHostFn::typecheck) names the specific mismatch and points at the correct API, in both directions.Linker::define_unknown_imports_as_trapsalways stubbed withfunc_new, so it could never stub an unsatisfiedasync funcimport at all — a component with one couldn't be instantiated even if the import was never called. It now stubs withfunc_new_concurrentwhen the import is async andConfig::concurrency_supportis enabled, falling back tofunc_new(and the improved error above) otherwise.Before / after
Manually satisfying an async import with
func_new_async(the issue's primary repro — a WIT world withconsume: async func(x: u32) -> string):Before:
Error: component imports instance `test:asyncnoresource/api`, but a matching implementation was not found in the linker Caused by: 0: instance export `consume` has the wrong type 1: type mismatch with asyncAfter:
Error: component imports instance `test:asyncnoresource/api`, but a matching implementation was not found in the linker Caused by: 0: instance export `consume` has the wrong type 1: type mismatch with async: this import is declared `async func` in WIT, but was satisfied with a sync-style host function (`func_new`/`func_wrap`, or `func_new_async`/`func_wrap_async` — despite the name, these implement a *sync*-WIT-typed function via blocking host code, not an `async func` import); use `func_new_concurrent`/`func_wrap_concurrent` instead
define_unknown_imports_as_trapson a component with an unsatisfied async import (nothing in the component even calls it):Before:
define_unknown_imports_as_trapsitself reports success (it happily stubs withfunc_newregardless of async-ness), but the component can never be instantiated — the confusing error above surfaces atinstantiate_asyncinstead.After:
define_unknown_imports_as_trapsstubs the import withfunc_new_concurrent, instantiation succeeds, and calling into the component only traps if the guest actually calls the unsatisfied import:calling probe() (should trap - consume() is stubbed): Err(error while executing at wasm backtrace: ... Caused by: unknown import: `test:asyncnoresource/api#consume` has not been defined )Testing
- New tests in
tests/all/component_model/missing_async.rs:func_new_async_cannot_satisfy_async_import,func_new_concurrent_cannot_satisfy_sync_import(checking the improved message text in both mismatch directions).- New test in
tests/all/component_model/linker.rs:linker_defines_unknown_async_imports_as_traps(checkingdefine_unknown_imports_as_traps+instantiate_asyncnow succeed for a component with an unsatisfied async func import + async interface method import) — confirmed this test fails with the original "type mismatch with async" error if thelinker.rschange alone is reverted.- Full
component_modeltest suite (224 tests) passes;cargo fmt --checkandcargo clippyclean; compiles cleanly both with and without thecomponent-model-asyncfeature.
malformed-c requested fitzgen for a review on PR #13821.
malformed-c requested wasmtime-core-reviewers for a review on PR #13821.
malformed-c updated PR #13821.
malformed-c edited PR #13821:
Fixes #13813.
func_new/func_wrapandfunc_new_async/func_wrap_asyncall build a host function withASYNC = false— onlyfunc_new_concurrent/func_wrap_concurrentsetASYNC = true. Satisfying anasync func-typed import with the former (easy to do by accident, sincefunc_new_async's name suggests it should work) failed at instantiation with a baretype mismatch with async, with no hint why or what to use instead.That's the first fix — a shared
typecheck_asynchelper names the specific mismatch and points at the right API, in both directions.The second is related:
Linker::define_unknown_imports_as_trapsalways stubbed withfunc_new, so it could never even stub (let alone instantiate) a component with an unsatisfied async import, whether or not the import was ever called. It now stubs withfunc_new_concurrentwhen the import is async andConfig::concurrency_supportis enabled, falling back tofunc_newotherwise.Before/after, using the issue's own repro (a WIT world with
consume: async func(x: u32) -> string):Manually satisfying it with
func_new_async:before: type mismatch with async after: type mismatch with async: this import is declared `async func` in WIT, but was satisfied with a sync-style host function (`func_new`/`func_wrap`, or `func_new_async`/`func_wrap_async` — despite the name, these implement a *sync*-WIT-typed function via blocking host code, not an `async func` import); use `func_new_concurrent`/`func_wrap_concurrent` insteadStubbing it via
define_unknown_imports_as_traps, where nothing in the component even calls it:before: define_unknown_imports_as_traps reports success, but instantiate_async fails outright with the confusing error above after: instantiates fine; calling into the component only traps if the guest actually calls the unsatisfied import ("unknown import: ... has not been defined")Added tests in
missing_async.rs(both mismatch directions) andlinker.rs(the stubbing fix) — confirmed the new linker test actually fails if just that half of the fix is reverted, so it's catching the real regression. Fullcomponent_modelsuite (224 tests) still green,cargo fmt/clippyclean, compiles with and without thecomponent-model-asyncfeature.
github-actions[bot] added the label wasmtime:api on PR #13821.
:thumbs_up: alexcrichton submitted PR review:
Thanks!
alexcrichton added PR #13821 component: improve async-mismatch diagnostics and stub async imports to the merge queue.
:check: alexcrichton merged PR #13821.
alexcrichton removed PR #13821 component: improve async-mismatch diagnostics and stub async imports from the merge queue.
Last updated: Jul 29 2026 at 05:03 UTC