Skip to content
This repository was archived by the owner on Apr 25, 2025. It is now read-only.

Clarification on i31ref nullability #124

Closed
dcodeIO opened this issue Aug 25, 2020 · 7 comments
Closed

Clarification on i31ref nullability #124

dcodeIO opened this issue Aug 25, 2020 · 7 comments

Comments

@dcodeIO
Copy link

dcodeIO commented Aug 25, 2020

In the MVP document, under reference types, the following is noted:

  • anyref is a new reference type
    • anyref == (ref null any)
  • eqref is a new reference type
    • eqref == (ref null eq)
  • i31ref is a new reference type
    • i31ref == (ref i31)

with i31ref equalling (ref i31) not (ref null i31). This turned up during prototyping in Binaryen where the initial strategy was to default to the abbreviations, but with (ref i31) != (ref null i31), and with (ref null i31) theoretically constructible, we'd then be missing a canonical name for (ref null i31). This is not a problem, as we can design this differently by defaulting to the heaptype representation with the abbreviations merely being aliases, but I'd like to know more about the design here, as it might also be that this is either an oversight or that it hints at (ref null i31) being illegal?

@jakobkummerow
Copy link
Contributor

I had a similar question when I implemented i31ref in V8, and the impression I got was that i31ref == (ref i31) was intentional, and hints at (ref null i31) being presumed less useful (though legal).

(Side note: it seems we went through a very similar journey as you did: in our internal representation, our ValueType evolved from an enum to a class wrapping a separate HeapType, and when we have a need to emit text (or binary test cases), we prefer the shorthands when applicable (e.g. internal (optref eq) is emitted as "eqref".)

@dcodeIO
Copy link
Author

dcodeIO commented Aug 25, 2020

Thanks Jakob, going with V8's approach now! Closing as this is answered, but if anyone has differing design insights, please let me know :)

@dcodeIO dcodeIO closed this as completed Aug 25, 2020
@rossberg
Copy link
Member

What @jakobkummerow said. Having a different nullability default for the i31ref shorthand was a pragmatic choice based on expected use cases, but it is a bit irregular. We can switch it around if folks think that's preferable. Opinions?

@dcodeIO
Copy link
Author

dcodeIO commented Sep 24, 2020

Having a different nullability default for the i31ref shorthand was a pragmatic choice based on expected use cases, but it is a bit irregular. We can switch it around if folks think that's preferable. Opinions?

So far I found that the irregularity requires frequent special casing of i31ref where all the other canonical refs have something in common, i.e. possibly null. Another challenge is, when creating globals using an enum of all the canonical types, all these types currently have a trivial initializer except i31ref (unless i31.new is meant to become a valid constant initializer expression, or introducing i31.zero). This is mostly a matter of convenience for implementers, though, and if more canonical names for non-nullable types are introduced it'd instantly feel less alien I guess.

@titzer
Copy link
Contributor

titzer commented Sep 24, 2020

What about #130 ?

@dcodeIO
Copy link
Author

dcodeIO commented Sep 24, 2020

Hmm, I don't really get the point in #130 ((ref i31 func) or even a concrete struct?), but I also already didn't get why i31ref has been introduced in the first place given the complexity it imposes on the type system for very little gain. Hence I might mistakenly see the suggestion there as just another continuation of a mistake. In general I am only confident about anyref, func, struct and array, and all the other curiosities seem odd to me, especially in an MVP.

@titzer
Copy link
Contributor

titzer commented Sep 25, 2020

The point of #130 is to treat tagged integers as orthogonal dimension in the type system the way nullability is.

I think it's easier to separate i31ref from the GC proposal if it is this orthogonal dimension.

Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Development

No branches or pull requests

4 participants