Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

cmd/go2go: internal error when nesting named generic type #40019

Open
benjaminjkraft opened this issue Jul 3, 2020 · 4 comments
Open

cmd/go2go: internal error when nesting named generic type #40019

benjaminjkraft opened this issue Jul 3, 2020 · 4 comments

Comments

@benjaminjkraft
Copy link

@benjaminjkraft benjaminjkraft commented Jul 3, 2020

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.

@ianlancetaylor
Copy link
Contributor

@ianlancetaylor ianlancetaylor commented Jul 3, 2020

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.

@beoran
Copy link

@beoran beoran commented Jul 4, 2020

Or perhaps it should be allowed to have methods on interface types. What is the reason they are disallowed now?

@ianlancetaylor
Copy link
Contributor

@ianlancetaylor ianlancetaylor commented Jul 4, 2020

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.

@jimmyfrasche
Copy link
Member

@jimmyfrasche jimmyfrasche commented Jul 4, 2020

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.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Linked pull requests

Successfully merging a pull request may close this issue.

None yet
4 participants
You can’t perform that action at this time.