Summary:wit-bindgen-cpp encodes wrong enum discriminant for enum payload inside variant inside option, producing incorrect values.
Bug report: C++ consumers generated by wit-bindgen-cpp lift/lower the enum case inside an option-wrapped variant with a wrong discriminant (e3 becomes e1), yielding wrong output values regardless of provider language.
Environment
| component |
version |
| OS |
macOS 15.7 (Darwin 24.6.0), x86_64 |
| jco |
1.16.1 (source checkout, tag jco-v1.16.1) |
| Node.js |
v22.22.2 |
| wac |
wac-cli 0.8.1 |
| wasi-sdk |
27.0 (wasm32-wasip2-clang/clang++) |
Steps to reproduce
The full chain is: compile the guest sources into a provider component and a consumer component, compose them with wac, then run the composed component. Prebuilt copies of every artifact are included (components/provider.wasm, components/consumer.wasm, composed.wasm), so you can also skip straight to step 5.
Github repo:https://github.com/xiaozzzZZzzz240/G028-Cplusplus-bindings-return-e1-instead-of-e3-for-enum-payload-in-option
-
Clone this repository:
git clone <THIS_REPO_URL>
cd <THIS_REPO_DIR>
-
Compile the provider component from the C sources in src/provider-C/ (toolchain versions in the table above; the WIT package is in wit/):
wasm32-wasip2-clang -o components/provider.wasm -mexec-model=reactor src/provider-C/world9-wi7n9u47_generated.c src/provider-C/world9_wi7n9u47.c src/provider-C/world9_wi7n9u47_component_type.o
-
Compile the consumer component from the C++ sources in src/consumer-Cpp/:
wasm32-wasip2-clang++ -std=c++23 -fno-exceptions -o components/consumer.wasm -mexec-model=reactor src/consumer-Cpp/world9b-mul38v8w_generated.cpp src/consumer-Cpp/world9b_mul38v8w.cpp src/consumer-Cpp/world9b_mul38v8w_component_type.o
-
Compose the two components into one runnable component with wac 0.8.1:
wac plug components/consumer.wasm --plug components/provider.wasm -o composed.wasm
-
Run the composed component with jco:
npm install -g @bytecodealliance/jco@1.16.1
jco run composed.wasm
Expected result
The composed component should print exactly the following, then exit 0:
"resinst0"
"resinst1"
"resinst2"
"resinst0"
resource("temres36")
"c2"
true
"c0"
resource("temres39")
(resource("temres40"), "bar")
"c2"
true
"temres39"
"temres44"
some([c1(enum(e3))])
resource("temres6")
"c0"
true
7
true
Actual result
Under jco the same composed.wasm exits with rc=0. stdout:
"resinst0"
"resinst1"
"resinst2"
"resinst0"
resource("temres36")
"c2"
true
"c0"
resource("temres39")
(resource("temres40"), "bar")
"c2"
true
"temres39"
"temres44"
some([c1(enum(e1))])
resource("temres6")
"c0"
true
7
true
stderr:
wasmtime on the exact same file: rc=0
"resinst0"
"resinst1"
"resinst2"
"resinst0"
resource("temres36")
"c2"
true
"c0"
resource("temres39")
(resource("temres40"), "bar")
"c2"
true
"temres39"
"temres44"
some([c1(enum(e1))])
resource("temres6")
"c0"
true
7
true
Both executing result in jco and wasmtime are not as expected.
Summary:wit-bindgen-cpp encodes wrong enum discriminant for enum payload inside variant inside option, producing incorrect values.
Bug report: C++ consumers generated by wit-bindgen-cpp lift/lower the enum case inside an option-wrapped variant with a wrong discriminant (e3 becomes e1), yielding wrong output values regardless of provider language.
Environment
Steps to reproduce
The full chain is: compile the guest sources into a provider component and a consumer component, compose them with
wac, then run the composed component. Prebuilt copies of every artifact are included (components/provider.wasm,components/consumer.wasm,composed.wasm), so you can also skip straight to step 5.Github repo:https://github.com/xiaozzzZZzzz240/G028-Cplusplus-bindings-return-e1-instead-of-e3-for-enum-payload-in-option
Clone this repository:
Compile the provider component from the C sources in
src/provider-C/(toolchain versions in the table above; the WIT package is inwit/):wasm32-wasip2-clang -o components/provider.wasm -mexec-model=reactor src/provider-C/world9-wi7n9u47_generated.c src/provider-C/world9_wi7n9u47.c src/provider-C/world9_wi7n9u47_component_type.oCompile the consumer component from the C++ sources in
src/consumer-Cpp/:wasm32-wasip2-clang++ -std=c++23 -fno-exceptions -o components/consumer.wasm -mexec-model=reactor src/consumer-Cpp/world9b-mul38v8w_generated.cpp src/consumer-Cpp/world9b_mul38v8w.cpp src/consumer-Cpp/world9b_mul38v8w_component_type.oCompose the two components into one runnable component with wac 0.8.1:
wac plug components/consumer.wasm --plug components/provider.wasm -o composed.wasmRun the composed component with jco:
Expected result
The composed component should print exactly the following, then exit 0:
Actual result
Under jco the same
composed.wasmexits with rc=0. stdout:stderr:
wasmtime on the exact same file: rc=0
Both executing result in jco and wasmtime are not as expected.