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 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 291 func ppanic(s string) { // ERROR "leaking param: s" 292 panic(s) // ERROR "s escapes to heap" 293 } 294