{"action":"created","issue":{"url":"https://api.github.com/repos/golang/go/issues/21120","repository_url":"https://api.github.com/repos/golang/go","labels_url":"https://api.github.com/repos/golang/go/issues/21120/labels{/name}","comments_url":"https://api.github.com/repos/golang/go/issues/21120/comments","events_url":"https://api.github.com/repos/golang/go/issues/21120/events","html_url":"https://github.com/golang/go/issues/21120","id":244800293,"number":21120,"title":"cmd/compile: incorrectly permits merging of unexported embedded pointer field name","user":{"login":"ianlancetaylor","id":3194333,"avatar_url":"https://avatars2.githubusercontent.com/u/3194333?v=4","gravatar_id":"","url":"https://api.github.com/users/ianlancetaylor","html_url":"https://github.com/ianlancetaylor","followers_url":"https://api.github.com/users/ianlancetaylor/followers","following_url":"https://api.github.com/users/ianlancetaylor/following{/other_user}","gists_url":"https://api.github.com/users/ianlancetaylor/gists{/gist_id}","starred_url":"https://api.github.com/users/ianlancetaylor/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/ianlancetaylor/subscriptions","organizations_url":"https://api.github.com/users/ianlancetaylor/orgs","repos_url":"https://api.github.com/users/ianlancetaylor/repos","events_url":"https://api.github.com/users/ianlancetaylor/events{/privacy}","received_events_url":"https://api.github.com/users/ianlancetaylor/received_events","type":"User","site_admin":false},"labels":[{"id":626114820,"url":"https://api.github.com/repos/golang/go/labels/release-blocker","name":"release-blocker","color":"b60205","default":false}],"state":"open","locked":false,"assignee":null,"assignees":[],"milestone":{"url":"https://api.github.com/repos/golang/go/milestones/49","html_url":"https://github.com/golang/go/milestone/49","labels_url":"https://api.github.com/repos/golang/go/milestones/49/labels","id":2053058,"number":49,"title":"Go1.9","description":"","creator":{"login":"rsc","id":104030,"avatar_url":"https://avatars1.githubusercontent.com/u/104030?v=4","gravatar_id":"","url":"https://api.github.com/users/rsc","html_url":"https://github.com/rsc","followers_url":"https://api.github.com/users/rsc/followers","following_url":"https://api.github.com/users/rsc/following{/other_user}","gists_url":"https://api.github.com/users/rsc/gists{/gist_id}","starred_url":"https://api.github.com/users/rsc/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/rsc/subscriptions","organizations_url":"https://api.github.com/users/rsc/orgs","repos_url":"https://api.github.com/users/rsc/repos","events_url":"https://api.github.com/users/rsc/events{/privacy}","received_events_url":"https://api.github.com/users/rsc/received_events","type":"User","site_admin":false},"open_issues":15,"closed_issues":607,"state":"open","created_at":"2016-10-06T18:17:55Z","updated_at":"2017-07-21T22:46:30Z","due_on":"2017-07-31T07:00:00Z","closed_at":null},"comments":2,"created_at":"2017-07-21T22:45:13Z","updated_at":"2017-07-21T23:58:53Z","closed_at":null,"body":"Test case has three input files.\r\n\r\na.go:\r\n\r\n```\r\npackage a\r\n\r\nimport \"reflect\"\r\n\r\ntype S struct {\r\n\tx int\r\n}\r\n\r\nfunc F() string {\r\n\tv := reflect.TypeOf(S{0})\r\n\treturn v.PkgPath()\r\n}\r\n```\r\n\r\nb.go:\r\n\r\n```\r\npackage b\r\n\r\nimport \"reflect\"\r\n\r\ntype X int\r\n\r\nfunc F1() string {\r\n\ttype x X\r\n\r\n\ts := struct {\r\n\t\t*x\r\n\t}{nil}\r\n\tv := reflect.TypeOf(s)\r\n\treturn v.Field(0).PkgPath\r\n}\r\n\r\nfunc F2() string {\r\n\ttype y X\r\n\r\n\ts := struct {\r\n\t\t*y\r\n\t}{nil}\r\n\tv := reflect.TypeOf(s)\r\n\treturn v.Field(0).PkgPath\r\n}\r\n```\r\n\r\nmain.go:\r\n\r\n```\r\npackage main\r\n\r\nimport (\r\n\t\"fmt\"\r\n\t\"os\"\r\n\r\n\t\"./a\"\r\n\t\"./b\"\r\n)\r\n\r\nfunc main() {\r\n\tok := true\r\n\tif s, want := a.F(), \"a\"; s != want {\r\n\t\tfmt.Printf(\"a.F() == %q, expected %q\\n\", s, want)\r\n\t\tok = false\r\n\t}\r\n\tif s, want := b.F1(), \"\"; s != want {\r\n\t\tfmt.Printf(\"b.F1() == %q, expected %q\\n\", s, want)\r\n\t\tok = false\r\n\t}\r\n\tif s, want := b.F2(), \"\"; s != want {\r\n\t\tfmt.Printf(\"b.F2() == %q, expected %q\\n\", s, want)\r\n\t\tok = false\r\n\t}\r\n\tif !ok {\r\n\t\tos.Exit(1)\r\n\t}\r\n}\r\n```\r\n\r\nThe two functions in b.go are identical except for the name they use for the type defined within the function.  Therefore, they should return the same value.  All Go releases since Go 1 have returned the empty string for the `PkgPath` of a struct field of embedded pointer type, even if the embedded pointer type is not exported.  That seems wrong, but it is what we have done, and it is what the code in main.go expects.\r\n\r\nHowever, in this case, `F1` does not return an empty string.  The reason is that `F1` uses a name `x` that is internally represented as a string with the exported flag (the least significant bit of the first byte in the `reflect.name`) clear.  That is fine, but in a.go the existence of the field `x` in `S` produces a name `x` that is internally represented as a string with the exported flag set.  Although those two `reflect.name` values are different, the compiler generates the same symbol name for both (`type..namedata.x.`).  The linker merges the two names, causing `F1` to unexpectedly see an unexported name, and to therefore return an unexpected non-empty `PkgPath`.\r\n\r\nThis bug is new in 1.9.  I suspect that it was introduced by https://golang.org/cl/35732."},"comment":{"url":"https://api.github.com/repos/golang/go/issues/comments/317137693","html_url":"https://github.com/golang/go/issues/21120#issuecomment-317137693","issue_url":"https://api.github.com/repos/golang/go/issues/21120","id":317137693,"user":{"login":"ianlancetaylor","id":3194333,"avatar_url":"https://avatars2.githubusercontent.com/u/3194333?v=4","gravatar_id":"","url":"https://api.github.com/users/ianlancetaylor","html_url":"https://github.com/ianlancetaylor","followers_url":"https://api.github.com/users/ianlancetaylor/followers","following_url":"https://api.github.com/users/ianlancetaylor/following{/other_user}","gists_url":"https://api.github.com/users/ianlancetaylor/gists{/gist_id}","starred_url":"https://api.github.com/users/ianlancetaylor/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/ianlancetaylor/subscriptions","organizations_url":"https://api.github.com/users/ianlancetaylor/orgs","repos_url":"https://api.github.com/users/ianlancetaylor/repos","events_url":"https://api.github.com/users/ianlancetaylor/events{/privacy}","received_events_url":"https://api.github.com/users/ianlancetaylor/received_events","type":"User","site_admin":false},"created_at":"2017-07-21T23:58:53Z","updated_at":"2017-07-21T23:58:53Z","body":"@odeke-em Thanks, the `expected \"a\"` only expects `\"a\"` if you write the import exactly as `\"./a\"`.  So it's OK that your version acts differently.\r\n\r\nIn any case the CL I just sent has a cleaner version of the test, that simply verifies that the two essentially identical functions return the same result, which I believe they should."}}
{"actor":{"display_login":"ianlancetaylor"}}