-
-
Notifications
You must be signed in to change notification settings - Fork 3.1k
Description
Zig Version
0.14.0
Steps to Reproduce and Observed Behavior
Encountered while trying to update zig-javascript-bridge to 0.14.0: scottredig/zig-javascript-bridge#12
Importing two functions with the same name and module in WASM is valid behavior, but currently either hits a wasm error for calling a function with invalid argument types, or hit an unreachable that appears to be related to an invalid @bitcast.
Minimal repro example:
const std = @import("std");
const Float = struct {
pub extern "foo" fn @"foo"(f32) void;
};
const Int = struct {
pub extern "foo" fn @"foo"(i32) void;
};
export fn main() void {
Float.foo(1);
Int.foo(2);
}With release small produces this wat file:
(module
(type $t0 (func (param f32)))
(type $t1 (func))
(type $t2 (func (param i64)))
(import "foo" "foo" (func $foo.foo (type $t0)))
(func $main (export "main") (type $t1)
(call $foo.foo
(f32.const 0x1p+0 (;=1;)))
(call $f2
(i64.const 2)))
(func $f2 (type $t2) (param $p0 i64)
(unreachable))
(memory $memory (export "memory") 16)
(global $g0 (mut i32) (i32.const 1048576)))As you can see, the main function will successfully call foo once, but the second call in unconditionally an unreachable.
Expected Behavior
One of two outcomes are reasonable here:
- This works, as it did in 0.13.0.
- This produces a compile error.
I personally advocate for it just working being the correct choice. Specifically, it should just create two different function imports with the same import name/module. The javascript environment will gladly import the same function but with different types. Since Javascript doesn't have static typing (and most number types become f64 in JS's type system anyways), it's perfectly legal to call the same Javascript functions with differently typed variables. I specifically encountered this in a function to log values, so really any value is legal here. Not allowing this behavior means more code/function variations on the javascript side, and possible incompatibility with WASM hosts which expect this behavior to be legal.
This also worked just fine in 0.13.0. This is the wat from the same source code but compiled by 0.13.0:
(module
(type $t0 (func (param f32)))
(type $t1 (func (param i32)))
(type $t2 (func))
(import "foo" "foo" (func $foo.foo (type $t0)))
(import "foo" "foo" (func $foo.foo_1 (type $t1)))
(func $main (export "main") (type $t2)
(call $foo.foo
(f32.const 0x1p+0 (;=1;)))
(call $foo.foo_1
(i32.const 2)))
(memory $memory (export "memory") 16)
(global $g0 (mut i32) (i32.const 1048576)))Producing a compile error would also be reasonable, though not preferred. Just making one of the functions (really, all but the first analyzed) error when called in runtime is rather silly :)