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/compile: The compiler does not detect an initialization loop #13343

Closed
momchil-velikov opened this issue Nov 20, 2015 · 4 comments
Closed
Milestone

Comments

@momchil-velikov
Copy link
Contributor

... as in the following program:

package main

var (
    a, b = f()
    c    = b
)

func f() (int, int) {
    return c, c
}

func main() {}

Related, though different issue here: #7320

go version go1.5.1 darwin/amd64
go version go1.5.1 linux/amd64
go version devel +af8cd3f Fri Nov 20 19:56:51 2015 +0000 linux/amd64

@ianlancetaylor ianlancetaylor added this to the Go1.6 milestone Nov 20, 2015
@ianlancetaylor
Copy link
Contributor

FYI, gccgo reports

foo.go:4:8: error: initialization expressions for ‘b’ and ‘c’ depend upon each other
     a, b = f()
        ^
foo.go:5:5: note: ‘c’ defined here
     c    = b
     ^
foo.go:5:5: error: initialization expressions for ‘c’ and ‘b’ depend upon each other
foo.go:4:8: note: ‘b’ defined here
     a, b = f()
        ^
/home/iant/foo4.go:5:5: error: initialization expression for ‘c’ depends upon itself
     c    = b
     ^

@griesemer
Copy link
Contributor

gotype reports:

foo.go:4:8: initialization cycle for b
foo.go:4:8:     b refers to
foo.go:8:6:     f refers to
foo.go:5:5:     c refers to
foo.go:4:8:     b

@rsc rsc modified the milestones: Go1.7, Go1.6 Dec 5, 2015
@kvu787
Copy link
Contributor

kvu787 commented Jan 4, 2016

Interestingly, swapping a and b does generate a cycle error:

package main

var (
    b, a = f()
    c    = b
)

func f() (int, int) {
    return c, c
}

func main() {}

cmd/compile/internal/gc/sinit.go:init1 is responsible for producing a list of definitions needing initialization code in dependency order, and for detecting initialization loops. init1 incorrectly marks function nodes as InitDone prior to traversing them.

Hence, in the first example, it will not detect the cycle on b because that involves traversing f twice:

a, b = f()
a
f()
f // mark f as done, but still traverse it
c
b
f()
// f has been marked done, so it is not checked and the cycle is undetected

In the second example, it will detect the cycle because f only has to be traversed once:

b, a = f()
f()
f
c
b // cycle detected

@gopherbot
Copy link

CL https://golang.org/cl/18159 mentions this issue.

@rsc rsc closed this as completed in aaabe3d Jan 6, 2016
@golang golang locked and limited conversation to collaborators Jan 7, 2017
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Projects
None yet
Development

No branches or pull requests

6 participants