fix: restore deterministic type section ordering#309
Merged
guybedford merged 2 commits intomainfrom Mar 30, 2026
Merged
Conversation
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.
97cc2df to
b9a1071
Compare
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.
b9a1071 to
9a9d51a
Compare
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
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)->i32and__wbindgen_realloc(i32,i32,i32,i32)->i32with 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
Typecontent. 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)->i32crates/tests/tests/round_trip/type-order-stability-swapped.wat— the realloc type first, must produce identical outputcrates/tests/tests/deterministic_type_order.rs— programmatic unit tests covering the same scenario and edge cases