...
1# Test closure naming with inlining.
2
3go build -gcflags=-S -o x.exe x.go
4# original closure name should appear
5stderr '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
16stderr 'ranger\.func1'
17stderr 'ranger-range1'
18stderr 'ranger\.func2'
19
20go tool nm x.exe
21# same applies to the nm output
22stdout 'adder\.func1'
23! stdout 'F1\.adder\.func1'
24! stdout 'F2\.adder\.func1'
25! stdout 'adder\.func2'
26! stdout 'adder\.func3'
27! stdout 'adder\.func4'
28stdout 'ranger\.func1'
29stdout 'ranger-range1'
30stdout 'ranger\.func2'
31# the inline hash should not make into the final binary
32! stdout 'adder\.func1#'
33
34-- x.go --
35package main
36
37// keep prevents closures being optimized out
38//
39//go:noinline
40func keep(x func()) func() { return x }
41
42func adder(n int) func(int) int {
43 return func(x int) int { return x + n }
44}
45
46//go:noinline
47func 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
54func 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
64func iter(yield func(int) bool) {
65 _ = yield(1) && yield(2) && yield(3)
66}
67
68func 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
77func main() {
78 x := 1
79 F1()(F2()(ranger()(x)))
80}
View as plain text