In Go generics, how to use a common method for types in a union constraint?

Add the method to the interface constraint, without forgoing generics:

type AB interface {
    *A | *B
    some() bool
}

func some[T AB](x T) bool {
    return x.some()   // works
}

This restricts T to types that are either *A or *B and declare some() bool method.

However, as you already found out, this is a workaround. You are right that it should work with the type union alone. It’s a limitation of Go 1.18. The confusing part is that the language specifications still seem to support your theory (Method sets):

The method set of an interface type is the intersection of the method sets of each type in the interface’s type set (the resulting method set is usually just the set of declared methods in the interface).

This limitation appears to be documented only in the Go 1.18 release notes:

The current generics implementation has the following limitations:

[…]
The Go compiler currently only supports calling a method m on a value x of type parameter type P if m is explicitly declared by P‘s constraint interface. […] even though m might be in the method set of P by virtue of the fact that all types in P implement m. We hope to remove this restriction in Go 1.19.

The relevant issue in the Go tracker is #51183, with Griesemer’s confirmation and the decision to leave the language specifications as is, and document the restriction.

Leave a Comment