This involves a rather significant reworking of the type system, and it happens to be one I have thought about quite a lot, ever since #8277 about anonymous sum types.
Basically what this idea of yours boils down to is making variants first-class types and replacing enums with what is much closer to type unions (though discriminated, of course).
I have a feeling that the end result of something like this could be superior, though it’s certainly not without its difficulties (most notably, what happens if you take the union of two types with a common variant?) but it would be a very drastic change and is, I think, too late for Rust.
I would take it a little further and formulate your example somewhat like this:
type Some<T>(T);
type None;
type Option<T> = Some<T> | None;
By that point you might as well throw away None and define it thus:
type Option<T> = T | ();
(“What about when T is ()?” you ask. Indeed, and I don’t know the answer yet. Probably it would be forbidden.)
Such a language as this would then have genuine subtyping; T would be a subtype of Option<T>, for example, and so inside your method you would be able to implicitly cast a T to a T | ().
This sort of thing would be particularly useful for things like remote APIs:
// Allowing inline type definitions like this is half-baked sugar
// for these things and has not been thought through at all.
type ErrorCode = type BadThing = 1
| type AnotherBadThing = 2;
type Message = type Foo
| type Bar(int)
| type Baz {
happy: bool,
};
type ApiError {
detail: String,
code: ErrorCode,
}
fn call() -> Result<Message, IoError | json::Error | ApiError>;
And because of the subtyping relationship where an IoError can be implicitly cast to IoError | json::Error | ApiError (it will do Magic with regards to the discriminants, of course), try!(stream.read(buf)) would work. (As it is, it’s distinctly unpleasant with lots of boilerplate, and you can’t use try!.)
Well, these are interesting things to think about, but I don’t think Rust will be getting it.