Surfaced by the issue-hunt (via gale#89), confirmed as a meld-local issue
meld fuse --memory shared --address-rebase (the single-address-space MCU lowering the jess/gale Pixhawk pipeline needs) fails:
unsupported component feature: memory.grow not supported with address rebasing
Both gale-app-demo and gale-kiln carry one memory.grow each — emitted by the default Rust / wit-bindgen wasip2 allocator. The multi-memory fallback isn't MCU-lowerable (2 memories × 1088 KB; synth loud-rejects). So the canonical dissolve meld fuse → loom → synth cannot currently produce the monolithic single-address-space core for the drone target. (gale#89 documents the gale-side view.)
This is correct fail-loud, not a bug — but it's a hard capability gap
meld's refusal is sound-by-construction (SR-37 + memory_probe.rs): MemoryStrategy::SharedMemory freezes the static memory layout at fuse time, so a runtime memory.grow would corrupt the shared single-address-space layout (merger Bug #7). The module_uses_memory_grow probe gates Auto→shared exactly on memory.grow absence, and a parse failure conservatively counts as "uses grow." So the gate must stay; this issue is about adding a sound path, not relaxing it.
Options (the actual work)
- Sound
memory.grow lowering under address-rebasing (preferred): reserve a bounded static heap region per fused component and rewrite memory.grow → a bounded bump within that reservation, failing loud (trap / AbiError::Oom) on exhaustion. Preserves the frozen-layout soundness invariant AND accepts default-allocator components. Touches segments.rs (address-rebase), memory_probe.rs/MemoryStrategy, and the rebase math in rewriter.rs. Needs an ls_*-gated oracle + a Kani/▢ bound-check.
- Documented no-grow input contract + actionable diagnostic: make the error point to the remediation (build components
no_std/no-grow, or pre-strip the allocator's grow when a static max is known) — the path gale#89 pursues on the gale side. Cheaper; pushes the requirement upstream.
- Allocator pre-pass: when a static heap max is declared, replace the wasip2 allocator's
memory.grow with a pre-sized static reservation before fusion.
Cross-refs
- gale#89 — gale-side dissolve constraints (components must be no_std/no-grow).
- gale#63 — runtime hosting of the fused async components (Pixhawk 6X-RT).
- meld#298 — drop vestigial cabi_realloc to unblock
--memory shared (related, distinct blocker).
- meld#172 (closed) —
--memory multi default rejected by wasm-opt/synth.
Honest scope note
Option 2 is a same-day diagnostic+docs improvement that unblocks the pipeline if gale components go no-grow (gale#89). Option 1 is the general fix (any default-allocator component MCU-lowerable) and is the larger, oracle-gated piece. Recommend shipping Option 2's diagnostic now and scoping Option 1 as the real capability.
Surfaced by the issue-hunt (via gale#89), confirmed as a meld-local issue
meld fuse --memory shared --address-rebase(the single-address-space MCU lowering the jess/gale Pixhawk pipeline needs) fails:Both
gale-app-demoandgale-kilncarry onememory.groweach — emitted by the default Rust / wit-bindgen wasip2 allocator. The multi-memory fallback isn't MCU-lowerable (2 memories × 1088 KB; synth loud-rejects). So the canonical dissolvemeld fuse → loom → synthcannot currently produce the monolithic single-address-space core for the drone target. (gale#89 documents the gale-side view.)This is correct fail-loud, not a bug — but it's a hard capability gap
meld's refusal is sound-by-construction (SR-37 +
memory_probe.rs):MemoryStrategy::SharedMemoryfreezes the static memory layout at fuse time, so a runtimememory.growwould corrupt the shared single-address-space layout (merger Bug #7). Themodule_uses_memory_growprobe gates Auto→shared exactly onmemory.growabsence, and a parse failure conservatively counts as "uses grow." So the gate must stay; this issue is about adding a sound path, not relaxing it.Options (the actual work)
memory.growlowering under address-rebasing (preferred): reserve a bounded static heap region per fused component and rewritememory.grow→ a bounded bump within that reservation, failing loud (trap /AbiError::Oom) on exhaustion. Preserves the frozen-layout soundness invariant AND accepts default-allocator components. Touchessegments.rs(address-rebase),memory_probe.rs/MemoryStrategy, and the rebase math inrewriter.rs. Needs anls_*-gated oracle + a Kani/▢ bound-check.no_std/no-grow, or pre-strip the allocator's grow when a static max is known) — the path gale#89 pursues on the gale side. Cheaper; pushes the requirement upstream.memory.growwith a pre-sized static reservation before fusion.Cross-refs
--memory shared(related, distinct blocker).--memory multidefault rejected by wasm-opt/synth.Honest scope note
Option 2 is a same-day diagnostic+docs improvement that unblocks the pipeline if gale components go no-grow (gale#89). Option 1 is the general fix (any default-allocator component MCU-lowerable) and is the larger, oracle-gated piece. Recommend shipping Option 2's diagnostic now and scoping Option 1 as the real capability.