From baba13293398e73d4fa3cb90c627f8aca7086a6b Mon Sep 17 00:00:00 2001 From: "Randall C. O'Reilly" Date: Fri, 19 Jul 2024 12:19:46 -0700 Subject: [PATCH] fix case where loopvar is redefined with an explicit i := i define (pre 1.22 fix for loopvar) with the same name as the original. all the other tests were using a new variable name, so we missed this case. --- _test/closure19.go | 18 ++++++++++++++++++ _test/closure20.go | 18 ++++++++++++++++++ interp/cfg.go | 16 ++++++++++++++++ 3 files changed, 52 insertions(+) create mode 100644 _test/closure19.go create mode 100644 _test/closure20.go diff --git a/_test/closure19.go b/_test/closure19.go new file mode 100644 index 00000000..7ad87fb5 --- /dev/null +++ b/_test/closure19.go @@ -0,0 +1,18 @@ +package main + +func main() { + foos := []func(){} + + for i := 0; i < 3; i++ { + i := i + foos = append(foos, func() { println(i) }) + } + foos[0]() + foos[1]() + foos[2]() +} + +// Output: +// 0 +// 1 +// 2 diff --git a/_test/closure20.go b/_test/closure20.go new file mode 100644 index 00000000..7afb6708 --- /dev/null +++ b/_test/closure20.go @@ -0,0 +1,18 @@ +package main + +func main() { + foos := []func(){} + + for i := range 3 { + i := i + foos = append(foos, func() { println(i) }) + } + foos[0]() + foos[1]() + foos[2]() +} + +// Output: +// 0 +// 1 +// 2 diff --git a/interp/cfg.go b/interp/cfg.go index 227a73a2..933e2a93 100644 --- a/interp/cfg.go +++ b/interp/cfg.go @@ -734,6 +734,22 @@ func (interp *Interpreter) cfg(root *node, sc *scope, importPath, pkgName string return } if sc.global || sc.isRedeclared(dest) { + if n.anc != nil && n.anc.anc != nil && (n.anc.anc.kind == forStmt7 || n.anc.anc.kind == rangeStmt) { + // check for redefine of for loop variables, which are now auto-defined in go1.22 + init := n.anc.anc.child[0] + var fi *node // for ident + if n.anc.anc.kind == forStmt7 { + if init.kind == defineStmt && len(init.child) >= 2 && init.child[0].kind == identExpr { + fi = init.child[0] + } + } else { // range + fi = init + } + if fi != nil && dest.ident == fi.ident { + n.gen = nop + break + } + } // Do not overload existing symbols (defined in GTA) in global scope. sym, _, _ = sc.lookup(dest.ident) }