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: Failing to handle generic instances that are unknown until the run time. #42863

Open
Joker-vD opened this issue Nov 28, 2020 · 6 comments
Assignees
Milestone

Comments

@Joker-vD
Copy link

@Joker-vD Joker-vD commented Nov 28, 2020

What version of Go are you using (go version)?

	fmt.Printf("%s\n", runtime.Version())
devel +9daca74ad2 Wed Nov 18 00:18:01 2020 +0000

What operating system and processor architecture are you using (go env)?

	fmt.Printf("%s/%s\n", runtime.GOOS, runtime.GOARCH)
linux/amd64

What did you do?

https://go2goplay.golang.org/p/NZaWIbJ5DAw (inspired by an example from http://okmij.org/ftp/Computation/typeclass.html, starting at the words "The final example deals with polymorphic recursion").

What did you expect to see?

Either that the program compiles and outputs {{{{{test}}}}}, or a compilation error that essentially says "All generic instantiations must be known at compile time", or even "The type T in wrapper[T] is not allowed to be an instance of wrapper[T]", is reported.

I believe a slightly modified example (https://go2goplay.golang.org/p/1TnY_eXmRQY, with T's bound changed from any to fmt.Stringer) should not trigger "The type T in wrapper[T] is not allowed to be an instance of wrapper[T]" error, since in this case a value of type T is not directly embedded into wrapper[T] but instead an interface pointer to it is stored.

What did you see instead?

panic: runtime error: invalid memory address or nil pointer dereference
[signal SIGSEGV: segmentation violation code=0x1 addr=0x48 pc=0x627cbe]

goroutine 1 [running]:
go/go2go.(*translator).sameType(0xc0003d3950, 0x0, 0x0, 0x6ec140, 0x8188c0, 0x58de00)
	/usr/local/go-faketime/src/go/go2go/rewrite.go:1250 +0x7e
go/go2go.(*translator).sameType(0xc0003d3950, 0x6ec3c0, 0xc0003895f0, 0x6ec3c0, 0xc00007ac60, 0x58de00)
	/usr/local/go-faketime/src/go/go2go/rewrite.go:1269 +0x1ec
go/go2go.(*translator).sameType(0xc0003d3950, 0x6ec3c0, 0xc000389680, 0x6ec3c0, 0xc00007ad80, 0x58de00)
	/usr/local/go-faketime/src/go/go2go/rewrite.go:1269 +0x1ec
go/go2go.(*translator).sameType(0xc0003d3950, 0x6ec3c0, 0xc000389710, 0x6ec3c0, 0xc00007af30, 0x58de00)
	/usr/local/go-faketime/src/go/go2go/rewrite.go:1269 +0x1ec
go/go2go.(*translator).sameType(0xc0003d3950, 0x6ec3c0, 0xc0003897a0, 0x6ec3c0, 0xc00007b0e0, 0x58de00)
	/usr/local/go-faketime/src/go/go2go/rewrite.go:1269 +0x1ec
go/go2go.(*translator).sameType(0xc0003d3950, 0x6ec3c0, 0xc000389830, 0x6ec3c0, 0xc00007b290, 0x58de00)
	/usr/local/go-faketime/src/go/go2go/rewrite.go:1269 +0x1ec
go/go2go.(*translator).sameType(0xc0003d3950, 0x6ec3c0, 0xc0003898c0, 0x6ec3c0, 0xc00007b440, 0x58de00)
	/usr/local/go-faketime/src/go/go2go/rewrite.go:1269 +0x1ec
go/go2go.(*translator).sameType(0xc0003d3950, 0x6ec3c0, 0xc000389950, 0x6ec3c0, 0xc00007b5f0, 0x58de00)
	/usr/local/go-faketime/src/go/go2go/rewrite.go:1269 +0x1ec
go/go2go.(*translator).sameType(0xc0003d3950, 0x6ec3c0, 0xc0003899e0, 0x6ec3c0, 0xc00007b7a0, 0x58de00)
	/usr/local/go-faketime/src/go/go2go/rewrite.go:1269 +0x1ec
go/go2go.(*translator).sameType(0xc0003d3950, 0x6ec3c0, 0xc000389a70, 0x6ec3c0, 0xc00007b950, 0x58de00)
	/usr/local/go-faketime/src/go/go2go/rewrite.go:1269 +0x1ec
go/go2go.(*translator).sameType(0xc0003d3950, 0x6ec3c0, 0xc000389b00, 0x6ec3c0, 0xc00007bb00, 0x58de00)
	/usr/local/go-faketime/src/go/go2go/rewrite.go:1269 +0x1ec
go/go2go.(*translator).sameType(0xc0003d3950, 0x6ec3c0, 0xc000389b90, 0x6ec3c0, 0xc00007bcb0, 0x58de00)
	/usr/local/go-faketime/src/go/go2go/rewrite.go:1269 +0x1ec
go/go2go.(*translator).sameType(0xc0003d3950, 0x6ec3c0, 0xc000389c20, 0x6ec3c0, 0xc00007be60, 0x58de00)
	/usr/local/go-faketime/src/go/go2go/rewrite.go:1269 +0x1ec
go/go2go.(*translator).sameType(0xc0003d3950, 0x6ec3c0, 0xc000389cb0, 0x6ec3c0, 0xc000388090, 0x58de00)
	/usr/local/go-faketime/src/go/go2go/rewrite.go:1269 +0x1ec
go/go2go.(*translator).sameType(0xc0003d3950, 0x6ec3c0, 0xc000389d40, 0x6ec3c0, 0xc000388240, 0x58de00)
	/usr/local/go-faketime/src/go/go2go/rewrite.go:1269 +0x1ec
go/go2go.(*translator).sameType(0xc0003d3950, 0x6ec3c0, 0xc000389dd0, 0x6ec3c0, 0xc0003883f0, 0x58de00)
	/usr/local/go-faketime/src/go/go2go/rewrite.go:1269 +0x1ec
go/go2go.(*translator).sameType(0xc0003d3950, 0x6ec3c0, 0xc000389e60, 0x6ec3c0, 0xc0003885a0, 0x58de00)
	/usr/local/go-faketime/src/go/go2go/rewrite.go:1269 +0x1ec
go/go2go.(*translator).sameType(0xc0003d3950, 0x6ec3c0, 0xc000389ef0, 0x6ec3c0, 0xc000388750, 0x58de00)
	/usr/local/go-faketime/src/go/go2go/rewrite.go:1269 +0x1ec
go/go2go.(*translator).sameType(0xc0003d3950, 0x6ec3c0, 0xc0003d8000, 0x6ec3c0, 0xc000388900, 0x58de00)
	/usr/local/go-faketime/src/go/go2go/rewrite.go:1269 +0x1ec
go/go2go.(*translator).sameType(0xc0003d3950, 0x6ec3c0, 0xc0003d8090, 0x6ec3c0, 0xc000388ab0, 0x58de00)
	/usr/local/go-faketime/src/go/go2go/rewrite.go:1269 +0x1ec
go/go2go.(*translator).sameType(0xc0003d3950, 0x6ec3c0, 0xc0003d8120, 0x6ec3c0, 0xc000388c60, 0x58de00)
	/usr/local/go-faketime/src/go/go2go/rewrite.go:1269 +0x1ec
go/go2go.(*translator).sameType(0xc0003d3950, 0x6ec3c0, 0xc0003d81b0, 0x6ec3c0, 0xc000388e10, 0x58de00)
	/usr/local/go-faketime/src/go/go2go/rewrite.go:1269 +0x1ec
go/go2go.(*translator).sameType(0xc0003d3950, 0x6ec3c0, 0xc0003d8240, 0x6ec3c0, 0xc000388fc0, 0x58de00)
	/usr/local/go-faketime/src/go/go2go/rewrite.go:1269 +0x1ec
go/go2go.(*translator).sameType(0xc0003d3950, 0x6ec3c0, 0xc0003d82d0, 0x6ec3c0, 0xc000389170, 0x58de00)
	/usr/local/go-faketime/src/go/go2go/rewrite.go:1269 +0x1ec
go/go2go.(*translator).sameType(0xc0003d3950, 0x6ec3c0, 0xc0003d8360, 0x6ec3c0, 0xc000389320, 0x40f100)
	/usr/local/go-faketime/src/go/go2go/rewrite.go:1269 +0x1ec
go/go2go.(*translator).sameType(0xc0003d3950, 0x6ec3c0, 0xc0003d83f0, 0x6ec3c0, 0xc0003894d0, 0xc000367000)
	/usr/local/go-faketime/src/go/go2go/rewrite.go:1269 +0x1ec
go/go2go.(*translator).setType(0xc0003d3950, 0x6e90a0, 0xc00039f4a0, 0x6ec3c0, 0xc0003894d0)
	/usr/local/go-faketime/src/go/go2go/types.go:39 +0x1c5
go/go2go.(*translator).typeToAST(0xc0003d3950, 0x6ec3c0, 0xc0003894d0, 0xc0003ba970, 0xc000366fd0)
	/usr/local/go-faketime/src/go/go2go/types.go:601 +0x607
go/go2go.(*translator).typeListToASTList(0xc0003d3950, 0xc0003ba910, 0x1, 0x1, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0)
	/usr/local/go-faketime/src/go/go2go/rewrite.go:1208 +0xe5
go/go2go.(*translator).instantiationTypes(0xc0003d3950, 0x6e8ca0, 0xc00039bae0, 0x0, 0xc00000c780, 0x5, 0xc0000fc000, 0xc0003672d0, 0x528c6c, 0x6578a0)
	/usr/local/go-faketime/src/go/go2go/rewrite.go:1071 +0x110
go/go2go.(*translator).translateFunctionInstantiation(0xc0003d3950, 0xc0003ba8e0)
	/usr/local/go-faketime/src/go/go2go/rewrite.go:889 +0xb1
go/go2go.(*translator).translateExpr(0xc0003d3950, 0xc0003ba8e0)
	/usr/local/go-faketime/src/go/go2go/rewrite.go:687 +0x3cc
go/go2go.(*translator).translateExprList(0xc0003d3950, 0xc0003ba8e0, 0x1, 0x1)
	/usr/local/go-faketime/src/go/go2go/rewrite.go:865 +0x46
go/go2go.(*translator).translateStmt(0xc000367950, 0xc00039f390)
	/usr/local/go-faketime/src/go/go2go/rewrite.go:596 +0x225
go/go2go.(*translator).translateBlockStmt(0xc0003d3950, 0xc0003c2090)
	/usr/local/go-faketime/src/go/go2go/rewrite.go:547 +0x57
go/go2go.(*translator).translateFuncDecl(0xc000367950, 0xc0003be620)
	/usr/local/go-faketime/src/go/go2go/rewrite.go:538 +0xdb
go/go2go.(*translator).translate(0xc0003d3950, 0xc00007a2d0)
	/usr/local/go-faketime/src/go/go2go/rewrite.go:466 +0x391
go/go2go.rewriteAST(0xc000072280, 0xc00004a3c0, 0x0, 0x0, 0xc000055950, 0xc00007a2d0, 0x1, 0xc0000553b0, 0xc000055950)
	/usr/local/go-faketime/src/go/go2go/rewrite.go:257 +0xe5
go/go2go.RewriteBuffer(0xc00004a3c0, 0x7ffc9df9fdec, 0x1e, 0xc0000ba000, 0x172, 0x372, 0x0, 0xc000010a80, 0xc000010a50, 0xc000010a20, ...)
	/usr/local/go-faketime/src/go/go2go/go2go.go:144 +0x2c5
main.translateFile(0xc00004a3c0, 0x7ffc9df9fdec, 0x1e)
	/usr/local/go-faketime/src/cmd/go2go/translate.go:26 +0xa9
main.main()
	/usr/local/go-faketime/src/cmd/go2go/main.go:74 +0x309

Go build failed.
@ianlancetaylor
Copy link
Contributor

@ianlancetaylor ianlancetaylor commented Nov 28, 2020

The generics design draft is clear that if a generic type refers to itself, it must use the same type arguments. Likely the same restriction should be applied to generic functions, in which case this test case would generate an error in the type checker.

@griesemer Any thoughts?

@Joker-vD
Copy link
Author

@Joker-vD Joker-vD commented Nov 28, 2020

if a generic type refers to itself, it must use the same type arguments

Oh, right, it says "refers", not "names". Perhaps some example in the document would be helpful? That e.g. if foo[T] has a T field, this T cannot be instantiated by foo[U] for any U, etc. Nevermind, there is an example.

Also, should not that part be talking about "instantiations of a generic type"? Strictly speaking the generic type wrapper[T] doesn't refer to itself, but its instantiation wrapper[wrapper[string]] refers to wrapper[string] which is an instantiation of the same generic type with different type, which is not allowed.

@Joker-vD
Copy link
Author

@Joker-vD Joker-vD commented Nov 28, 2020

Wait, does that mean that type Vector[T any] []T can't be used for making vectors of vectors, since Vector[Vector[int]] would break this restriction?

@ianlancetaylor
Copy link
Contributor

@ianlancetaylor ianlancetaylor commented Nov 28, 2020

The restriction is on the definition of Vector itself. There is no restriction on the type arguments used to instantiate Vector.

@Joker-vD
Copy link
Author

@Joker-vD Joker-vD commented Nov 28, 2020

Oh, I think now I get what restriction on generic functions you mean: func Foo[T] must only call itself (directly or indirectly) as Foo[T] exactly; so stringWrapped[T] is forbidden to instantiate and call stringWrapped[wrapper[T]], and so there is no explosion of types.

@griesemer
Copy link
Contributor

@griesemer griesemer commented Dec 2, 2020

In any case, this code should not lead to an endless recursion. The problem should be caught at typechecking time.

@griesemer griesemer self-assigned this Dec 2, 2020
@griesemer griesemer modified the milestones: Unreleased, Go1.17 Dec 2, 2020
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
3 participants
You can’t perform that action at this time.