WebAssembly / gc

Branch of the spec repo scoped to discussion of GC integration in WebAssembly
https://webassembly.github.io/gc/
Other
1k stars 73 forks source link

Type matching logic in test suite assertions #572

Open CharlieTap opened 3 weeks ago

CharlieTap commented 3 weeks ago

Various test assertions require the testsuite runner implementation to understand the type matching logic, for example:

(module
  (global $null nullref (ref.null none))
  (func (export "anyref") (result anyref) (global.get $null))
)

(assert_return (invoke "anyref") (ref.null any))
(assert_return (invoke "anyref") (ref.null none))

Any code computing assert_return would need to understand that ref.null any matches ref.null none, which is a little odd as now the test itself is dependant on working matching code. Ideally the test assertions would simply be testing equality, and the actual wasm code would perform a computation that proves the type matching is correct. Thoughts?

rossberg commented 3 weeks ago

This simply verifies that (ref.null any) and (ref.null none) are the same value. There is no type matching involved, neither dynamically nor statically (the script level is pretty much untyped).

CharlieTap commented 3 weeks ago

I guess I'm not following 🤔 , how could two different types be the same value? Irrespective of language and encoding you're going to have some composition of structs and the inner (abstract heap type) none would not equal any without some additional type matching logic?

rossberg commented 3 weeks ago

Well, both variants of the null instructions produce the same null value. There exists only one null value (per type hierarchy anyway, across hierarchies they are incomparable so you can't tell). The heaptype annotation primarily exists to determine the type hierarchy. Within a given hierarchy the specific annotation only affects the local static type of the null value, not its representation. You can always pick the respective bottom type — the fact that you can choose others is a historical wart more than anything else.

For other heap types, like struct or array, ref patterns indeed requires some minimal matching logic. It is fair to view this as runtime subtyping if you prefer, but in a very limited form that really only amounts to classifying GC values into structs, array, i31s, and null. Depending on the implementation, these are typically distinguished by other mechanisms than actual runtime types. In particular, subtype declarations are never relevant for testing this.