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/compile: recursive embedded interface types cause stack overflow #25262
Comments
@nathanjcochran Thanks for your report. |
I think this is a duplicate of a very old, known bug. Would be good to check older go versions. In any case, this is definitely in @mdempsky’s wheelhouse. |
The very old bug might be #1074. |
The issue here is that we don't have a type encoding scheme for anonymous type cycles. For types that self-reference multiple times (e.g., I think if we adopt a scheme that handles cycles better (examples), that would address this issue too. |
A simple approach (for now) might be to disallow such code as this is effectively the same as the following: package main
func main() {}
type I alias
type alias = interface {
M1() interface {
alias
}
M2() interface {
alias
}
} which is the same as package main
func main() {}
type I alias
type alias = interface {
M1() alias
M2() alias
} both of which are disallowed for the same reason the original code "explodes". Forbidding this case would certainly be less surprising than have the compiler run out of memory. It still leaves the door open to remove the restriction down the road, in a backward-compatible way. |
Marking release-blocker for now. It would be nice to have this and the other cycle-related issues addressed for 1.11 if we can. |
For comparison with other Go versions after running $ go tool compile main.go
[1]$ go tool compile main.go
runtime: goroutine stack exceeds 1000000000-byte limit
fatal error: stack overflow
runtime stack:
runtime.throw(0x4fb0f7, 0xe)
/Users/emmanuelodeke/go/src/go.googlesource.com/go/src/runtime/panic.go:566 +0x95
runtime.newstack()
/Users/emmanuelodeke/go/src/go.googlesource.com/go/src/runtime/stack.go:1061 +0x416
runtime.morestack()
/Users/emmanuelodeke/go/src/go.googlesource.com/go/src/runtime/asm_amd64.s:366 +0x7f
goroutine 1 [running]:
encoding/binary.PutVarint(0xc4404b0316, 0xa, 0xa, 0xfffffffffffffff2, 0x0)
/Users/emmanuelodeke/go/src/go.googlesource.com/go/src/encoding/binary/varint.go:78 fp=0xc4404b02d8 sp=0xc4404b02d0
cmd/compile/internal/gc.(*exporter).rawInt64(0xc4604af890, 0xfffffffffffffff2)
/Users/emmanuelodeke/go/src/go.googlesource.com/go/src/cmd/compile/internal/gc/bexport.go:1712 +0x5d fp=0xc4404b0330 sp=0xc4404b02d8
cmd/compile/internal/gc.(*exporter).tag(0xc4604af890, 0xfffffffffffffff2)
/Users/emmanuelodeke/go/src/go.googlesource.com/go/src/cmd/compile/internal/gc/bexport.go:1658 +0x101 fp=0xc4404b0380 sp=0xc4404b0330
cmd/compile/internal/gc.(*exporter).typ(0xc4604af890, 0xc42041fc70)
/Users/emmanuelodeke/go/src/go.googlesource.com/go/src/cmd/compile/internal/gc/bexport.go:792 +0xeb1 fp=0xc4404b04e8 sp=0xc4404b0380
cmd/compile/internal/gc.(*exporter).param(0xc4604af890, 0xc42040d5c0, 0xffffffffffffffff, 0x0)
/Users/emmanuelodeke/go/src/go.googlesource.com/go/src/cmd/compile/internal/gc/bexport.go:938 +0x49 fp=0xc4404b0530 sp=0xc4404b04e8
cmd/compile/internal/gc.(*exporter).paramList(0xc4604af890, 0xc42041fc20, 0xc42040d600)
/Users/emmanuelodeke/go/src/go.googlesource.com/go/src/cmd/compile/internal/gc/bexport.go:928 +0xf1 fp=0xc4404b0588 sp=0xc4404b0530
cmd/compile/internal/gc.(*exporter).method(0xc4604af890, 0xc42040d680)
/Users/emmanuelodeke/go/src/go.googlesource.com/go/src/cmd/compile/internal/gc/bexport.go:863 +0xbc fp=0xc4404b05b0 sp=0xc4404b0588
cmd/compile/internal/gc.(*exporter).methodList(0xc4604af890, 0xc42041fc70)
/Users/emmanuelodeke/go/src/go.googlesource.com/go/src/cmd/compile/internal/gc/bexport.go:855 +0xb8 fp=0xc4404b0620 sp=0xc4404b05b0
cmd/compile/internal/gc.(*exporter).typ(0xc4604af890, 0xc42041fc70)
/Users/emmanuelodeke/go/src/go.googlesource.com/go/src/cmd/compile/internal/gc/bexport.go:797 +0xee9 fp=0xc4404b0788 sp=0xc4404b0620
cmd/compile/internal/gc.(*exporter).param(0xc4604af890, 0xc42040d5c0, 0xffffffffffffffff, 0x0)
/Users/emmanuelodeke/go/src/go.googlesource.com/go/src/cmd/compile/internal/gc/bexport.go:938 +0x49 fp=0xc4404b07d0 sp=0xc4404b0788
cmd/compile/internal/gc.(*exporter).paramList(0xc4604af890, 0xc42041fc20, 0xc42040d600)
/Users/emmanuelodeke/go/src/go.googlesource.com/go/src/cmd/compile/internal/gc/bexport.go:928 +0xf1 fp=0xc4404b0828 sp=0xc4404b07d0
cmd/compile/internal/gc.(*exporter).method(0xc4604af890, 0xc42040d680)
/Users/emmanuelodeke/go/src/go.googlesource.com/go/src/cmd/compile/internal/gc/bexport.go:863 +0xbc fp=0xc4404b0850 sp=0xc4404b0828
cmd/compile/internal/gc.(*exporter).methodList(0xc4604af890, 0xc42041fc70)
/Users/emmanuelodeke/go/src/go.googlesource.com/go/src/cmd/compile/internal/gc/bexport.go:855 +0xb8 fp=0xc4404b08c0 sp=0xc4404b0850
cmd/compile/internal/gc.(*exporter).typ(0xc4604af890, 0xc42041fc70)
/Users/emmanuelodeke/go/src/go.googlesource.com/go/src/cmd/compile/internal/gc/bexport.go:797 +0xee9 fp=0xc4404b0a28 sp=0xc4404b08c0
cmd/compile/internal/gc.(*exporter).param(0xc4604af890, 0xc42040d5c0, 0xffffffffffffffff, 0x0)
/Users/emmanuelodeke/go/src/go.googlesource.com/go/src/cmd/compile/internal/gc/bexport.go:938 +0x49 fp=0xc4404b0a70 sp=0xc4404b0a28
<frames_elided> [2]$ go tool compile main.go
./main.go:8: cannot export unnamed recursive interface
./main.go:11: cannot export unnamed recursive interface
./main.go:11: too many errors |
Thanks, @odeke-em for this analysis; this is useful. As this is not a regression, I'll push this to 1.12. A fix will likely be involved and it's too risky for 1.11 at this point. |
Too late for 1.12. |
This seems to work now with Go 1.18. Closing. |
What did you do?
I tried to compile the following program, but it caused the compiler to hang indefinitely:
If you remove either of the two interface method definitions (
M1
orM2
), it compiles. Furthermore, it seems to exhibit the same behavior whether the anonymous interfaces are for the method return types, parameter types, or a mixture of the two.Go Playground: https://play.golang.org/p/UkT9bStm3tR (After the first run on the Go Playground, which hung until it timed out, the playground started responding immediately with what appears to be a cached error message).
Github: https://github.com/nathanjcochran/hung-compiler
What did you expect to see?
I expected it to compile.
What did you see instead?
The compiler hangs indefinitely.
Does this issue reproduce with the latest release (go1.10.2)?
I tried it with go1.10.1, but not go1.10.2
EDIT: I tried it with go1.10.2, and it still hung indefinitely
System details
The text was updated successfully, but these errors were encountered: