Skip to content

fix: restore deterministic type section ordering#309

Merged
guybedford merged 2 commits intomainfrom
fix/type-section-sort
Mar 30, 2026
Merged

fix: restore deterministic type section ordering#309
guybedford merged 2 commits intomainfrom
fix/type-section-sort

Conversation

@guybedford
Copy link
Copy Markdown
Contributor

Problem

PR #304 changed type section emission from a canonically-sorted flat iteration to rec-group definition order. This broke determinism: two wasm binaries containing the same types but in different orders now produce different output from walrus.

This caused flaky reference tests in wasm-bindgen (wasm-bindgen/wasm-bindgen#5065), where different Rust compiler versions emit __wbindgen_malloc (i32,i32)->i32 and __wbindgen_realloc (i32,i32,i32,i32)->i32 with swapped type indices in the wasm binary's type section.

Fix

Sort "free" singleton implicit rec groups — those whose single type has no cross-group type references — into a canonical order by their Type content. Groups that have dependencies (explicit rec groups, multi-type groups, or singletons referencing types in other groups via supertypes or concrete heap types) remain in definition order, which already satisfies the topological constraint that referenced types must precede referencing types.

This restores the pre-#304 determinism for the common case (plain function types) while correctly handling all GC type constructs.

Tests

  • crates/tests/tests/round_trip/type-order-stability.wat — the malloc type first, should round-trip with (;0;) (i32,i32)->i32
  • crates/tests/tests/round_trip/type-order-stability-swapped.wat — the realloc type first, must produce identical output
  • crates/tests/tests/deterministic_type_order.rs — programmatic unit tests covering the same scenario and edge cases

Adds tests that expose the non-determinism reported in
wasm-bindgen/wasm-bindgen#5065.

PR #304 changed type section emission from a sorted flat iteration to
rec-group definition order. This means two semantically-identical
modules that differ only in the order their types appear in the input
binary can now produce different output bytes.

The two round-trip fixtures (type-order-stability.wat /
type-order-stability-swapped.wat) encode the exact pair of types that
causes flaky wasm-bindgen reference tests: the malloc type
(i32,i32)->i32 and the realloc type (i32,i32,i32,i32)->i32 inserted
in opposite orders. Both should round-trip to the same CHECK output
but currently do not.

The deterministic_type_order.rs unit tests cover the same scenario
programmatically and will also fail until the sort is restored.
PR #304 changed type section emission from a canonically-sorted flat
iteration to rec-group definition order, which broke determinism: two
wasm binaries with the same types in different orders now produce
different output from walrus. This caused flaky reference tests in
wasm-bindgen (wasm-bindgen/wasm-bindgen#5065), where different Rust
compiler versions emit __wbindgen_malloc and __wbindgen_realloc with
swapped type indices.

The fix sorts 'free' singleton implicit rec groups — those with no
cross-group type references — into a canonical order by their Type
content. Groups that have dependencies (explicit rec groups, multi-type
groups, or singleton groups that reference types in other groups via
supertypes or concrete heap types) remain in definition order, which
already satisfies the topological constraint that referenced types must
precede referencing types.

This restores the pre-#304 determinism for the common case (plain
function types) while correctly handling all GC type constructs.
@guybedford guybedford force-pushed the fix/type-section-sort branch from b9a1071 to 9a9d51a Compare March 30, 2026 20:49
@guybedford guybedford merged commit 8e44bbd into main Mar 30, 2026
18 checks passed
@guybedford guybedford deleted the fix/type-section-sort branch March 30, 2026 21:03
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant