]> Cypherpunks repositories - gostls13.git/commitdiff
go/types: fix regression with short variable declarations
authorRobert Griesemer <gri@golang.org>
Thu, 22 Feb 2018 04:27:29 +0000 (20:27 -0800)
committerRobert Griesemer <gri@golang.org>
Thu, 22 Feb 2018 16:28:38 +0000 (16:28 +0000)
The variables on the lhs of a short variable declaration are
only in scope after the variable declaration. Specifically,
function literals on the rhs of a short variable declaration
must not see newly declared variables on the lhs.

This used to work and this bug was likely introduced with
https://go-review.googlesource.com/c/go/+/83397 for go1.11.
Luckily this is just an oversight and the fix is trivial:
Simply use the mechanism for delayed type-checkin of function
literals introduced in the before-mentioned change here as well.

Fixes #24026.

Change-Id: I74ce3a0d05c5a2a42ce4b27601645964f906e82d
Reviewed-on: https://go-review.googlesource.com/96177
Reviewed-by: Alan Donovan <adonovan@google.com>
src/go/types/assignments.go
src/go/types/testdata/issues.src

index f0030efedcd3ab9ee2e03b907f41554f71031f02..cb0fe3bc3a775c5600b6c37629ea9931259281e8 100644 (file)
@@ -279,6 +279,7 @@ func (check *Checker) assignVars(lhs, rhs []ast.Expr) {
 }
 
 func (check *Checker) shortVarDecl(pos token.Pos, lhs, rhs []ast.Expr) {
+       top := len(check.delayed)
        scope := check.scope
 
        // collect lhs variables
@@ -319,6 +320,9 @@ func (check *Checker) shortVarDecl(pos token.Pos, lhs, rhs []ast.Expr) {
 
        check.initVars(lhsVars, rhs, token.NoPos)
 
+       // process function literals in rhs expressions before scope changes
+       check.processDelayed(top)
+
        // declare new variables
        if len(newVars) > 0 {
                // spec: "The scope of a constant or variable identifier declared inside
index 8729555e175546bc0a9847cd1d5a8023ca13fd50..a346ab169aaa31c48eba847559d129df9c6a2026 100644 (file)
@@ -207,3 +207,25 @@ func issue20358() {
        _ = T{t}
        _ = P{f: p}
 }
+
+// Test that we don't declare lhs variables in short variable
+// declarations before we type-check function literals on the
+// rhs.
+func issue24026() {
+       f := func() int { f(0) /* must refer to outer f */; return 0 }
+       _ = f
+
+       _ = func() {
+               f := func() { _ = f() /* must refer to outer f */ }
+               _ = f
+       }
+
+       // b and c must not be visible inside function literal
+       a := 0
+       a, b, c := func() (int, int, int) {
+               return a, b /* ERROR undeclared */ , c /* ERROR undeclared */
+       }()
+       _, _ = b, c
+}
+
+func f(int) {} // for issue24026