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