]> Cypherpunks repositories - gostls13.git/commitdiff
cmd/compile: prevent compiling closures more than once
authorCuong Manh Le <cuong.manhle.vn@gmail.com>
Fri, 22 Oct 2021 10:05:35 +0000 (17:05 +0700)
committerCuong Manh Le <cuong.manhle.vn@gmail.com>
Sat, 23 Oct 2021 06:36:16 +0000 (06:36 +0000)
Since CL 282892, functions are always compiled before closures. To do
that, when walking the closure, it is added to its outer function queue
for scheduling compilation later. Thus, a closure may be added to queue
more than once, causing the ICE dues to being compiled twice.

To fix this, catching the re-walking of the closure expression and do
not add it to the compilation queue.

Fixes #49029

Change-Id: I7d188e8f5b4d5c4248a0d8e6389da26f1084e464
Reviewed-on: https://go-review.googlesource.com/c/go/+/357960
Trust: Cuong Manh Le <cuong.manhle.vn@gmail.com>
Run-TryBot: Cuong Manh Le <cuong.manhle.vn@gmail.com>
TryBot-Result: Go Bot <gobot@golang.org>
Reviewed-by: Keith Randall <khr@golang.org>
src/cmd/compile/internal/walk/closure.go
test/fixedbugs/issue49029.go [new file with mode: 0644]

index 40535afa7a44c811c86e19a1c4f5278ee7b23d06..4d1c5621fec857fe3a9487bf9da3c422367e08d5 100644 (file)
@@ -107,7 +107,16 @@ func walkClosure(clo *ir.ClosureExpr, init *ir.Nodes) ir.Node {
        // The closure is not trivial or directly called, so it's going to stay a closure.
        ir.ClosureDebugRuntimeCheck(clo)
        clofn.SetNeedctxt(true)
-       ir.CurFunc.Closures = append(ir.CurFunc.Closures, clofn)
+
+       // The closure expression may be walked more than once if it appeared in composite
+       // literal initialization (e.g, see issue #49029).
+       //
+       // Don't add the closure function to compilation queue more than once, since when
+       // compiling a function twice would lead to an ICE.
+       if !clofn.Walked() {
+               clofn.SetWalked(true)
+               ir.CurFunc.Closures = append(ir.CurFunc.Closures, clofn)
+       }
 
        typ := typecheck.ClosureType(clo)
 
diff --git a/test/fixedbugs/issue49029.go b/test/fixedbugs/issue49029.go
new file mode 100644 (file)
index 0000000..51c9a78
--- /dev/null
@@ -0,0 +1,25 @@
+// compile
+
+// Copyright 2021 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package p
+
+type s struct {
+       f func()
+}
+
+func f() {
+       ch := make(chan struct{}, 1)
+       _ = [...]struct{ slice []s }{
+               {}, {}, {}, {},
+               {
+                       slice: []s{
+                               {
+                                       f: func() { ch <- struct{}{} },
+                               },
+                       },
+               },
+       }
+}