{"action":"created","issue":{"url":"https://api.github.com/repos/golang/go/issues/10709","repository_url":"https://api.github.com/repos/golang/go","labels_url":"https://api.github.com/repos/golang/go/issues/10709/labels{/name}","comments_url":"https://api.github.com/repos/golang/go/issues/10709/comments","events_url":"https://api.github.com/repos/golang/go/issues/10709/events","html_url":"https://github.com/golang/go/issues/10709","id":73456546,"number":10709,"title":"go/types: recursive functions cause broken InitOrder","user":{"login":"nlacasse","id":153325,"avatar_url":"https://avatars.githubusercontent.com/u/153325?v=3","gravatar_id":"","url":"https://api.github.com/users/nlacasse","html_url":"https://github.com/nlacasse","followers_url":"https://api.github.com/users/nlacasse/followers","following_url":"https://api.github.com/users/nlacasse/following{/other_user}","gists_url":"https://api.github.com/users/nlacasse/gists{/gist_id}","starred_url":"https://api.github.com/users/nlacasse/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/nlacasse/subscriptions","organizations_url":"https://api.github.com/users/nlacasse/orgs","repos_url":"https://api.github.com/users/nlacasse/repos","events_url":"https://api.github.com/users/nlacasse/events{/privacy}","received_events_url":"https://api.github.com/users/nlacasse/received_events","type":"User","site_admin":false},"labels":[],"state":"open","locked":false,"assignee":{"login":"griesemer","id":8528975,"avatar_url":"https://avatars.githubusercontent.com/u/8528975?v=3","gravatar_id":"","url":"https://api.github.com/users/griesemer","html_url":"https://github.com/griesemer","followers_url":"https://api.github.com/users/griesemer/followers","following_url":"https://api.github.com/users/griesemer/following{/other_user}","gists_url":"https://api.github.com/users/griesemer/gists{/gist_id}","starred_url":"https://api.github.com/users/griesemer/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/griesemer/subscriptions","organizations_url":"https://api.github.com/users/griesemer/orgs","repos_url":"https://api.github.com/users/griesemer/repos","events_url":"https://api.github.com/users/griesemer/events{/privacy}","received_events_url":"https://api.github.com/users/griesemer/received_events","type":"User","site_admin":false},"milestone":{"url":"https://api.github.com/repos/golang/go/milestones/31","html_url":"https://github.com/golang/go/milestones/Go1.7","labels_url":"https://api.github.com/repos/golang/go/milestones/31/labels","id":1414133,"number":31,"title":"Go1.7","description":"","creator":{"login":"bradfitz","id":2621,"avatar_url":"https://avatars.githubusercontent.com/u/2621?v=3","gravatar_id":"","url":"https://api.github.com/users/bradfitz","html_url":"https://github.com/bradfitz","followers_url":"https://api.github.com/users/bradfitz/followers","following_url":"https://api.github.com/users/bradfitz/following{/other_user}","gists_url":"https://api.github.com/users/bradfitz/gists{/gist_id}","starred_url":"https://api.github.com/users/bradfitz/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/bradfitz/subscriptions","organizations_url":"https://api.github.com/users/bradfitz/orgs","repos_url":"https://api.github.com/users/bradfitz/repos","events_url":"https://api.github.com/users/bradfitz/events{/privacy}","received_events_url":"https://api.github.com/users/bradfitz/received_events","type":"User","site_admin":false},"open_issues":216,"closed_issues":53,"state":"open","created_at":"2015-11-16T16:57:07Z","updated_at":"2016-02-25T16:48:29Z","due_on":"2016-07-31T07:00:00Z","closed_at":null},"comments":2,"created_at":"2015-05-05T22:57:14Z","updated_at":"2016-02-25T16:56:31Z","closed_at":null,"body":"If you have a recursive function called in an `init` function (or toplevel `var` block), the parsed `InitOrder` can be broken.  It will report that some variables should be initialized before their dependencies.\r\n\r\nFor example, in `program.go` below, we have two variables: `m` and `fooInst`.  The variable `m` depends on `fooInst`, and `fooInst` is the result of a recursive function call.\r\n\r\n```\r\npackage program\r\n\r\nvar (\r\n\tm       = fooInst.Method()\r\n\tfooInst = newFoo()\r\n)\r\n\r\ntype Foo struct{}\r\n\r\nfunc (t *Foo) Method() bool {\r\n\treturn true\r\n}\r\n\r\nfunc newFoo() *Foo {\r\n\treturn newFoo()\r\n}\r\n```\r\n\r\nThe initialization order should be `fooInst` then `m`.\r\n\r\nHowever, after parsing `program.go` with `parser.ParseFile` and then calling `config.Check`, the resulting `InitOrder` has `m` initialized before `fooInst`.\r\n\r\nHere is the parsing program I used:\r\n```\r\npackage main\r\n\r\nimport (\r\n\t\"fmt\"\r\n\t\"go/ast\"\r\n\t\"go/parser\"\r\n\t\"go/token\"\r\n\t\"golang.org/x/tools/go/types\"\r\n)\r\n\r\nfunc main() {\r\n\tfset := token.NewFileSet()\r\n\r\n\tf, err := parser.ParseFile(fset, \"program.go\", nil, 0)\r\n\tif err != nil {\r\n\t\tpanic(err)\r\n\t}\r\n\r\n\tinfo := &types.Info{}\r\n\tconfig := types.Config{}\r\n\r\n\t_, err = config.Check(\"\", fset, []*ast.File{f}, info)\r\n\tif err != nil {\r\n\t\tpanic(err)\r\n\t}\r\n\r\n\tfor k, v := range info.InitOrder {\r\n\t\tfmt.Printf(\"Initializer #%v: %v\\n\", k, v)\r\n\t}\r\n}\r\n```\r\n\r\nAnd the output:\r\n```\r\nInitializer #0: m = fooInst.Method()\r\nInitializer #1: fooInst = newFoo()\r\n```\r\n\r\nThis order is clearly broken, since `m` cannot be initialized before `fooInst`.\r\n\r\n(All tests done with go version go1.4 linux/amd64)\r\n"},"comment":{"url":"https://api.github.com/repos/golang/go/issues/comments/188877162","html_url":"https://github.com/golang/go/issues/10709#issuecomment-188877162","issue_url":"https://api.github.com/repos/golang/go/issues/10709","id":188877162,"user":{"login":"cierniak","id":1224635,"avatar_url":"https://avatars.githubusercontent.com/u/1224635?v=3","gravatar_id":"","url":"https://api.github.com/users/cierniak","html_url":"https://github.com/cierniak","followers_url":"https://api.github.com/users/cierniak/followers","following_url":"https://api.github.com/users/cierniak/following{/other_user}","gists_url":"https://api.github.com/users/cierniak/gists{/gist_id}","starred_url":"https://api.github.com/users/cierniak/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/cierniak/subscriptions","organizations_url":"https://api.github.com/users/cierniak/orgs","repos_url":"https://api.github.com/users/cierniak/repos","events_url":"https://api.github.com/users/cierniak/events{/privacy}","received_events_url":"https://api.github.com/users/cierniak/received_events","type":"User","site_admin":false},"created_at":"2016-02-25T16:56:31Z","updated_at":"2016-02-25T16:56:31Z","body":"This bug makes it impossible to use go/types as part of a frontend for a compiler. Here's an example of a Go package that is compiled incorrectly and fails at runtime because of incorrect variable initialization order: https://github.com/vanadium/go.v23/tree/master/vdl"}}