proposal: Go 2: sum types using interface type lists #41716
Description
This is a speculative issue for discussion about an aspect of the current generics design draft. This is not part of the design draft, but is instead a further language change we could make if the design draft winds up being adopted into the language.
The design draft describes adding type lists to interface types. In the design draft, an interface type with a type list may only be used as a type constraint. This proposal is to discuss removing that restriction.
We would permit interface types with type lists to be used just as any other interface type may be used. A value of type T
implements an interface type I
with a type list if
- the method set of
T
includes all of the methods inI
(if any); and - either
T
or the underlying type ofT
is identical to one of the types in the type list ofI
.
(The latter requirement is intentionally identical to the requirement in the design draft when a type list is used in a type constraint.)
For example, consider:
type MyInt int
type MyOtherInt int
type MyFloat float64
type I1 interface {
type MyInt, MyFloat
}
type I2 interface {
type int, float64
}
The types MyInt
and MyFloat
implement I1
. The type MyOtherInt
does not implement I1
. All three types, MyInt
, MyOtherInt
, and MyFloat
implement I2
.
The rules permit an interface type with a type list to permit either exact types (by listing non-builtin defined types) or types with a particular structure (by listing builtin defined types or type literals). There would be no way to permit the type int
without also permitting all defined types whose underlying type is int
. While this may not be the ideal rule for a sum type, it is the right rule for a type constraint, and it seems like a good idea to use the same rule in both cases.
Edit: This paragraph is withdrawn. We propose further that in a type switch on an interface type with a type list, it would be a compilation error if the switch does not include a default
case and if there are any types in the type list that do not appear as cases in the type switch.
In all other ways an interface type with a type list would act exactly like an interface type. There would be no support for using operators with values of the interface type, even though that is permitted when using such a type as a type constraint. This is because in generic code we know that two values of some type parameter are the same type, and may therefore be used with a binary operator such as +
. With two values of some interface type, all we know is that both types appear in the type list, but they need not be the same type, and so +
may not be well defined. (One could imagine a further extension in which +
is permitted but panics if the values are not the same type, but there is no obvious reason why that would be useful in practice.)
In particular, the zero value of an interface type with a type list would be nil
, just as for any interface type. So this is a form of sum type in which there is always another possible option, namely nil
. Sum types in most languages do not work this way, and this may be a reason to not add this functionality to Go.
As I said above, this is a speculative issue, opened here because it is an obvious extension of the generics design draft. In discussion here, please focus on the benefits and costs of this specific proposal. Discussion of sum types in general, or different proposals for sum types, should remain on #19412. Thanks.