I was reading the fantastic Baby Steps blog post about class inheritance and had a few ideas to add this to the language. I tried to keep it as “Rusty” as possible and also make sure that existing code compiles to more-or-less the same thing as it would without them.
enum &A(a: i32, b: i32) { // & at start of type name denotes unsized enum
X { y: u32 },
enum Y { // can also be &Y, leading to the internal representation being a pointer to a tagged enum,
// whose data is a pointer to a tagged enum
G,
H(r: u32, t: u32),
},
Z,
}
impl A {
fn do_stuff(&self) -> () {
match self {
A(a, b)::X { y = x } => {},
Z => {}, // equivalent to A(_, _)::Z
Y::a => match a {
_ => {},
}
// could also do Y => {} which is the same as Y::_ => {}
}
}
}
fn main() {
let a: &A = &( A(1, 2)::Y::H(1, 2) ); // outermost brackets unnecessary
// let a: &A = Z;
// ^~~~~~~~~~~~~^ throws error "a, b not given" or suchlike
}
/*
This shows off three ideas for Rust language additions - enum- (or type-, possibly, such as for trait fields) inherent values,
nested enums, and unsized enums. For the latter, internal representation is a tag followed by a pointer, like if you had done:
enum A { First(a: &Type), Second(b: &Type2) }
These are intended to help with use-cases for C++-style inheritance (such as the rustc TypeData enum) in a rusty way.
*/
I believe this satisfies thin pointers, cheap field access (enum values would be contiguous in memory after the enum tag I guess), cheap downcasting (for obvious reasons), sharing of fields and methods (that was the main thing I was interested in), static/dynamic dispatch, safety, upcasting (through matching wildcard inner types), and calling methods via the pointer (through the combined deref/access operator). These are the requirements steveklabnik describes in this post. I’ve only got a little experience in serious language design so any criticism is more than welcome.