1// errorcheck -0 -m -l
2
3// Copyright 2015 The Go Authors. All rights reserved.
4// Use of this source code is governed by a BSD-style
5// license that can be found in the LICENSE file.
6
7// Test escape analysis for interface conversions.
8
9package escape
10
11var sink interface{}
12
13type M interface {
14	M()
15}
16
17func mescapes(m M) { // ERROR "leaking param: m"
18	sink = m
19}
20
21func mdoesnotescape(m M) { // ERROR "m does not escape"
22}
23
24// Tests for type stored directly in iface and with value receiver method.
25type M0 struct {
26	p *int
27}
28
29func (M0) M() {
30}
31
32func efaceEscape0() {
33	{
34		i := 0
35		v := M0{&i}
36		var x M = v
37		_ = x
38	}
39	{
40		i := 0 // ERROR "moved to heap: i"
41		v := M0{&i}
42		var x M = v
43		sink = x
44	}
45	{
46		i := 0
47		v := M0{&i}
48		var x M = v
49		v1 := x.(M0)
50		_ = v1
51	}
52	{
53		i := 0 // ERROR "moved to heap: i"
54		v := M0{&i}
55		// BAD: v does not escape to heap here
56		var x M = v
57		v1 := x.(M0)
58		sink = v1
59	}
60	{
61		i := 0
62		v := M0{&i}
63		var x M = v
64		x.M() // ERROR "devirtualizing x.M"
65	}
66	{
67		i := 0 // ERROR "moved to heap: i"
68		v := M0{&i}
69		var x M = v
70		mescapes(x)
71	}
72	{
73		i := 0
74		v := M0{&i}
75		var x M = v
76		mdoesnotescape(x)
77	}
78}
79
80// Tests for type stored indirectly in iface and with value receiver method.
81type M1 struct {
82	p *int
83	x int
84}
85
86func (M1) M() {
87}
88
89func efaceEscape1() {
90	{
91		i := 0
92		v := M1{&i, 0}
93		var x M = v // ERROR "v does not escape"
94		_ = x
95	}
96	{
97		i := 0 // ERROR "moved to heap: i"
98		v := M1{&i, 0}
99		var x M = v // ERROR "v escapes to heap"
100		sink = x
101	}
102	{
103		i := 0
104		v := M1{&i, 0}
105		var x M = v // ERROR "v does not escape"
106		v1 := x.(M1)
107		_ = v1
108	}
109	{
110		i := 0 // ERROR "moved to heap: i"
111		v := M1{&i, 0}
112		var x M = v // ERROR "v does not escape"
113		v1 := x.(M1)
114		sink = v1 // ERROR "v1 escapes to heap"
115	}
116	{
117		i := 0
118		v := M1{&i, 0}
119		var x M = v // ERROR "v does not escape"
120		x.M()       // ERROR "devirtualizing x.M"
121	}
122	{
123		i := 0 // ERROR "moved to heap: i"
124		v := M1{&i, 0}
125		var x M = v // ERROR "v escapes to heap"
126		mescapes(x)
127	}
128	{
129		i := 0
130		v := M1{&i, 0}
131		var x M = v // ERROR "v does not escape"
132		mdoesnotescape(x)
133	}
134}
135
136// Tests for type stored directly in iface and with pointer receiver method.
137type M2 struct {
138	p *int
139}
140
141func (*M2) M() {
142}
143
144func efaceEscape2() {
145	{
146		i := 0
147		v := &M2{&i} // ERROR "&M2{...} does not escape"
148		var x M = v
149		_ = x
150	}
151	{
152		i := 0       // ERROR "moved to heap: i"
153		v := &M2{&i} // ERROR "&M2{...} escapes to heap"
154		var x M = v
155		sink = x
156	}
157	{
158		i := 0
159		v := &M2{&i} // ERROR "&M2{...} does not escape"
160		var x M = v
161		v1 := x.(*M2)
162		_ = v1
163	}
164	{
165		i := 0       // ERROR "moved to heap: i"
166		v := &M2{&i} // ERROR "&M2{...} escapes to heap"
167		// BAD: v does not escape to heap here
168		var x M = v
169		v1 := x.(*M2)
170		sink = v1
171	}
172	{
173		i := 0       // ERROR "moved to heap: i"
174		v := &M2{&i} // ERROR "&M2{...} does not escape"
175		// BAD: v does not escape to heap here
176		var x M = v
177		v1 := x.(*M2)
178		sink = *v1
179	}
180	{
181		i := 0       // ERROR "moved to heap: i"
182		v := &M2{&i} // ERROR "&M2{...} does not escape"
183		// BAD: v does not escape to heap here
184		var x M = v
185		v1, ok := x.(*M2)
186		sink = *v1
187		_ = ok
188	}
189	{
190		i := 0
191		v := &M2{&i} // ERROR "&M2{...} does not escape"
192		var x M = v
193		x.M() // ERROR "devirtualizing x.M"
194	}
195	{
196		i := 0       // ERROR "moved to heap: i"
197		v := &M2{&i} // ERROR "&M2{...} escapes to heap"
198		var x M = v
199		mescapes(x)
200	}
201	{
202		i := 0
203		v := &M2{&i} // ERROR "&M2{...} does not escape"
204		var x M = v
205		mdoesnotescape(x)
206	}
207}
208
209type T1 struct {
210	p *int
211}
212
213type T2 struct {
214	T1 T1
215}
216
217func dotTypeEscape() *T2 { // #11931
218	var x interface{}
219	x = &T1{p: new(int)} // ERROR "new\(int\) escapes to heap" "&T1{...} does not escape"
220	return &T2{          // ERROR "&T2{...} escapes to heap"
221		T1: *(x.(*T1)),
222	}
223}
224
225func dotTypeEscape2() { // #13805, #15796
226	{
227		i := 0
228		j := 0
229		var v int
230		var ok bool
231		var x interface{} = i // ERROR "i does not escape"
232		var y interface{} = j // ERROR "j does not escape"
233
234		*(&v) = x.(int)
235		*(&v), *(&ok) = y.(int)
236	}
237	{ // #13805, #15796
238		i := 0
239		j := 0
240		var ok bool
241		var x interface{} = i // ERROR "i does not escape"
242		var y interface{} = j // ERROR "j does not escape"
243
244		sink = x.(int)         // ERROR "x.\(int\) escapes to heap"
245		sink, *(&ok) = y.(int) // ERROR "autotmp_.* escapes to heap"
246	}
247	{
248		i := 0 // ERROR "moved to heap: i"
249		j := 0 // ERROR "moved to heap: j"
250		var ok bool
251		var x interface{} = &i
252		var y interface{} = &j
253
254		sink = x.(*int)
255		sink, *(&ok) = y.(*int)
256	}
257}
258
259func issue42279() {
260	type I interface{ M() }
261	type T struct{ I }
262
263	var i I = T{} // ERROR "T\{\} does not escape"
264	i.M()         // ERROR "partially devirtualizing i.M to T"
265}
266