AL+

Language: RO (română) EN (English)

Email us: paul@alplustech.com

A Wasm import needs its module as well as its symbol

Rust 1.91.1 repaired a Wasm import regression across crates. Preserve module and symbol identity in integration checks, beyond successful native compilation.

Citiți articolul în română

A WebAssembly import has an identity that a native-linking check may fail to exercise. When two imported functions share a symbol name but belong to different modules, the boundary must preserve both names through compilation and host execution. An integration check should make that distinction observable, especially when declarations live in separate Rust crates.

Looking back from November 2026, Rust 1.91.0 was announced on 30 October 2025. The 1.91.1 patch followed on 10 November, fixing two regressions introduced in 1.91.0. The Wasm fix is a precise example of why a patch release can matter to a narrow integration boundary even when most of an application's Rust source still compiles.

The module name carries meaning

The patch announcement explains that Wasm identifies imported functions using both a symbol name and a Wasm module name. Rust's #[link(wasm_import_module)] attribute customizes that module identity for an external block. The regression arose when the same symbol name was imported from different Wasm modules across multiple Rust crates. A single symbol string was insufficient to preserve the intended distinction.

The reported consequences included compilation failures with an import-module mismatch and incorrect function selection at runtime. The latter could cause undefined behavior, including crashes and silent data corruption. That distinction matters when assessing evidence: a linker failure is visible during the build, whereas wrong selection can leave a superficially successful artifact that still violates the host contract.

Rust 1.91.1 fixed that regression. The same release also fixed Cargo target-directory locking on illumos; that was a separate issue. Do not combine the two into a broad claim that all Rust linking or all build concurrency was broken. A maintenance decision should identify which reported condition intersects the product's actual toolchain and target.

Propose a fixture that makes mistaken identity visible

A useful proposed fixture would contain two import modules exposing the same function symbol. Put the import declarations across separate Rust crates so the check reaches the reported boundary. Have the host implementations return distinguishable expected results, then call both through the built Wasm artifact. If both calls accidentally resolve to one implementation, the expectation should fail clearly.

This is a proposed two-module, same-symbol fixture, not a performed test. No compiler was run and no regression was reproduced for this article. The proposal follows from the failure condition described in the patch announcement. Its exact implementation would need to match the application's target, linkage arrangement and host runtime before its result could support a release.

Choose simple behavior whose intended result can be explained without reproducing the application's entire business logic. The fixture's job is to expose import identity across a boundary. A complex calculation may obscure whether a failure comes from resolution or arithmetic. Distinct outputs let the reviewer see the contract the check is intended to protect.

Keep the generated artifact in the evidence chain. A test that calls only native replacements can demonstrate the fixture's arithmetic while never exercising Wasm imports. Similarly, inspecting declarations without instantiating the relevant artifact may miss wrong runtime binding. The chosen evidence should reach the stage where the reported failure could become observable.

Cross-crate structure belongs to the case

Moving every declaration into one crate to simplify a reproduction can remove an essential condition. The historical problem specifically crossed crate boundaries. Preserve that structure in the proposed fixture and explain why it exists. Otherwise a passing small example can provide false reassurance about a product whose declarations remain separated in dependencies.

Record the compiler version, target and relevant dependency resolution with any eventual result. If generated bindings or host configuration supply import names, retain those versions as well. The point is reproducibility of the boundary, not a long inventory for its own sake. A future compiler update should be comparable to the last working artifact and its host arrangement.

Also check what the host actually provides. An absent module, a misspelled symbol and incorrect compiler preservation of identity are different failures. A fixture should make the intended host mapping explicit enough to distinguish them. Otherwise an integration error may be blamed on a historical compiler regression that the current toolchain no longer contains.

This scope differs from the earlier article about Wasm generated-binding ABI compatibility. That discussion concerns calling conventions and matching callers with generated interfaces. Here the question is which imported function is selected when module namespaces differ. Matching argument representation does not establish correct import selection, and correct selection does not establish every calling-convention detail.

Most applications need a smaller assessment

The strongest counterargument is exposure. An application with no imported Wasm functions has no exposure to this particular imported-function regression. One without the same-name, different-module cross-crate pattern should not inherit a bespoke fixture merely because it uses Rust or WebAssembly. First establish whether the reported condition is present.

For an affected build, the historical patch supplies a repair boundary, not a recommendation to freeze indefinitely on 1.91.1 in November 2026. Select a currently appropriate supported toolchain and inspect relevant intervening changes. A known working pin can be a temporary containment decision, but its removal still needs an owner and evidence.

A product's integration checks should remain proportional to the interfaces it promises. A focused case is worthwhile when import identity is a real contract and the ordinary suite would miss it. If existing integration coverage already distinguishes both module implementations through the delivered artifact, adding a duplicate fixture may contribute little. Review what the evidence establishes before expanding the suite.

For software maintenance, request an exposure decision first: whether the application has the affected import shape, which toolchain built the artifact and what verifies host binding. If new coverage is needed, make module and symbol identity visible in its expected behavior. A passing native build alone cannot close a Wasm-specific question.