aboutsummaryrefslogtreecommitdiff
path: root/test/closure3.dir
diff options
context:
space:
mode:
authorHugues Bruant <hugues.bruant@gmail.com>2017-11-02 19:54:46 -0700
committerKeith Randall <khr@golang.org>2017-11-03 20:09:26 +0000
commit483e298daad38f39515ba20c0fcedc20b5475ae8 (patch)
treee825b91aa124c364def4e6be57224f3b8a29b590 /test/closure3.dir
parentd593f85ebdcdb36938e5c3e56fedc7852d713d18 (diff)
downloadgo-483e298daad38f39515ba20c0fcedc20b5475ae8.tar.gz
go-483e298daad38f39515ba20c0fcedc20b5475ae8.zip
cmd/compile: fix reassignment check
CL 65071 enabled inlining for local closures with no captures. To determine safety of inlining a call sites, we check whether the variable holding the closure has any assignments after its original definition. Unfortunately, that check did not catch OAS2MAPR and OAS2DOTTYPE, leading to incorrect inlining when a variable holding a closure was subsequently reassigned through a type conversion or a 2-valued map access. There was another more subtle issue wherein reassignment check would always return a false positive for closure calls inside other closures. This was caused by the Name.Curfn field of local variables pointing to the OCLOSURE node instead of the corresponding ODCLFUNC, which resulted in reassigned walking an empty Nbody and thus never seeing any reassignments. This CL fixes these oversights and adds many more tests for closure inlining which ensure not only that inlining triggers but also the correctness of the resulting code. Updates #15561 Change-Id: I74bdae849c4ecfa328546d6d62b512e8d54d04ce Reviewed-on: https://go-review.googlesource.com/75770 Reviewed-by: Hugues Bruant <hugues.bruant@gmail.com> Reviewed-by: Matthew Dempsky <mdempsky@google.com> Run-TryBot: Brad Fitzpatrick <bradfitz@golang.org> TryBot-Result: Gobot Gobot <gobot@golang.org>
Diffstat (limited to 'test/closure3.dir')
-rw-r--r--test/closure3.dir/main.go173
1 files changed, 173 insertions, 0 deletions
diff --git a/test/closure3.dir/main.go b/test/closure3.dir/main.go
new file mode 100644
index 0000000000..5629a522d7
--- /dev/null
+++ b/test/closure3.dir/main.go
@@ -0,0 +1,173 @@
+// Copyright 2017 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.
+
+// Check correctness of various closure corner cases that
+// that are expected to be inlined
+
+package main
+
+var ok bool
+var sink int
+
+func main() {
+ {
+ if x := func() int { // ERROR "can inline main.func1"
+ return 1
+ }(); x != 1 { // ERROR "inlining call to main.func1"
+ panic("x != 1")
+ }
+ if x := func() int { // ERROR "can inline main.func2" "func literal does not escape"
+ return 1
+ }; x() != 1 { // ERROR "inlining call to main.func2"
+ panic("x() != 1")
+ }
+ }
+
+ {
+ if y := func(x int) int { // ERROR "can inline main.func3"
+ return x + 2
+ }(40); y != 42 { // ERROR "inlining call to main.func3"
+ panic("y != 42")
+ }
+ if y := func(x int) int { // ERROR "can inline main.func4" "func literal does not escape"
+ return x + 2
+ }; y(40) != 42 { // ERROR "inlining call to main.func4"
+ panic("y(40) != 42")
+ }
+ }
+
+ {
+ y := func(x int) int { // ERROR "can inline main.func5" "func literal does not escape"
+ return x + 2
+ }
+ y = func(x int) int { // ERROR "can inline main.func6" "func literal does not escape"
+ return x + 1
+ }
+ if y(40) != 41 {
+ panic("y(40) != 41")
+ }
+ }
+
+ {
+ func() { // ERROR "func literal does not escape"
+ y := func(x int) int { // ERROR "can inline main.func7.1" "func literal does not escape"
+ return x + 2
+ }
+ y = func(x int) int { // ERROR "can inline main.func7.2" "func literal does not escape"
+ return x + 1
+ }
+ if y(40) != 41 {
+ panic("y(40) != 41")
+ }
+ }()
+ }
+
+ {
+ y := func(x int) int { // ERROR "can inline main.func8" "func literal does not escape"
+ return x + 2
+ }
+ y, sink = func(x int) int { // ERROR "can inline main.func9" "func literal does not escape"
+ return x + 1
+ }, 42
+ if y(40) != 41 {
+ panic("y(40) != 41")
+ }
+ }
+
+ {
+ func() { // ERROR "func literal does not escape"
+ y := func(x int) int { // ERROR "can inline main.func10.1" "func literal does not escape"
+ return x + 2
+ }
+ y, sink = func(x int) int { // ERROR "can inline main.func10.2" "func literal does not escape"
+ return x + 1
+ }, 42
+ if y(40) != 41 {
+ panic("y(40) != 41")
+ }
+ }()
+ }
+
+ {
+ y := func(x int) int { // ERROR "can inline main.func11" "func literal does not escape"
+ return x + 2
+ }
+ y, sink = func() (func(int)int, int) { // ERROR "func literal does not escape"
+ return func(x int) int { // ERROR "can inline main.func12" "func literal escapes"
+ return x + 1
+ }, 42
+ }()
+ if y(40) != 41 {
+ panic("y(40) != 41")
+ }
+ }
+
+ {
+ func() { // ERROR "func literal does not escape"
+ y := func(x int) int { // ERROR "can inline main.func13.1" "func literal does not escape"
+ return x + 2
+ }
+ y, sink = func() (func(int) int, int) { // ERROR "func literal does not escape"
+ return func(x int) int { // ERROR "can inline main.func13.2" "func literal escapes"
+ return x + 1
+ }, 42
+ }()
+ if y(40) != 41 {
+ panic("y(40) != 41")
+ }
+ }()
+ }
+
+ {
+ y := func(x int) int { // ERROR "can inline main.func14" "func literal does not escape"
+ return x + 2
+ }
+ y, ok = map[int]func(int)int { // ERROR "does not escape"
+ 0: func (x int) int { return x + 1 }, // ERROR "can inline main.func15" "func literal escapes"
+ }[0]
+ if y(40) != 41 {
+ panic("y(40) != 41")
+ }
+ }
+
+ {
+ func() { // ERROR "func literal does not escape"
+ y := func(x int) int { // ERROR "can inline main.func16.1" "func literal does not escape"
+ return x + 2
+ }
+ y, ok = map[int]func(int) int{// ERROR "does not escape"
+ 0: func(x int) int { return x + 1 }, // ERROR "can inline main.func16.2" "func literal escapes"
+ }[0]
+ if y(40) != 41 {
+ panic("y(40) != 41")
+ }
+ }()
+ }
+
+ {
+ y := func(x int) int { // ERROR "can inline main.func17" "func literal does not escape"
+ return x + 2
+ }
+ y, ok = interface{}(func (x int) int { // ERROR "can inline main.func18" "does not escape"
+ return x + 1
+ }).(func(int)int)
+ if y(40) != 41 {
+ panic("y(40) != 41")
+ }
+ }
+
+ {
+ func() { // ERROR "func literal does not escape"
+ y := func(x int) int { // ERROR "can inline main.func19.1" "func literal does not escape"
+ return x + 2
+ }
+ y, ok = interface{}(func(x int) int { // ERROR "can inline main.func19.2" "does not escape"
+ return x + 1
+ }).(func(int) int)
+ if y(40) != 41 {
+ panic("y(40) != 41")
+ }
+ }()
+ }
+}