This tests whether is is viable to have an imported function with the same name as a function that is exported from an rlib which are both have the same name. In this case "call". It turns out that this is possible if at least one of them has name mangeling enabled.
cargo build --release --target wasm32-unknown-unknown
wasm2wat target/wasm32-unknown-unknown/release/contract.wasm
Yields the following module (some unrelated stuff was removed from the listing):
(module
(type (;0;) (func (result i32)))
(type (;1;) (func))
(import "seal0" "call" (func $_ZN8contract4seal4call17h598b41fa1bda15e7E (type 0)))
(func $start (type 1)
call $_ZN8contract4seal4call17h598b41fa1bda15e7E
drop
call $call
drop)
(func $call (type 0) (result i32)
i32.const 7)
(export "start" (func $start))
(export "call" (func $call))
We can see that the viability of this approach is based on the fact that we have name mangling for the imported function:
mod seal {
#[link(wasm_import_module = "seal0")]
extern "C" {
// Enable the no mangle attribute and this clashes with the "call" function from
// dep which results in this function never imported nor called. The result is that
// the "call" from dep is called two times.
// #[no_mangle]
pub fn call() -> u32;
}
}
Disabling mangling for the import butchers the module in that it calls the function from the "dep" dependy two times.
(module
(type (;0;) (func))
(type (;1;) (func (result i32)))
(func $start (type 0)
call $call
drop
call $call
drop)
(func $call (type 1) (result i32)
i32.const 7)
(export "start" (func $start))
(export "call" (func $call))
That said, there is no apparent reason to use #[no_mangle]
for the imported function. For
the dependency this was merely to emulate a C library.
Writing contracts in languages without name mangling should not be a problem, either.
C compilers support the import_name attribute.
Even if the embedder uses a non-prefixed imported function like call
we can avoid
clashed in C like this
// Add a prefix on import to avoid possible name clashes
uint32_t imported_call() __attribute__((import_module(<seal0>, import_name(<call>))));