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.
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.
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.