From b98ce3b606b2bb620c9c62482cd73f068157a32c Mon Sep 17 00:00:00 2001 From: Dan Scales Date: Mon, 1 Mar 2021 09:05:58 -0800 Subject: [PATCH] cmd/compile: import empty closure function correctly On import, make sure that an empty closure is represented as a single empty block statement. Otherwise, the closure is dropped. Block statements are not exported explicitly, so must recreate on import. Fixes #44330 Change-Id: I061598f0f859dd71d2d0cbd10c77cdd81525d1f2 Reviewed-on: https://go-review.googlesource.com/c/go/+/297569 Run-TryBot: Dan Scales TryBot-Result: Go Bot Reviewed-by: Matthew Dempsky Trust: Dan Scales --- src/cmd/compile/internal/typecheck/iimport.go | 5 ++++ test/fixedbugs/issue44330.dir/a.go | 21 +++++++++++++++++ test/fixedbugs/issue44330.dir/b.go | 23 +++++++++++++++++++ test/fixedbugs/issue44330.go | 7 ++++++ 4 files changed, 56 insertions(+) create mode 100644 test/fixedbugs/issue44330.dir/a.go create mode 100644 test/fixedbugs/issue44330.dir/b.go create mode 100644 test/fixedbugs/issue44330.go diff --git a/src/cmd/compile/internal/typecheck/iimport.go b/src/cmd/compile/internal/typecheck/iimport.go index 17aa35549d..9355174da8 100644 --- a/src/cmd/compile/internal/typecheck/iimport.go +++ b/src/cmd/compile/internal/typecheck/iimport.go @@ -992,6 +992,11 @@ func (r *importReader) node() ir.Node { r.funcBody(fn) fn.Dcl = fn.Inl.Dcl fn.Body = fn.Inl.Body + if len(fn.Body) == 0 { + // An empty closure must be represented as a single empty + // block statement, else it will be dropped. + fn.Body = []ir.Node{ir.NewBlockStmt(src.NoXPos, nil)} + } fn.Inl = nil ir.FinishCaptureNames(pos, r.curfn, fn) diff --git a/test/fixedbugs/issue44330.dir/a.go b/test/fixedbugs/issue44330.dir/a.go new file mode 100644 index 0000000000..9d3ab9fe80 --- /dev/null +++ b/test/fixedbugs/issue44330.dir/a.go @@ -0,0 +1,21 @@ +// 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 a + +type Table struct { + ColumnSeparator bool + RowSeparator bool + + // ColumnResizer is called on each Draw. Can be used for custom column sizing. + ColumnResizer func() +} + +func NewTable() *Table { + return &Table{ + ColumnSeparator: true, + RowSeparator: true, + ColumnResizer: func() {}, + } +} diff --git a/test/fixedbugs/issue44330.dir/b.go b/test/fixedbugs/issue44330.dir/b.go new file mode 100644 index 0000000000..1d5742421b --- /dev/null +++ b/test/fixedbugs/issue44330.dir/b.go @@ -0,0 +1,23 @@ +// 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 main + +import ( + "./a" +) + +type Term struct { + top *a.Table +} + +//go:noinline +func NewFred() *Term { + table := a.NewTable() + return &Term{top: table} +} + +func main() { + NewFred() +} diff --git a/test/fixedbugs/issue44330.go b/test/fixedbugs/issue44330.go new file mode 100644 index 0000000000..682d9c5bf3 --- /dev/null +++ b/test/fixedbugs/issue44330.go @@ -0,0 +1,7 @@ +// rundir + +// 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 ignored