1 # Test closure naming with inlining.
2
3 go build -gcflags=-S -o x.exe x.go
4 # original closure name should appear
5 stderr 'adder\.func1'
6 # inlining should not cause the closure to have longer names
7 ! stderr 'F1\.adder\.func1'
8 ! stderr 'F2\.adder\.func1'
9 # the counter should match the original one, regardless of
10 # how many closures are in the inlined caller
11 ! stderr 'adder\.func2'
12 ! stderr 'adder\.func3'
13 ! stderr 'adder\.func4'
14 # user closure counter and range func counter should not
15 # interfere
16 stderr 'ranger\.func1'
17 stderr 'ranger-range1'
18 stderr 'ranger\.func2'
19
20 go tool nm x.exe
21 # same applies to the nm output
22 stdout 'adder\.func1'
23 ! stdout 'F1\.adder\.func1'
24 ! stdout 'F2\.adder\.func1'
25 ! stdout 'adder\.func2'
26 ! stdout 'adder\.func3'
27 ! stdout 'adder\.func4'
28 stdout 'ranger\.func1'
29 stdout 'ranger-range1'
30 stdout 'ranger\.func2'
31 # the inline hash should not make into the final binary
32 ! stdout 'adder\.func1#'
33
34 -- x.go --
35 package main
36
37 // keep prevents closures being optimized out
38 //
39 //go:noinline
40 func keep(x func()) func() { return x }
41
42 func adder(n int) func(int) int {
43 return func(x int) int { return x + n }
44 }
45
46 //go:noinline
47 func F1() func(int) int {
48 // adder is inlined into F1, along with its closure.
49 // The closure should still be named addr.func1.
50 return adder(1)
51 }
52
53 //go:noinline
54 func F2() func(int) int {
55 keep(func() {})
56 keep(func() {})
57 keep(func() {})
58 // Closures in the outer function should not change
59 // the counter. It should still be addr.func1.
60 return adder(2)
61 }
62
63 //go:noinline
64 func iter(yield func(int) bool) {
65 _ = yield(1) && yield(2) && yield(3)
66 }
67
68 func ranger() func(int) int {
69 keep(func() {}) // func1
70 s := 0
71 for x := range iter { // range1
72 s += x
73 }
74 return func(x int) int { return s + x } // func2
75 }
76
77 func main() {
78 x := 1
79 F1()(F2()(ranger()(x)))
80 }
81
View as plain text