C Generator Panics on Case-Variant Function Names
Summary
The C code generator in wit-bindgen panics with "duplicate symbols" error when processing valid WIT files that contain function names differing only in case.
Environment
- wit-bindgen version: 0.47.0
- Affected generator: C
- OS: Ubuntu 22.04, x86-64
Steps to Reproduce
-
Create a minimal WIT file
Save the following as
test.wit:package poc:demo; world example { export get-user: func() -> string; export GET-USER: func() -> string; } -
Run wit-bindgen C generator
wit-bindgen c --out-dir /tmp/test test.wit -
Observe the panic
thread 'main' panicked at crates/c/src/lib.rs:1899:38: duplicate symbols: "name `exports_example_get_user` already defined" note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace -
Verify Rust generator works correctly
wit-bindgen rust --out-dir /tmp/test_rust test.witResult: Successfully generates code without errors.
This is invalid WIT. WIT identifiers are case-insensitive and normalize to lowercase:
Each name must be case-insensitively unique in the scope in which it is
declared. In the case of worlds, all imported names are in the same scope,
but separate from all the export names, and thus the same name can *not* be
imported twice, but *can* be both imported and exported.
https://github.com/WebAssembly/component-model/blob/66c925632bbf718671aec851ba4e6b65dbd35ac5/design/mvp/WIT.md?plain=1#L260-L263
Thanks for the clarification and the spec link — that helps.
One question though: the same invalid WIT is accepted by the Rust generator but causes an internal panic in the C generator. If the file is invalid, shouldn’t wit-bindgen reject it during parsing so all backends behave consistently? Right now Rust succeeds while C errors, which is a bit confusing.
@alexcrichton this might be a wit-parser issue, we should be pushing up the case-insensitive validation to there, per the spec Bailey cites above
Yeah pushing this sort of validation into wit-parser seems fine to me. Having one generator accept this and another reject it is sort of like "UB" where one behavior isn't really more right than the other because in the end it's all invalid anyway. Historically wit-parser has been more lax on the validation side because the actual component validator is the load bearing component there. Moving more validation into wit-parser and declaring, early on, that this is an invalid WIT document sounds like good idea to me.