From 3e8b28ad80ed17550d489e4017775d9653a05df8 Mon Sep 17 00:00:00 2001 From: Evan Carroll Date: Tue, 14 Apr 2026 01:45:01 -0500 Subject: [PATCH] fix: problems introduced with patch to Rust. Rust patch rust-lang/rust#149868 introduced some breaking changes by removing `--allow-undefined` from WASM linker defaults. The compiler ignores `#[link(wasm_import_module)]` on non-C ABI, and these were never real WASM imports. The fix was to use `unsafe extern "C"` instead of `unsafe #declared_abi` on WASM. --- Cargo.lock | 4 ++-- Cargo.toml | 2 +- crates/wasm_split/Cargo.toml | 2 +- crates/wasm_split_cli/src/reloc.rs | 2 +- crates/wasm_split_macros/Cargo.toml | 2 +- crates/wasm_split_macros/src/lib.rs | 29 +++++++++++++++++++++++++++-- 6 files changed, 33 insertions(+), 8 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 1d9c5fe..26ee27c 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -539,7 +539,7 @@ dependencies = [ [[package]] name = "wasm_split_helpers" -version = "0.2.1" +version = "0.2.2" dependencies = [ "async-once-cell", "wasm_split_macros", @@ -547,7 +547,7 @@ dependencies = [ [[package]] name = "wasm_split_macros" -version = "0.2.1" +version = "0.2.2" dependencies = [ "base16", "quote", diff --git a/Cargo.toml b/Cargo.toml index 3c71cbf..a250eb3 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -25,4 +25,4 @@ categories = ["wasm", "web-programming"] # - when changing internals of `rt`, release a new minor version of the macro and bump the # version requirement here. # - when adjusting the macro without touching `rt`, release a new patch version of the macro. -wasm_split_macros = { version = ">= 0.2.1, < 0.3", path = "crates/wasm_split_macros" } +wasm_split_macros = { version = ">= 0.2.2, < 0.3", path = "crates/wasm_split_macros" } diff --git a/crates/wasm_split/Cargo.toml b/crates/wasm_split/Cargo.toml index 6b8eba5..8b9bde1 100644 --- a/crates/wasm_split/Cargo.toml +++ b/crates/wasm_split/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "wasm_split_helpers" -version = "0.2.1" +version = "0.2.2" authors.workspace = true categories.workspace = true edition.workspace = true diff --git a/crates/wasm_split_cli/src/reloc.rs b/crates/wasm_split_cli/src/reloc.rs index e40bb0e..3dfd6f5 100644 --- a/crates/wasm_split_cli/src/reloc.rs +++ b/crates/wasm_split_cli/src/reloc.rs @@ -147,7 +147,7 @@ fn get_indirect_functions( } let mut referenced_indirects = visible_functions.clone(); - for relocation in this.relocs.iter().flat_map(|(_, relocs)| relocs.iter()) { + for relocation in this.relocs.values().flat_map(|relocs| relocs.iter()) { use RelocationType::*; if !matches!( relocation.ty, diff --git a/crates/wasm_split_macros/Cargo.toml b/crates/wasm_split_macros/Cargo.toml index f59b11a..9abe1f5 100644 --- a/crates/wasm_split_macros/Cargo.toml +++ b/crates/wasm_split_macros/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "wasm_split_macros" -version = "0.2.1" +version = "0.2.2" authors.workspace = true categories.workspace = true edition.workspace = true diff --git a/crates/wasm_split_macros/src/lib.rs b/crates/wasm_split_macros/src/lib.rs index 185c844..693b6fa 100644 --- a/crates/wasm_split_macros/src/lib.rs +++ b/crates/wasm_split_macros/src/lib.rs @@ -194,6 +194,18 @@ pub fn wasm_split(args: TokenStream, input: TokenStream) -> TokenStream { ..item_fn.sig.clone() }; + // On WASM targets, we must use extern "C" for the import/export pair. + // #[link(wasm_import_module)] only creates proper WASM imports for + // non-Rust ABIs. Previously this worked because rustc passed + // --allow-undefined to wasm-ld by default, but rust-lang/rust#149868 + // removed that. Using extern "C" ensures the import is a real WASM + // import and the export has a matching ABI for wasm-split to link. + let wasm_export_sig = Signature { + abi: parse_quote!(extern "C"), + ident: impl_export_ident.clone(), + ..item_fn.sig.clone() + }; + let mut args = Vec::new(); for (i, param) in wrapper_sig.inputs.iter_mut().enumerate() { match param { @@ -287,16 +299,29 @@ pub fn wasm_split(args: TokenStream, input: TokenStream) -> TokenStream { } #(#attrs)* #vis #wrapper_sig { + // On WASM, use extern "C" so #[link(wasm_import_module)] creates + // a real WASM import (it is ignored on extern "Rust" blocks). #[cfg(target_family = "wasm")] #[link(wasm_import_module = #link_name)] - unsafe #declared_abi { + #[allow(improper_ctypes)] + unsafe extern "C" { // We rewrite calls to this function instead of actually calling it. We just need to link to it. The name is unique by hashing. #[unsafe(no_mangle)] safe #import_sig; } + // On WASM, the export must use extern "C" to match the import ABI. + #[cfg(target_family = "wasm")] + #(#attrs)* + #[allow(improper_ctypes_definitions)] + #[unsafe(no_mangle)] + #wasm_export_sig { + #(#stmts)* + } + + // On non-WASM targets, use the declared ABI (no import needed). + #[cfg(not(target_family = "wasm"))] #(#attrs)* - #[cfg_attr(target_family = "wasm", unsafe(no_mangle))] #export_sig { #(#stmts)* }