Why do we need the type of i31 in WasmGC proposal?

Why do we need the type of i31 in the WasmGC proposal? The difference between it and primitive scalar is only the tagging bit, is that right? Also, I saw from the spec that an i31 is not actually allocated in the store, so why is it regarded as a heap type? Since AFAIK, GC only cares about the object data in the heap.

Spec: https://webassembly.github.io/gc/core/syntax/types.html#syntax-heaptype


  • An i31 is compatible with other references. That means it can be used as part of a union with other reference types, unlike ordinary numeric types, which have an incompatible representation.

    This reflects a common implementation technique in managed language runtimes, where tagging bits distinguish pointers from unboxed integers. This is used internally e.g. in JavaScript engines and many other dynamic and functional languages. Wasm, as a low-level VM, needs to make it available to runtimes implemented on top of its GC mechanism.

    It is a heap type in so far that it lives in the same space as other heap types, and a GC must be able to dynamically distinguish i31s from genuine pointers when it traverses the heap.