fix(355): --component lifts bare world exports with real signatures - #357
Conversation
fuse --component emitted an INVALID component for any non-empty export
signature: bare world exports (world root { export get-b: func(i:s32)->u32 })
were all lifted with an empty (func) type, so wasm-tools validate rejected the
output — silently, after 'Fusion complete!'.
Three latent defects, all fixed:
- parser.rs: record func export-aliases (ComponentFuncDef::ExportAlias) so the
component-function index space stays aligned with export.index (wit-component
interleaves canon lifts and export-aliases; the space was silently compacted,
so component_func_defs[export.index] mis-resolved).
- component_wrap.rs: carry the source export's lift type + options instead of
hardcoding func(); terminate a no-result func type (func_enc.result(None) was
never called → truncated type → decoder EOF); advance the bare-export
component-func index by 2 (lift + export-alias) so each export references its
own lift, not the previous export's alias.
- p3_stream.rs: handle the new ExportAlias variant (follow one hop).
Tests: component_bare_export_355.rs on avrabe's exact fixtures — valid component
+ correct per-export arities (get-b (1,1), set-b (2,0), ptr-b (0,1)). Full
meld-core suite green. SR-54; CHANGELOG.
Refs #355
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Mythos delta-pass requiredThis PR modifies one or more Tier-5 source files (per Before merge, run the Mythos discover protocol on the
Why this gate exists: LS-A-10 The gate check on this PR will pass once the label is |
LS-N verification gate✅ 59/59 approved LS entries verified
Approved Failed LS entries(none) Missing regression tests(none) Updated automatically by |
Mythos delta-pass (auto)✅ NO FINDINGS across 3 Tier-5 file(s)
Auto-run via |
…thos) The #355 Mythos discover pass on component_wrap.rs (clean on the #355 change itself) surfaced the same index-desync class in the INTERFACE-export loop: it advanced component_instance_idx by 1 per exported interface, but exporting an instance binds an export-alias index too, so a component exporting >=2 interfaces silently bound the 2nd+ export to the previous interface's alias — exporting the wrong functions (output still validated; UCA-CP-1). Fixed (+= 2). - component_wrap.rs: component_instance_idx += 2. - tests/component_multi_interface_instance_idx.rs: two-interface component, each export must resolve to its own funcs (Mythos PoC). - SR-54 verification extended; CHANGELOG. Full meld-core suite green. Mythos passes (parser/component_wrap/p3_stream) all clean on the #355 change; parser change also improves resolver index alignment. Refs #355 Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Mythos delta-pass — findingsThree clean-room adversarial discover passes (fresh-context agents), one per
|
Ships the #355 fixes (merged #357): fuse --component now lifts bare world exports with their real signatures instead of an empty (func) (was an INVALID component for any non-empty signature), and a component exporting >=2 interfaces binds each export to its own instance (sibling index-desync found by the Mythos pass). SR-54 verified. Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
What
Fixes #355 —
fuse --componentemitted an invalid component for any exportwith a non-empty signature. Reproduced on avrabe's exact fixtures.
Root cause (three latent defects)
Bare world exports (
world root { export get-b: func(i: s32) -> u32 }) took apath that hardcoded an empty
(func)type. Digging in surfaced three bugs:ComponentFuncDef): exporting aFuncbinds a newcomponent-function index (an export alias); wit-component interleaves these
with
canon lifts. The parser recorded them nowhere, so the func index spacewas silently compacted and
component_func_defs[export.index]mis-resolved(
get-b✓,set-b/ptr-bshifted). Fixed by recordingComponentFuncDef::ExportAlias.func_enc.result(None)was never called for avoid-returning export (
set-b), leaving the type unterminated → decoderEOF. (Latent until a no-result export routed through this helper.)
component-func index by 1 per export, but each export also binds an alias
index — so every export referenced the previous export's alias. Fixed to
advance by 2.
Result
get-b: func(i:s32)->u32,set-b: func(i:s32,v:u32),ptr-b: func()->u32— allcorrect, output validates. The standard
{iface}#{func}interface path isuntouched.
Tests / falsification
component_bare_export_355.rs(single + two-component) ontests/reloc351/{a,b}.wasm:asserts a valid component (
wasmparser::Validator, all features) and thecorrect per-export arity (get-b (1,1), set-b (2,0), ptr-b (0,1)) — the first
catches the empty-type + no-result bugs, the second catches the index shift.
Full
meld-coresuite green (no regression from the parser index-space change);fmt + clippy clean. SR-54 (verified); CHANGELOG. Tier-5 (parser/component_wrap/
p3_stream) → Mythos discover pass to follow on this PR.
Refs #355