Nominal Types in WebAssembly
This technical deep dive explores the nuanced world of type equality in WebAssembly, contrasting its default structural typing with the desire for nominal types. It highlights how Wasm's recursive type groups offer an approximation, but true inter-module nominality has been elusive. The author then cleverly reveals how the recent exception handling proposal, with its tag keyword and exception mechanics, inadvertently provides a mechanism for nominal types, framed as a "troll post" on the committee's slow progress.
The Lowdown
WebAssembly's type system primarily employs structural type equality, where two types are considered equivalent if they have the same structure, even if declared separately. This can be problematic when distinct types are desired, especially for security or capability management. The article delves into this challenge and proposes an unexpected solution.
- Initially, WebAssembly types like
(type $t (struct i32))and(type $u (struct i32))are structurally equivalent, handled by the Wasm implementation partitioning types into equivalence classes. - Recursive type groups (
rec) offer a way to create an approximation of nominal typing within a single module, as types within the samerecgroup are considered distinct from those outside or in other groups. - However,
recgroups don't prevent other modules from forging types with identical structures, undermining strict nominality across module boundaries. - The author then unveils a "troll post" revelation: the recently adopted WebAssembly exception handling proposal introduces the
tagkeyword, which can be repurposed to create nominal types. - These
tag-defined types useparaminstead offieldand lack features like subtyping and mutability directly, but mutable fields can be wrapped in mutable structs. - Constructing such a nominal type involves using
throw, and instances are returned as theexn(exception) type, requiring specific code to check their identity and access their "fields" viacatchhandlers. - The mechanism, while syntactically unconventional, ensures type safety: if a value isn't the expected nominal type, an exception is thrown upon access.
- For principled composition, the
tagcan be exported and imported by other modules, similar to the proposed type imports, allowing strict nominal identities across modules.
Ultimately, the post serves as a clever demonstration that the Wasm committee's exception handling proposal, perhaps unintentionally, provides a pathway to implement nominal types, highlighting the sometimes circuitous routes technical specifications take.