Context
Adding wit-bindgen fixtures for variants, options, and flavorful type families (issue #10) revealed that fusion + validation pass, but runtime execution traps due to corrupted string data in cross-component calls.
Reproduction
With fixtures generated from wit-bindgen v0.52.0:
cargo test --package meld-core --test wit_bindgen_runtime test_runtime_wit_bindgen_options
Observed behavior
options: option<string> roundtrip produces Some("189") instead of Some("foo")
flavorful: list-in-variant tests produce "\u{1e}\0\0" instead of "foo"
variants: variant types with string payloads produce corrupted data
The string pointer/length pairs are being read from wrong offsets or wrong memory after adapter lowering.
Root cause
The adapter code path for identifying pointer pairs in function parameters (collect_pointer_positions in parser.rs:1315-1343) explicitly ignores Option, Result, and Variant types:
// Scalars, options, results, resources — no pointer pairs at param level
_ => {}
In the Canonical ABI, option<string> flattens to [i32(discriminant), i32(ptr), i32(len)]. Since the resolver reports no pointer pairs for these types, the adapter does not copy the string data across memories. The callee receives a pointer that references the caller's memory, reading garbage.
Fix needed
collect_pointer_positions and collect_pointer_byte_offsets must recurse into:
Option<T> — discriminant at offset 0, then payload at offset 1
Result<T,E> — discriminant at offset 0, then ok/err payload at offset 1
Variant — discriminant at offset 0, then case payloads at offset 1
The adapter must emit conditional copy logic: only copy the pointer data when the discriminant indicates the variant is active (e.g., Some for option, Ok/Err for result).
This requires:
- Extending
pointer_pair_positions to include option/result/variant payloads
- Generating conditional
if discriminant == X then copy blocks in the adapter
- Handling the case where different variant arms have different layouts (e.g.,
result<string, u32>)
Affected code
meld-core/src/parser.rs: collect_pointer_positions, collect_pointer_byte_offsets
meld-core/src/adapter/fact.rs: generate_memory_copy_adapter, generate_retptr_adapter
meld-core/src/resolver.rs: collect_param_copy_layouts, collect_result_copy_layouts
STPA traceability
- SR-16 (recursive inner pointer fixup)
- LS-R-2 (CopyLayout misclassification)
- UCA-A-7 (wrong element stride)
Affected tests
Tests are currently handled with graceful degradation (log + skip):
test_runtime_wit_bindgen_variants
test_runtime_wit_bindgen_options
test_runtime_wit_bindgen_flavorful
Fusion (CoreModule + Component) tests pass for all three. ref #10
Context
Adding wit-bindgen fixtures for
variants,options, andflavorfultype families (issue #10) revealed that fusion + validation pass, but runtime execution traps due to corrupted string data in cross-component calls.Reproduction
With fixtures generated from wit-bindgen v0.52.0:
cargo test --package meld-core --test wit_bindgen_runtime test_runtime_wit_bindgen_optionsObserved behavior
options:option<string>roundtrip producesSome("189")instead ofSome("foo")flavorful: list-in-variant tests produce"\u{1e}\0\0"instead of"foo"variants: variant types with string payloads produce corrupted dataThe string pointer/length pairs are being read from wrong offsets or wrong memory after adapter lowering.
Root cause
The adapter code path for identifying pointer pairs in function parameters (
collect_pointer_positionsinparser.rs:1315-1343) explicitly ignoresOption,Result, andVarianttypes:In the Canonical ABI,
option<string>flattens to[i32(discriminant), i32(ptr), i32(len)]. Since the resolver reports no pointer pairs for these types, the adapter does not copy the string data across memories. The callee receives a pointer that references the caller's memory, reading garbage.Fix needed
collect_pointer_positionsandcollect_pointer_byte_offsetsmust recurse into:Option<T>— discriminant at offset 0, then payload at offset 1Result<T,E>— discriminant at offset 0, then ok/err payload at offset 1Variant— discriminant at offset 0, then case payloads at offset 1The adapter must emit conditional copy logic: only copy the pointer data when the discriminant indicates the variant is active (e.g.,
Somefor option,Ok/Errfor result).This requires:
pointer_pair_positionsto include option/result/variant payloadsif discriminant == X then copyblocks in the adapterresult<string, u32>)Affected code
meld-core/src/parser.rs:collect_pointer_positions,collect_pointer_byte_offsetsmeld-core/src/adapter/fact.rs:generate_memory_copy_adapter,generate_retptr_adaptermeld-core/src/resolver.rs:collect_param_copy_layouts,collect_result_copy_layoutsSTPA traceability
Affected tests
Tests are currently handled with graceful degradation (log + skip):
test_runtime_wit_bindgen_variantstest_runtime_wit_bindgen_optionstest_runtime_wit_bindgen_flavorfulFusion (CoreModule + Component) tests pass for all three. ref #10