Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[overview] Expand explanation; add private types #8

Merged
merged 7 commits into from
Jul 1, 2020
Merged

Conversation

rossberg
Copy link
Member

No description provided.

@rossberg rossberg requested a review from lukewagner June 18, 2020 15:41

Type _exports_ are transparent by default.
When using a type export to instantiate the import of another module,
its full definition is therefor available to verify any import constraints.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

typo: therefor -> therefore

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fixed.

Copy link
Member

@lukewagner lukewagner left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

(Sorry for the slow reply! I missed the notification.) I wonder if it's possible to achieve the requirements without requiring the extra boxing of reference values. I'm not sure I've thought through all the constraints, but it seems like we could achieve this by having:

  • deftype ::= <functype> | <privatetype> (as in the PR)
  • privatetype ::= private <heaptype> (not a <valtype>*)
  • (ref (private $T)) </: (ref $T) (analogous to the PR)
  • all the operations that are valid for (ref $T) are made valid for a (ref (private $T))

The net effect of the last bullet would be "almost subtyping" but without the ability to convert first-class (ref (private $T)) values into first-class (ref $T) values. (Weird, I know; maybe you can help me find a better way to frame this.) Thus, creating a new private object would be just like creating a normal public object except the typeindex would refer to a privatetype instead of another kind of deftype. So, specifically, a private function could be created by using the index of a privatetype in the function section and a private struct could be created with struct.new $PrivateType.

Now, this doesn't work for i31.new, since i31.new doesn't have a typeindex, so there would need to be some new boxing variant private.box_i31 : [i32] -> [(ref (private i31))] which is unfortunate, but I don't see any way around boxing private i31s when they can be upcast to anyref and passed out to an untyped language. But at least every other reference type doesn't need to be boxed. (I think.)

WDYT?

proposals/type-imports/Overview.md Outdated Show resolved Hide resolved
proposals/type-imports/Overview.md Outdated Show resolved Hide resolved
proposals/type-imports/Overview.md Outdated Show resolved Hide resolved
proposals/type-imports/Overview.md Show resolved Hide resolved
proposals/type-imports/Overview.md Outdated Show resolved Hide resolved
proposals/type-imports/Overview.md Show resolved Hide resolved
rossberg and others added 2 commits June 30, 2020 08:45
Co-authored-by: Luke Wagner <mail@lukewagner.name>
Copy link
Member Author

@rossberg rossberg left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@lukewagner, re your suggestion:

  • privatetype ::= private <heaptype> (not a <valtype>*)

Yes, this is what I would have preferred to do. But then we'd need to pull in more stuff from the GC proposal, such as structs.

So instead, I was hoping that we can later reinterpret private type definitions in a way that unifies it with structs, see the section in the end. The main difference to the above would be that "private" ends up being a sort of flag on struct definitions(*), instead of a separate type constructor. That's slightly less nice from a decomposition point of view, but in neither case a separate allocation should be needed.

(*) And potentially others; a binary format hack could even backport the flag to func types, although I'm not sure what use case you have in mind.

  • (ref (private $T)) </: (ref $T) (analogous to the PR)

Now this would imply that privatetype is a heaptype, not a deftype, I think?

Of course, you'd still need to be able to pass a ref $T to somebody else (and receive it back), so you'd now need conversion functions between the two types. But why separate the reference types and require conversions? We'd still need to control availability of the conversions via scoping. With what I propose, scoping instead controls availability of accessors on the type directly. Outside the scope of the private definition it's still the same type, but you simply don't know anything about its definition -- basically, the usual semantics of abstract data types.

FWIW, this would work even if we separated private from struct. If you had

(type $S (struct (field i32)))
(type $P (private $S))

then you'd simple know (statically) that $P <: $S inside the module but not outside. So all accessors would be applicable immediately.

proposals/type-imports/Overview.md Show resolved Hide resolved
proposals/type-imports/Overview.md Show resolved Hide resolved
@lukewagner
Copy link
Member

@rossberg Ah hah, ok. I had seen the "reinterpret as a struct definition" bit, but I had interpreted it differently. Re-reading it now, I think I see what you're getting at.

So to check my understanding: a type definition (type $T (private i32)) would get desugared into something like (type $T (struct private (field i32))) and private.get $T is then desugared into struct.get $T 0, but since you can add private to arbitrary struct definitions, there is never a need to box a (struct $Fs) inside of a (private (ref (struct $Fs))) because you could just as well have a (struct private $Fs). Also I assume one could have an (array private $elem) and similarly for every other heap type. If that's all right, that sounds great; I really like it.

Copy link
Member Author

@rossberg rossberg left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, exactly. I expanded the section to explain the desugaring more concretely. PTAL.

proposals/type-imports/Overview.md Outdated Show resolved Hide resolved
Copy link
Member

@lukewagner lukewagner left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

lgtm, thanks for writing this up!

Co-authored-by: Luke Wagner <mail@lukewagner.name>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants