Source file
test/fixedbugs/issue71685.go
1
2
3
4
5
6
7
8
9
10
11
12
13 package main
14
15 import "fmt"
16
17 func iter(yield func(int) bool) { yield(0) }
18
19 var fails int
20
21 func check(name string, got, want any) {
22 if got != want {
23 fmt.Printf("%s = %v, want %v\n", name, got, want)
24 fails++
25 }
26 }
27
28
29
30 func recovered(f func(*any)) (got any) {
31 defer func() {
32 if recover() != nil {
33 got = nil
34 }
35 }()
36 var r any
37 func() {
38 defer f(&r)
39 panic("boom")
40 }()
41 return r
42 }
43
44
45 func body(r *any) {
46 for range iter {
47 *r = recover()
48 }
49 }
50
51
52 func nested(r *any) {
53 for range iter {
54 for range iter {
55 *r = recover()
56 }
57 }
58 }
59
60
61
62 func inClosure(r *any) {
63 for range iter {
64 func() { *r = recover() }()
65 }
66 }
67
68
69
70 func inCallee(r *any) {
71 helper(r)
72 }
73
74 func helper(r *any) {
75 for range iter {
76 *r = recover()
77 }
78 }
79
80
81 func overInt(r *any) {
82 for range 1 {
83 *r = recover()
84 }
85 }
86
87 func overSlice(r *any) {
88 for range []int{0} {
89 *r = recover()
90 }
91 }
92
93 func overChan(r *any) {
94 ch := make(chan int, 1)
95 ch <- 0
96 close(ch)
97 for range ch {
98 *r = recover()
99 }
100 }
101
102
103
104 func withDefer(r *any) {
105 for range iter {
106 defer func() { *r = "deferred ran" }()
107 if recover() == nil {
108 *r = "did not recover"
109 return
110 }
111 }
112 }
113
114
115 func twice(r *any) {
116 for range iter {
117 first := recover()
118 second := recover()
119 *r = fmt.Sprint(first, " ", second)
120 }
121 }
122
123
124
125 func inner(r *any) {
126 for range iter {
127 func() {
128 defer func() { recover() }()
129 panic("inner")
130 }()
131 *r = recover()
132 }
133 }
134
135 func main() {
136 check("body", recovered(body), "boom")
137 check("nested", recovered(nested), "boom")
138 check("inClosure", recovered(inClosure), nil)
139 check("inCallee", recovered(inCallee), nil)
140 check("overInt", recovered(overInt), "boom")
141 check("overSlice", recovered(overSlice), "boom")
142 check("overChan", recovered(overChan), "boom")
143 check("withDefer", recovered(withDefer), "deferred ran")
144 check("twice", recovered(twice), "boom <nil>")
145 check("inner", recovered(inner), "boom")
146
147
148
149 n := 0
150 var got any = "not nil"
151 for range iter {
152 got = recover()
153 n++
154 }
155 check("no panic: recover()", got, nil)
156 check("no panic: iterations", n, 1)
157
158 if fails > 0 {
159 panic("failed")
160 }
161 }
162
View as plain text