> From: Bill Myers <[email protected]>
>
> I was reading a proposal about adding "datasort refinements" to make enum
> variants first-class types, and it seems to me there is a simpler and more
> effective way of solving the problem.
>
> The idea is that if A, B and C are types, then "A | B | C" is a
> "structural" enum type that can be either A, B or C.
>
> In addition, A can be implicitly converted to "A | B", "A | B" can be
> implicitly converted to "A | B | C", and also "(A | B) | C" and "A | (B |
> C)" are equivalent to "A | B | C", and finally "C | B | A" is equivalent to
> "A | B | C" (to support the latter, the implementation needs to sort
> variants in some arbitrary total order before assigning tag numbers).
>
> Furthermore, a way to bind variables to an "or" pattern is introduced to
> allow to convert "A | B | C" to "A | B" in the case that it holds an A or a
> B.
>
> This way, one can rewrite Option as a type alias like this:
> struct Some<T>(T);
> struct None;
>
> type Option<T> = None | Some<T>;
>
> Which is like the current Option, but also makes None and Some<T>
> first-class types.
>
> The current enum syntax can remain as syntax sugar for the above code.
>

Hi, I'm just your friendly everyday lurker... Assuming there's nothing in
this proposal that fundamentally breaks the language, I just wanted to say
I think this idea is fantastic. You almost don't need Some(T) since
Option<T> could just be None|T.

I would add that I recall recently some people were discussing how to do a
"variant" type in Rust. If all struct types in a program are assigned a
unique tag, this very same feature could support a variant type, which is
defined as the union of all types. Then any struct converts implicitly to
variant (oh, and since I just wrote a parser generator that supports
inverted sets like ~('a'..'z'), it occurs to me that the type system could
readily support "any type except A | B" as well.)

The tag could either be a unique integer index, or a pointer to a global
variable that contains type information (the latter, it seems to me,
automatically solves the dynamic linking problem "how do we ensure two
unrelated DLLs have unique tags?" DLL loaders already support relocation in
case of conflicts.)


The only issue I see is what to do for code such as "let mut x = Some(3);
> x = None;": with this proposal, Some and None are separate unrelated types,
> so we either have this code emit an error, or x must be given the type
> "Some<int> | None" automatically, which however can lead to obscure error
> messages if one mistakenly attempts to assign a string to it causing the
> type to become "Some<int> | None | ~str" (i.e. the user might be told than
> a match is not exhaustive because it does not handle the "~str" case,
> rather than that they assigned a ~str to an Option-typed variable).
>
> It should be possible to allow this, and make the error-emitting code use
> heuristics to figure out whether it is more likely that the user assigned a
> value of the wrong type, or used an enum improperly (for example, by
> looking at whether the implicitly created enum type is ever written
> explicitly in the source, and whether the deduced structural enum type is
> being used in places that require a non-enum type).
>
> Alternatively, one can stipulate that only types that are structs, or that
> are structs marked "enum struct" or "case struct" or similar can become
> part of an inferred structural enum, but this seems unappealing.


To keep the feature more conservative it's not unreasonable to (initially,
at least) restrict the members of the union to be struct types; any
non-struct type can still be used with Some(T). But the restriction doesn't
entirely solve this particular problem; yeah, the compiler will complain if
you assign ~str to a variable intended to be an Option, but it still won't
complain if you assign some struct type to it.


> Note that some structural enums can change representations depending
> generic instantiation, since "T | int" becomes just "int" if T = int, while
> it is "~str | int" if T = ~str (and similar for "Some<T> | Some<int>"), but
> this should not be a problem.
>
_______________________________________________
Rust-dev mailing list
[email protected]
https://mail.mozilla.org/listinfo/rust-dev

Reply via email to