fix(wasm): recover tuple pointer element type through the ? boundary#78
Merged
Merged
Conversation
A tuple whose element is pointer-shaped (Map / List / Set) returned through a ?/Result boundary and destructured lost its element type on the Wasm backend, emitting invalid Wasm. It passed --check and ran on the Python backend, so only the Wasm validator rejected it. _lower_try defaulted the ? result type to Unknown when the analyzer left the Try node untyped. That Unknown flowed into the let-tuple binders, so the Wasm tuple emitter sized a Map element as an i64 slot while a Map is an i32 heap pointer, tripping the validator. Fixes: - _lower_try now recovers the unwrapped payload from the operand's Result<T,E> / Option<T> type via _unwrap_try_payload_ty, so the binders carry the precise pointer type. - _emit_try_unwrap now decodes any pointer-shaped payload (including a tuple) via _is_pointer_shape_ty instead of an ad-hoc struct/sum/List/Map/Set check that missed tuples. - The tuple slot emitter (store and index) now fails loud with a clear diagnostic when a pointer-shaped value reaches an unresolved slot type, so a future type-propagation gap can never again ship as invalid Wasm. Scoped to fire only on pointer-shaped values, so Int/Bool/Float elements are unaffected. Adds regression tests on both backends for the let-destructure and match-Ok forms plus the fail-loud guard.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Problem
A tuple with a pointer-shaped element (
Map/List/Set/struct) returned through a?/Resultboundary and destructured (let (m, s) = f()?) passedcapa --checkand ran on the Python backend but emitted INVALID Wasm ("type mismatch: expected i32, found i64"). A silent miscompile: only the Wasm validator caught it. Found by dogfooding a TOML parser.Root cause (two parts)
_lower_trydefaulted the?result type toUnknown, so the tuple binders bound asUnknown; the Wasm tuple emitter then sized aMapelement as i64 while it is an i32 heap pointer._emit_try_unwrap's pointer-payload decode did not recognize a tuple payload, loading the i32 payload as a barei64.load.Fix
_lower_tryrecovers the unwrapped payload type from the operand'sResult<T,E>/Option<T>via a new_unwrap_try_payload_tyhelper, so tuple binders get their precise pointer type._emit_try_unwrapuses the existing_is_pointer_shape_typredicate (covers tuples).WasmEmissionErrorwhen a pointer-shaped value reaches an unresolved slot, instead of silently emitting invalid Wasm. Scoped so it never fires on Int/Bool/Float tuple elements.Tests
New
TestWasmTuplePointerElementThroughTry+ parity class covering Map/List/match Ok((m,s))through?, plus pure emitter unit tests for the guard (not skip-guarded, so the no-wasm CI job runs them). Full suite: 4221 passed, 18 skipped, exit 0. Adversarially reviewed (guard scoping + no regression to the pre-existing match-form/struct-in-tuple/bare-pointer paths).