Description
In the discussion for #45346, this comment mentioned the possibility of adding a type switch on parametric types. Given that it's threatening to derail the discussion there, I'm creating this proposal to talk about it.
Proposal: type switching on type parameters
I propose that a new statement be added to the language which allows a function with type parameters to further constrain its type parameters:
switch type T {
case A1:
case A2, A3:
...
}
The switched type (T
above) must be the name of a type parameter. The type in a case arm can be any type, including constraint types.
The first case is chosen that has a constraint that matches the type parameter.
Within a chosen arm of the case statement, the type parameter that's being switched on becomes further restricted by the type selected, just as if it had originally been constrained by that type too. Precisely, given a switched type T
constrained by C
, and a type in the switch arm A
, within the code of the switch arm, T
takes on the type:
interface{
C
A
}
If there are multiple cases mentioned in the arm (A1
, A2
, ... An
), then T
is constrained by using a union element:
interface{
C
A1 | A2 | ... | An
}
Example
type Stringish interface {
string | fmt.Stringer
}
func Concat[S Stringish](x []S) string {
switch type S {
case string:
// S is constrained by interface {Stringish; string} which is the same as
// interface{string} which is the same as string, so we can use x
// as a normal []string slice.
return strings.Join(x, "")
case fmt.Stringer:
// S is constrained by interface {Stringish; Stringer}
// which is the same as `Stringer`, so we can call
// its `String` method but we can't use x directly as
// []fmt.Stringer because it might have any layout
// or size.
var buf strings.Builder
for _, s := range x {
buf.WriteString(s.String())
}
return buf.String()
}
}
The above assumes that the constraint:
interface {
X | Y | Z
X
}
would allow all operations allowed on X
, but I believe that's true under #45346 proposal.
Note: I don't think there's any need to allow ~
to be used directly in these type switch cases - case interface {~T}:
is sufficient if necessary.
Metadata
Metadata
Assignees
Type
Projects
Status