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>
// 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)
--- /dev/null
+// 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{}{} },
+ },
+ },
+ },
+ }
+}