Skip to content

Commit 06b86e9

Browse files
committed
cmd/compile: fix check to avoid creating new closure function when typechecking inline body
By default, when typechecking a closure, tcClosure() creates a new closure function. This should really be done separate from typechecking. For now, we explicitly avoid creating a new closure function when typechecking an inline body (in ImportedBody). However, the heuristic for determining when we are typechecking an inline body was not correct for double nested closures in an inline body, since CurFunc will then be the inner closure, which has a body. So, use a simple global variable to indicate when we typechecking an inline body. The global variable is fine (just like ir.CurFunc), since the front-end runs serially. Fixes #44325 Change-Id: If2829fe1ebb195a7b1a240192b57fe6f04d1a36b Reviewed-on: https://go-review.googlesource.com/c/go/+/294211 TryBot-Result: Go Bot <[email protected]> Reviewed-by: Matthew Dempsky <[email protected]> Trust: Dan Scales <[email protected]> Run-TryBot: Dan Scales <[email protected]>
1 parent 9322eec commit 06b86e9

File tree

4 files changed

+43
-1
lines changed

4 files changed

+43
-1
lines changed

src/cmd/compile/internal/typecheck/func.go

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -100,6 +100,11 @@ func PartialCallType(n *ir.SelectorExpr) *types.Type {
100100
return t
101101
}
102102

103+
// True if we are typechecking an inline body in ImportedBody below. We use this
104+
// flag to not create a new closure function in tcClosure when we are just
105+
// typechecking an inline body, as opposed to the body of a real function.
106+
var inTypeCheckInl bool
107+
103108
// Lazy typechecking of imported bodies. For local functions, CanInline will set ->typecheck
104109
// because they're a copy of an already checked body.
105110
func ImportedBody(fn *ir.Func) {
@@ -138,7 +143,12 @@ func ImportedBody(fn *ir.Func) {
138143

139144
savefn := ir.CurFunc
140145
ir.CurFunc = fn
146+
if inTypeCheckInl {
147+
base.Fatalf("inTypeCheckInl should not be set recursively")
148+
}
149+
inTypeCheckInl = true
141150
Stmts(fn.Inl.Body)
151+
inTypeCheckInl = false
142152
ir.CurFunc = savefn
143153

144154
// During ImportBody (which imports fn.Func.Inl.Body),
@@ -307,7 +317,6 @@ func tcClosure(clo *ir.ClosureExpr, top int) {
307317
// body in ImportedBody(), since we only want to create the named function
308318
// when the closure is actually inlined (and then we force a typecheck
309319
// explicitly in (*inlsubst).node()).
310-
inTypeCheckInl := ir.CurFunc != nil && ir.CurFunc.Body == nil
311320
if !inTypeCheckInl {
312321
fn.Nname.SetSym(ClosureName(ir.CurFunc))
313322
ir.MarkFunc(fn.Nname)

test/fixedbugs/issue44325.dir/a.go

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
// Copyright 2021 The Go Authors. All rights reserved. Use of this
2+
// source code is governed by a BSD-style license that can be found in
3+
// the LICENSE file.
4+
5+
package a
6+
7+
func FM() func() {
8+
return func() {
9+
_ = func() int {
10+
return 0
11+
}
12+
}
13+
}

test/fixedbugs/issue44325.dir/b.go

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
// Copyright 2021 The Go Authors. All rights reserved. Use of this
2+
// source code is governed by a BSD-style license that can be found in
3+
// the LICENSE file.
4+
5+
package b
6+
7+
import (
8+
"./a"
9+
)
10+
11+
func F() {
12+
a.FM()
13+
}

test/fixedbugs/issue44325.go

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
// compiledir
2+
3+
// Copyright 2021 The Go Authors. All rights reserved. Use of this
4+
// source code is governed by a BSD-style license that can be found in
5+
// the LICENSE file.
6+
7+
package ignored

0 commit comments

Comments
 (0)