-
Notifications
You must be signed in to change notification settings - Fork 1.6k
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
Alternative to virtual struct and functions by extending enums #11
Conversation
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)? |
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. |
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. |
Another alternative to RFC rust-lang#5 and an extension/variant of RFC rust-lang#11. Unify enums and structs by allowing enums to have fields, and structs to have variants. Allow nested enums/structs. Virtual dispatch of methods on struct/enum pointers. Remove struct variants. Treat enum variants as first class. Possibly remove nullary structs and tuple structs.
Another alternative to RFC rust-lang#5 and an extension/variant of RFC rust-lang#11. Unify enums and structs by allowing enums to have fields, and structs to have variants. Allow nested enums/structs. Virtual dispatch of methods on struct/enum pointers. Remove struct variants. Treat enum variants as first class. Possibly remove nullary structs and tuple structs.
Some preliminary thoughts. Sorry for the delay.
|
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 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? |
6357402
to
e0acdf4
Compare
- 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, ...") |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
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?
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. |
RFC: Improved CP Syntax
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).