1// Copyright 2017 The Go Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style
3// license that can be found in the LICENSE file.
4
5// Check correctness of various closure corner cases
6// that are expected to be inlined
7
8package main
9
10var ok bool
11var sink int
12
13func main() {
14	{
15		if x := func() int { // ERROR "can inline main.func1"
16			return 1
17		}(); x != 1 { // ERROR "inlining call to main.func1"
18			ppanic("x != 1")
19		}
20		if x := func() int { // ERROR "can inline main.func2" "func literal does not escape"
21			return 1
22		}; x() != 1 { // ERROR "inlining call to main.func2"
23			ppanic("x() != 1")
24		}
25	}
26
27	{
28		if y := func(x int) int { // ERROR "can inline main.func3"
29			return x + 2
30		}(40); y != 42 { // ERROR "inlining call to main.func3"
31			ppanic("y != 42")
32		}
33		if y := func(x int) int { // ERROR "can inline main.func4" "func literal does not escape"
34			return x + 2
35		}; y(40) != 42 { // ERROR "inlining call to main.func4"
36			ppanic("y(40) != 42")
37		}
38	}
39
40	{
41		y := func(x int) int { // ERROR "can inline main.func5" "func literal does not escape"
42			return x + 2
43		}
44		y = func(x int) int { // ERROR "can inline main.func6" "func literal does not escape"
45			return x + 1
46		}
47		if y(40) != 41 {
48			ppanic("y(40) != 41")
49		}
50	}
51
52	{
53		func() { // ERROR "func literal does not escape"
54			y := func(x int) int { // ERROR "can inline main.func7.1" "func literal does not escape"
55				return x + 2
56			}
57			y = func(x int) int { // ERROR "can inline main.func7.2" "func literal does not escape"
58				return x + 1
59			}
60			if y(40) != 41 {
61				ppanic("y(40) != 41")
62			}
63		}()
64	}
65
66	{
67		y := func(x int) int { // ERROR "can inline main.func8" "func literal does not escape"
68			return x + 2
69		}
70		y, sink = func(x int) int { // ERROR "can inline main.func9" "func literal does not escape"
71			return x + 1
72		}, 42
73		if y(40) != 41 {
74			ppanic("y(40) != 41")
75		}
76	}
77
78	{
79		func() { // ERROR "func literal does not escape"
80			y := func(x int) int { // ERROR "can inline main.func10.1" "func literal does not escape"
81				return x + 2
82			}
83			y, sink = func(x int) int { // ERROR "can inline main.func10.2" "func literal does not escape"
84				return x + 1
85			}, 42
86			if y(40) != 41 {
87				ppanic("y(40) != 41")
88			}
89		}()
90	}
91
92	{
93		y := func(x int) int { // ERROR "can inline main.func11" "func literal does not escape"
94			return x + 2
95		}
96		y, sink = func() (func(int) int, int) { // ERROR "can inline main.func12"
97			return func(x int) int { // ERROR "can inline main.func12"
98				return x + 1
99			}, 42
100		}() // ERROR "func literal does not escape" "inlining call to main.func12"
101		if y(40) != 41 {
102			ppanic("y(40) != 41")
103		}
104	}
105
106	{
107		func() { // ERROR "func literal does not escape"
108			y := func(x int) int { // ERROR "func literal does not escape" "can inline main.func13.1"
109				return x + 2
110			}
111			y, sink = func() (func(int) int, int) { // ERROR "can inline main.func13.2"
112				return func(x int) int { // ERROR   "can inline main.func13.2"
113					return x + 1
114				}, 42
115			}() // ERROR "func literal does not escape" "inlining call to main.func13.2"
116			if y(40) != 41 {
117				ppanic("y(40) != 41")
118			}
119		}()
120	}
121
122	{
123		y := func(x int) int { // ERROR "can inline main.func14" "func literal does not escape"
124			return x + 2
125		}
126		y, ok = map[int]func(int) int{ // ERROR "does not escape"
127			0: func(x int) int { return x + 1 }, // ERROR "can inline main.func15" "func literal escapes"
128		}[0]
129		if y(40) != 41 {
130			ppanic("y(40) != 41")
131		}
132	}
133
134	{
135		func() { // ERROR "func literal does not escape"
136			y := func(x int) int { // ERROR "can inline main.func16.1" "func literal does not escape"
137				return x + 2
138			}
139			y, ok = map[int]func(int) int{ // ERROR "does not escape"
140				0: func(x int) int { return x + 1 }, // ERROR "can inline main.func16.2" "func literal escapes"
141			}[0]
142			if y(40) != 41 {
143				ppanic("y(40) != 41")
144			}
145		}()
146	}
147
148	{
149		y := func(x int) int { // ERROR "can inline main.func17" "func literal does not escape"
150			return x + 2
151		}
152		y, ok = interface{}(func(x int) int { // ERROR "can inline main.func18" "does not escape"
153			return x + 1
154		}).(func(int) int)
155		if y(40) != 41 {
156			ppanic("y(40) != 41")
157		}
158	}
159
160	{
161		func() { // ERROR "func literal does not escape"
162			y := func(x int) int { // ERROR "can inline main.func19.1" "func literal does not escape"
163				return x + 2
164			}
165			y, ok = interface{}(func(x int) int { // ERROR "can inline main.func19.2" "does not escape"
166				return x + 1
167			}).(func(int) int)
168			if y(40) != 41 {
169				ppanic("y(40) != 41")
170			}
171		}()
172	}
173
174	{
175		x := 42
176		if y := func() int { // ERROR "can inline main.func20"
177			return x
178		}(); y != 42 { // ERROR "inlining call to main.func20"
179			ppanic("y != 42")
180		}
181		if y := func() int { // ERROR "can inline main.func21" "func literal does not escape"
182			return x
183		}; y() != 42 { // ERROR "inlining call to main.func21"
184			ppanic("y() != 42")
185		}
186	}
187
188	{
189		x := 42
190		if z := func(y int) int { // ERROR "can inline main.func22"
191			return func() int { // ERROR "can inline main.func22.1" "can inline main.main.func22.func30"
192				return x + y
193			}() // ERROR "inlining call to main.func22.1"
194		}(1); z != 43 { // ERROR "inlining call to main.func22" "inlining call to main.main.func22.func30"
195			ppanic("z != 43")
196		}
197		if z := func(y int) int { // ERROR "func literal does not escape" "can inline main.func23"
198			return func() int { // ERROR "can inline main.func23.1" "can inline main.main.func23.func31"
199				return x + y
200			}() // ERROR "inlining call to main.func23.1"
201		}; z(1) != 43 { // ERROR "inlining call to main.func23" "inlining call to main.main.func23.func31"
202			ppanic("z(1) != 43")
203		}
204	}
205
206	{
207		a := 1
208		func() { // ERROR "can inline main.func24"
209			func() { // ERROR "can inline main.func24" "can inline main.main.func24.func32"
210				a = 2
211			}() // ERROR "inlining call to main.func24"
212		}() // ERROR "inlining call to main.func24" "inlining call to main.main.func24.func32"
213		if a != 2 {
214			ppanic("a != 2")
215		}
216	}
217
218	{
219		b := 2
220		func(b int) { // ERROR "func literal does not escape"
221			func() { // ERROR "can inline main.func25.1"
222				b = 3
223			}() // ERROR "inlining call to main.func25.1"
224			if b != 3 {
225				ppanic("b != 3")
226			}
227		}(b)
228		if b != 2 {
229			ppanic("b != 2")
230		}
231	}
232
233	{
234		c := 3
235		func() { // ERROR "can inline main.func26"
236			c = 4
237			func() {
238				if c != 4 {
239					ppanic("c != 4")
240				}
241				recover() // prevent inlining
242			}()
243		}() // ERROR "inlining call to main.func26" "func literal does not escape"
244		if c != 4 {
245			ppanic("c != 4")
246		}
247	}
248
249	{
250		a := 2
251		// This has an unfortunate exponential growth, where as we visit each
252		// function, we inline the inner closure, and that constructs a new
253		// function for any closures inside the inner function, and then we
254		// revisit those. E.g., func34 and func36 are constructed by the inliner.
255		if r := func(x int) int { // ERROR "can inline main.func27"
256			b := 3
257			return func(y int) int { // ERROR "can inline main.func27.1" "can inline main.main.func27.func34"
258				c := 5
259				return func(z int) int { // ERROR "can inline main.func27.1.1" "can inline main.main.func27.func34.1" "can inline main.func27.main.func27.1.2" "can inline main.main.func27.main.main.func27.func34.func36"
260					return a*x + b*y + c*z
261				}(10) // ERROR "inlining call to main.func27.1.1"
262			}(100) // ERROR "inlining call to main.func27.1" "inlining call to main.func27.main.func27.1.2"
263		}(1000); r != 2350 { // ERROR "inlining call to main.func27" "inlining call to main.main.func27.func34" "inlining call to main.main.func27.main.main.func27.func34.func36"
264			ppanic("r != 2350")
265		}
266	}
267
268	{
269		a := 2
270		if r := func(x int) int { // ERROR "can inline main.func28"
271			b := 3
272			return func(y int) int { // ERROR "can inline main.func28.1" "can inline main.main.func28.func35"
273				c := 5
274				func(z int) { // ERROR "can inline main.func28.1.1" "can inline main.func28.main.func28.1.2" "can inline main.main.func28.func35.1" "can inline main.main.func28.main.main.func28.func35.func37"
275					a = a * x
276					b = b * y
277					c = c * z
278				}(10) // ERROR "inlining call to main.func28.1.1"
279				return a + c
280			}(100) + b // ERROR "inlining call to main.func28.1" "inlining call to main.func28.main.func28.1.2"
281		}(1000); r != 2350 { // ERROR "inlining call to main.func28" "inlining call to main.main.func28.func35" "inlining call to main.main.func28.main.main.func28.func35.func37"
282			ppanic("r != 2350")
283		}
284		if a != 2000 {
285			ppanic("a != 2000")
286		}
287	}
288}
289
290//go:noinline
291func ppanic(s string) { // ERROR "leaking param: s"
292	panic(s) // ERROR "s escapes to heap"
293}
294