The following code (playground):
package main
type Iterator(type T) interface {
Next()
}
type repeat(type T) T
func (r repeat(T)) Next() {
return
}
func Repeat(type T)(val T) Iterator(T) {
return repeat(T)(val)
}
func Chain(type T)(iters Iterator(Iterator(T))) Iterator(T) {
return nil
}
func main() {
var it Iterator(int) = Chain(Repeat(Repeat(3)))
_ = it
}
gives an internal error:
./prog.go2:9: invalid receiver type instantiateą¦ą¦repeatą¦mainą®aIteratorą®8intą®9 (instantiateą¦ą¦repeatą¦mainą®aIteratorą®8intą®9 is an interface type)
Note that the implementation of repeat as a named type of T is somehow necessary to the repro; when I changed Repeat to just return nil, or changed repeat to be a struct{T}, the bug went away.
CC @griesemer
This is an interesting case. In effect we wind up adding a method to an interface type, which is normally forbidden. The translator tool will never support this. But we'll need to think about whether this can work in a full-fledged compiler.
Or perhaps it should be allowed to have methods on interface types. What is the reason they are disallowed now?
An interface type is a description of how some other type behaves. Permitting methods on interface types confuses that. What should happen if the type implements the method and the interface also implements the method? How should we handle type assertions of values of the interface type: do they have the interface type method, or do they only have the original type method? If the former, how do we implement that?
We skip all these complexities by forbidding methods on interface types.
Shorter reproducer: https://go2goplay.golang.org/p/4QG9mB3iPQl
Also consider: https://go2goplay.golang.org/p/qU88nnOcaci
I think these imply that type S(type T) T has to be illegal unless there's a constraint on T with a type list that specifically disallows interface and struct types.
Most helpful comment
An interface type is a description of how some other type behaves. Permitting methods on interface types confuses that. What should happen if the type implements the method and the interface also implements the method? How should we handle type assertions of values of the interface type: do they have the interface type method, or do they only have the original type method? If the former, how do we implement that?
We skip all these complexities by forbidding methods on interface types.