golang.org/x/tools@v0.21.1-0.20240520172518-788d39e776b1/go/ssa/interp/testdata/forvarlifetime_go122.go (about) 1 // Copyright 2023 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 //go:build go1.22 6 7 package main 8 9 import ( 10 "reflect" 11 ) 12 13 func main() { 14 test_init() 15 bound() 16 manyvars() 17 nocond() 18 nopost() 19 address_sequences() 20 post_escapes() 21 22 // Clones from cmd/compile/internal/loopvar/testdata . 23 for_complicated_esc_address() 24 for_esc_address() 25 for_esc_closure() 26 for_esc_method() 27 } 28 29 // After go1.22, each i will have a distinct address and value. 30 var distinct = func(m, n int) []*int { 31 var r []*int 32 for i := m; i <= n; i++ { 33 r = append(r, &i) 34 } 35 return r 36 }(3, 5) 37 38 func test_init() { 39 if len(distinct) != 3 { 40 panic(distinct) 41 } 42 for i, v := range []int{3, 4, 5} { 43 if v != *(distinct[i]) { 44 panic(distinct) 45 } 46 } 47 } 48 49 func bound() { 50 b := func(k int) func() int { 51 var f func() int 52 for i := 0; i < k; i++ { 53 f = func() int { return i } // address before post updates i. So last value in the body. 54 } 55 return f 56 } 57 58 if got := b(0); got != nil { 59 panic(got) 60 } 61 if got := b(5); got() != 4 { 62 panic(got()) 63 } 64 } 65 66 func manyvars() { 67 // Tests declaring many variables and having one in the middle escape. 68 var f func() int 69 for i, j, k, l, m, n, o, p := 7, 6, 5, 4, 3, 2, 1, 0; p < 6; l, p = l+1, p+1 { 70 _, _, _, _, _, _, _, _ = i, j, k, l, m, n, o, p 71 f = func() int { return l } // address *before* post updates l 72 } 73 if f() != 9 { // l == p+4 74 panic(f()) 75 } 76 } 77 78 func nocond() { 79 var c, b, e *int 80 for p := 0; ; p++ { 81 if p%7 == 0 { 82 c = &p 83 continue 84 } else if p == 20 { 85 b = &p 86 break 87 } 88 e = &p 89 } 90 91 if *c != 14 { 92 panic(c) 93 } 94 if *b != 20 { 95 panic(b) 96 } 97 if *e != 19 { 98 panic(e) 99 } 100 } 101 102 func nopost() { 103 var first, last *int 104 for p := 0; p < 20; { 105 if first == nil { 106 first = &p 107 } 108 last = &p 109 110 p++ 111 } 112 113 if *first != 1 { 114 panic(first) 115 } 116 if *last != 20 { 117 panic(last) 118 } 119 } 120 121 func address_sequences() { 122 var c, b, p []*int 123 124 cond := func(x *int) bool { 125 c = append(c, x) 126 return *x < 5 127 } 128 body := func(x *int) { 129 b = append(b, x) 130 } 131 post := func(x *int) { 132 p = append(p, x) 133 (*x)++ 134 } 135 for i := 0; cond(&i); post(&i) { 136 body(&i) 137 } 138 139 if c[0] == c[1] { 140 panic(c) 141 } 142 143 if !reflect.DeepEqual(c[:5], b) { 144 panic(c) 145 } 146 147 if !reflect.DeepEqual(c[1:], p) { 148 panic(c) 149 } 150 151 if !reflect.DeepEqual(b[1:], p[:4]) { 152 panic(b) 153 } 154 } 155 156 func post_escapes() { 157 var p []*int 158 post := func(x *int) { 159 p = append(p, x) 160 (*x)++ 161 } 162 163 for i := 0; i < 5; post(&i) { 164 } 165 166 var got []int 167 for _, x := range p { 168 got = append(got, *x) 169 } 170 if want := []int{1, 2, 3, 4, 5}; !reflect.DeepEqual(got, want) { 171 panic(got) 172 } 173 } 174 175 func for_complicated_esc_address() { 176 // Clone of for_complicated_esc_adress.go 177 ss, sa := shared(23) 178 ps, pa := private(23) 179 es, ea := experiment(23) 180 181 if ss != ps || ss != es || ea != pa || sa == pa { 182 println("shared s, a", ss, sa, "; private, s, a", ps, pa, "; experiment s, a", es, ea) 183 panic("for_complicated_esc_address") 184 } 185 } 186 187 func experiment(x int) (int, int) { 188 sum := 0 189 var is []*int 190 for i := x; i != 1; i = i / 2 { 191 for j := 0; j < 10; j++ { 192 if i == j { // 10 skips 193 continue 194 } 195 sum++ 196 } 197 i = i*3 + 1 198 if i&1 == 0 { 199 is = append(is, &i) 200 for i&2 == 0 { 201 i = i >> 1 202 } 203 } else { 204 i = i + i 205 } 206 } 207 208 asum := 0 209 for _, pi := range is { 210 asum += *pi 211 } 212 213 return sum, asum 214 } 215 216 func private(x int) (int, int) { 217 sum := 0 218 var is []*int 219 I := x 220 for ; I != 1; I = I / 2 { 221 i := I 222 for j := 0; j < 10; j++ { 223 if i == j { // 10 skips 224 I = i 225 continue 226 } 227 sum++ 228 } 229 i = i*3 + 1 230 if i&1 == 0 { 231 is = append(is, &i) 232 for i&2 == 0 { 233 i = i >> 1 234 } 235 } else { 236 i = i + i 237 } 238 I = i 239 } 240 241 asum := 0 242 for _, pi := range is { 243 asum += *pi 244 } 245 246 return sum, asum 247 } 248 249 func shared(x int) (int, int) { 250 sum := 0 251 var is []*int 252 i := x 253 for ; i != 1; i = i / 2 { 254 for j := 0; j < 10; j++ { 255 if i == j { // 10 skips 256 continue 257 } 258 sum++ 259 } 260 i = i*3 + 1 261 if i&1 == 0 { 262 is = append(is, &i) 263 for i&2 == 0 { 264 i = i >> 1 265 } 266 } else { 267 i = i + i 268 } 269 } 270 271 asum := 0 272 for _, pi := range is { 273 asum += *pi 274 } 275 return sum, asum 276 } 277 278 func for_esc_address() { 279 // Clone of for_esc_address.go 280 sum := 0 281 var is []*int 282 for i := 0; i < 10; i++ { 283 for j := 0; j < 10; j++ { 284 if i == j { // 10 skips 285 continue 286 } 287 sum++ 288 } 289 if i&1 == 0 { 290 is = append(is, &i) 291 } 292 } 293 294 bug := false 295 if sum != 100-10 { 296 println("wrong sum, expected", 90, ", saw", sum) 297 bug = true 298 } 299 if len(is) != 5 { 300 println("wrong iterations, expected ", 5, ", saw", len(is)) 301 bug = true 302 } 303 sum = 0 304 for _, pi := range is { 305 sum += *pi 306 } 307 if sum != 0+2+4+6+8 { 308 println("wrong sum, expected ", 20, ", saw ", sum) 309 bug = true 310 } 311 if bug { 312 panic("for_esc_address") 313 } 314 } 315 316 func for_esc_closure() { 317 var is []func() int 318 319 // Clone of for_esc_closure.go 320 sum := 0 321 for i := 0; i < 10; i++ { 322 for j := 0; j < 10; j++ { 323 if i == j { // 10 skips 324 continue 325 } 326 sum++ 327 } 328 if i&1 == 0 { 329 is = append(is, func() int { 330 if i%17 == 15 { 331 i++ 332 } 333 return i 334 }) 335 } 336 } 337 338 bug := false 339 if sum != 100-10 { 340 println("wrong sum, expected ", 90, ", saw", sum) 341 bug = true 342 } 343 if len(is) != 5 { 344 println("wrong iterations, expected ", 5, ", saw", len(is)) 345 bug = true 346 } 347 sum = 0 348 for _, f := range is { 349 sum += f() 350 } 351 if sum != 0+2+4+6+8 { 352 println("wrong sum, expected ", 20, ", saw ", sum) 353 bug = true 354 } 355 if bug { 356 panic("for_esc_closure") 357 } 358 } 359 360 type I int 361 362 func (x *I) method() int { 363 return int(*x) 364 } 365 366 func for_esc_method() { 367 // Clone of for_esc_method.go 368 var is []func() int 369 sum := 0 370 for i := I(0); int(i) < 10; i++ { 371 for j := 0; j < 10; j++ { 372 if int(i) == j { // 10 skips 373 continue 374 } 375 sum++ 376 } 377 if i&1 == 0 { 378 is = append(is, i.method) 379 } 380 } 381 382 bug := false 383 if sum != 100-10 { 384 println("wrong sum, expected ", 90, ", saw ", sum) 385 bug = true 386 } 387 if len(is) != 5 { 388 println("wrong iterations, expected ", 5, ", saw", len(is)) 389 bug = true 390 } 391 sum = 0 392 for _, m := range is { 393 sum += m() 394 } 395 if sum != 0+2+4+6+8 { 396 println("wrong sum, expected ", 20, ", saw ", sum) 397 bug = true 398 } 399 if bug { 400 panic("for_esc_method") 401 } 402 }