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