github.com/cockroachdb/tools@v0.0.0-20230222021103-a6d27438930d/go/ssa/interp/testdata/fixedbugs/issue55086.go (about) 1 // Copyright 2022 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 package main 6 7 func a() (r string) { 8 s := "initial" 9 var p *struct{ i int } 10 defer func() { 11 recover() 12 r = s 13 }() 14 15 s, p.i = "set", 2 // s must be set before p.i panics 16 return "unreachable" 17 } 18 19 func b() (r string) { 20 s := "initial" 21 fn := func() []int { panic("") } 22 defer func() { 23 recover() 24 r = s 25 }() 26 27 s, fn()[0] = "set", 2 // fn() panics before any assignment occurs 28 return "unreachable" 29 } 30 31 func c() (r string) { 32 s := "initial" 33 var p map[int]int 34 defer func() { 35 recover() 36 r = s 37 }() 38 39 s, p[0] = "set", 2 //s must be set before p[0] index panics" 40 return "unreachable" 41 } 42 43 func d() (r string) { 44 s := "initial" 45 var p map[int]int 46 defer func() { 47 recover() 48 r = s 49 }() 50 fn := func() int { panic("") } 51 52 s, p[0] = "set", fn() // fn() panics before s is set 53 return "unreachable" 54 } 55 56 func e() (r string) { 57 s := "initial" 58 p := map[int]int{} 59 defer func() { 60 recover() 61 r = s 62 }() 63 fn := func() int { panic("") } 64 65 s, p[fn()] = "set", 0 // fn() panics before any assignment occurs 66 return "unreachable" 67 } 68 69 func f() (r string) { 70 s := "initial" 71 p := []int{} 72 defer func() { 73 recover() 74 r = s 75 }() 76 77 s, p[1] = "set", 0 // p[1] panics after s is set 78 return "unreachable" 79 } 80 81 func g() (r string) { 82 s := "initial" 83 p := map[any]any{} 84 defer func() { 85 recover() 86 r = s 87 }() 88 var i any = func() {} 89 s, p[i] = "set", 0 // p[i] panics after s is set 90 return "unreachable" 91 } 92 93 func h() (r string) { 94 fail := false 95 defer func() { 96 recover() 97 if fail { 98 r = "fail" 99 } else { 100 r = "success" 101 } 102 }() 103 104 type T struct{ f int } 105 var p *struct{ *T } 106 107 // The implicit "p.T" operand should be evaluated in phase 1 (and panic), 108 // before the "fail = true" assignment in phase 2. 109 fail, p.f = true, 0 110 return "unreachable" 111 } 112 113 func main() { 114 for _, test := range []struct { 115 fn func() string 116 want string 117 desc string 118 }{ 119 {a, "set", "s must be set before p.i panics"}, 120 {b, "initial", "p() panics before s is set"}, 121 {c, "set", "s must be set before p[0] index panics"}, 122 {d, "initial", "fn() panics before s is set"}, 123 {e, "initial", "fn() panics before s is set"}, 124 {f, "set", "p[1] panics after s is set"}, 125 {g, "set", "p[i] panics after s is set"}, 126 {h, "success", "p.T panics before fail is set"}, 127 } { 128 if test.fn() != test.want { 129 panic(test.desc) 130 } 131 } 132 }