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