Join GitHub today
GitHub is home to over 31 million developers working together to host and review code, manage projects, and build software together.
Sign upAlternative to virtual struct and functions by extending enums #11
Conversation
This comment has been minimized.
This comment has been minimized.
|
I haven't been following the virtual struct/function story very closely (and this is a big proposal), could you summarize what the core motivation is / what important things it's adding relative to the current language in terms of expressiveness (as distinct from syntax/ergonomics/convenience/etc)? |
This comment has been minimized.
This comment has been minimized.
|
It adds an equivalent of Java OO functionality by reusing and extending enums, plus some syntax sugar for impls. Which basically means having a type (in this RFC, an extended version of enums) such that pointers to this type have these features:
In other RFCs, the type in question are the new "virtual structs" in #5 or the Fat<T, U> object of #9 where T is a trait that can extend a struct. The idea of this RFC is that we want to have enums in the language anyway, and we can extend them to perform this role relatively naturally, and that should thus be better than adding something else. In a nutshell, if you use a vtable pointer as an enum discriminator, and implement match on an enum in the current language by creating a virtual function for each match case, you have a two-level Java-style OO hierarchy where the parent class cannot have fields and enum variants are the subclasses. This RFC extends the language so that enum have fields, enum variants are first-class structs or enum, multi-level hierarchies are supported, traits can be dispatched over the enum hierarchy, and adds syntax sugar to make it all pleasant. The motivating issue seems to be to implement the HTML/XML DOM in Servo efficiently, as well as possibly interoperating with COM interfaces without writing the dispatch code by hand. |
This comment has been minimized.
This comment has been minimized.
|
I think this is a great idea! I prefer it to virtual structs (RFC 5) since it is feels more Rust-like. I have quite a few suggested tweaks though and I think there are enough it is worth submitting a new RFC rather than commenting here, so I will do that. The only real question I have with this general approach is how practical it is. Virtual structs have the advantage of being battle tested in the form of 'normal' OO inheritance - we know their advantages and disadvantages. I wonder what if, with this proposal, things get unwieldy when dealing with large numbers of classes with lots of fields and methods and a deep inheritance hierarchy (such as the DOM or COM stuff). I'm not saying it will, just that I don't know and so I have that question. |
nrc
added a commit
to nrc/rfcs
that referenced
this pull request
Mar 30, 2014
nrc
added a commit
to nrc/rfcs
that referenced
this pull request
Mar 30, 2014
This comment has been minimized.
This comment has been minimized.
|
Some preliminary thoughts. Sorry for the delay.
|
This comment has been minimized.
This comment has been minimized.
I suggested this syntax It's not fantastic, but it seems better than banning them (which introduces a special case and a discontinuity - i.e. you want to add a field and suddenly you need to refactor the variant as well).
Unless an ABI is specified, the compiler is free to arbitrarily choose to use vtables or not, since matching and vtable dispatch are equivalent. Of course, it's possible to specify this more strictly. But note that in some cases, like 1 or 2 variants, using an direct call or if statement is going faster, and there is no reason to not do that.
Here traits are used simply to give a name to sets of methods. Making them only inherent is possible but isn't great, for many reasons:
Anyway, one could add syntax for it like this:
This would be equivalent to putting method1 and method2 each in its own trait, implementing them on Base using "impl as match" and implementing them for A and B. Problem is, there is no longer any clue in the impls of A and B that you are implementing an abstract interface, and no indication of what the interface is supposed to do other than being Base's interface (and even that requires searching for where method1 and method2 are defined). These issues may be avoided by having syntax like On the other hand this syntax is less verbose than explicit traits. I suppose it would be nice to try things out with the DOM and see whether using traits looks nice or excessively verbose. |
bill-myers
referenced this pull request
Apr 3, 2014
Closed
Use different keywords for declaring tagged unions and C-style enums. #27
nrc
self-assigned this
Sep 4, 2014
brson
assigned
zwarich
and unassigned
nrc
Sep 9, 2014
This comment has been minimized.
This comment has been minimized.
|
@bill-myers We are going to be discussing the various proposals for struct inheritance in the weekly Rust meeting soon (hopefully one week from today). We are using the DOM example in https://gist.github.com/jdm/9900569 as a common benchmark for comparing the usability of the different approaches. Can you update this RFC with that example converted to use these new features, or should I attempt it for you? |
pcwalton
added a commit
that referenced
this pull request
Sep 11, 2014
alexcrichton
force-pushed the
rust-lang:master
branch
from
6357402
to
e0acdf4
Sep 11, 2014
zwarich
reviewed
Sep 12, 2014
| - Instantiable and overridable structures are separated into struct and enum, rather than having a virtual struct that is both instantiable and overridable | ||
| - Only intra-crate inheritance by default, so that it can be better optimized and doesn't try to reinvent traits (virtual structs can also be made inter-crate only, but it is less natural than with enums) | ||
| - Overridable methods are declared in traits and not in anonymous impls so that related sets of overridable methods can be separated from each other and have a name and documentation | ||
| - It is only possible to override abstract methods and not implemented methods, which makes it harder to create badly designed class hierarchies (but we have syntax sugar to relieve the drawbacks in the form of "impl Trait for Type1, Type2, Type3, ...") |
This comment has been minimized.
This comment has been minimized.
zwarich
Sep 12, 2014
Contributor
The ability to override implemented methods is required for the DOM use case, because of common before/after method idioms in OO code. The overrided method also needs to be able to call the 'superclass' method. Is it even possible to do that with this proposal?
huonw
reviewed
Sep 15, 2014
|
|
||
| For Tuple-like structs that have ancestors with fields, we add this new mixed construction syntax, which is also used for pattern matching: | ||
| ``` | ||
| let struct_value = Struct{a: A, b: B}(X, Y); |
This comment has been minimized.
This comment has been minimized.
huonw
reviewed
Sep 15, 2014
| ``` | ||
| enum Enum<T, U> [: Parent] | ||
| { | ||
| [field1 : Type1], |
This comment has been minimized.
This comment has been minimized.
huonw
Sep 15, 2014
Member
Is
enum Enum<T, U> {
field1: Type1,
field2: Type2,
}any different to that with s/enum/struct/?
This comment has been minimized.
This comment has been minimized.
zwarich
Sep 23, 2014
Contributor
I think that this enum would be equivalent to the struct if you added a single constructor with no parameters.
huonw
reviewed
Sep 15, 2014
| impl Trait for EnumOrStruct1, EnumOrStruct2, ... | ||
| ``` | ||
|
|
||
| All target types must have a common enum ancestor, and this syntax is equivalent to implementing all methods as anonymous methods on that ancestor, and then implementing the trait on each target type by calling the anonymous method on the common ancestor. |
This comment has been minimized.
This comment has been minimized.
huonw
Sep 15, 2014
Member
This is just sugar for this, right? i.e. identical behaviour can be encoded without this syntax?
huonw
reviewed
Sep 15, 2014
| <manually implemented methods> | ||
| } | ||
| ``` | ||
| is added, and implements the traits for EnumOrStruct by calling corresponding methods on \<expr\> (which is inserted exactly like a macro expansion with expr parameter). |
This comment has been minimized.
This comment has been minimized.
huonw
Sep 15, 2014
Member
It seems that this is non-hygienic (not necessarily a bad thing, just not it's not exactly like a macro).
aturon
force-pushed the
rust-lang:master
branch
from
4c0bebf
to
b1d1bfd
Sep 16, 2014
This comment has been minimized.
This comment has been minimized.
|
We discussed this in the inheritance meeting and decided that the good ideas from this RFC have been spread amongst the later inheritance RFCs, and those later RFCs satisfy more of the requirements that we are looking to satisfy. Thus it would be best to close this and continue discussion there. |
bill-myers commentedMar 17, 2014
This is an alternative plan for virtual structs/functions that implements virtual structs by making it possible to inherit enums to support class inheritance trees, and by automatically dispatching traits over them.
I think this is a superior alternative to both of the current proposals (#5 and #9) and what I originally proposed on the mailing list (which was very similar to #9).