When it fires. A method spec of an interface declares type parameters of
its own, as in Map[T any](f func(string) T) T. A Go interface method cannot
have type parameters, so GALA interfaces cannot either. Type parameters on the
interface itself (type Named[T any] interface { ... }) and on methods of a
struct are fine.
Minimal repro.
package main
type Named interface {
Map[T any](f func(string) T) T
}
func main() = Println("ok")
Error output.
error[GALA-E0086]: interface method "Map" of "Named" declares a type parameter [T]: a Go interface method cannot have type parameters
--> main.gala:4:5
|
4 | Map[T any](f func(string) T) T
| ^^^ declare T on the interface instead
|
= hint: declare T on the interface instead (type Named[T any] interface { ... }), or write Map as a generic function that takes a Named
Fix. When every value of the interface works with one T, put the type
parameter on the interface. Each implementation then picks its T:
package main
type Named[T any] interface {
Map(f func(string) T) T
}
struct Person(name string)
func (p Person) Map(f func(string) int) int = f(p.name)
func main() {
val n Named[int] = Person("ada")
Println(n.Map((s) => s.Size()))
}
When the caller picks T on each call, keep the interface free of type
parameters and write the operation as a generic function that takes the
interface value:
package main
type Named interface {
Name() string
}
struct Person(name string)
func (p Person) Name() string = p.name
func MapName[T any](n Named, f func(string) T) T = f(n.Name())
func main() {
val n Named = Person("ada")
Println(MapName(n, (s) => s.Size()))
Println(MapName(n, (s) => s + "!"))
}
Rationale. A generic method of a struct can be lowered, because the
compiler sees every call and the one receiver type it calls. A call through an
interface value is dispatched at run time to whichever type the value holds,
so there is no set of instantiations to generate: an implementation would have
to provide the method for every T any caller in any package uses. Lowering
T to any would give up the concrete types GALA generates. The spec used to
be copied into the Go interface as written; that Go does not parse, and the
build stopped with an internal error (GALA-E0017)
instead of an error at the method.