File: issue55086.go

package info (click to toggle)
golang-golang-x-tools 1%3A0.25.0%2Bds-1
  • links: PTS, VCS
  • area: main
  • in suites: experimental, forky, sid, trixie
  • size: 22,724 kB
  • sloc: javascript: 2,027; asm: 1,645; sh: 166; yacc: 155; makefile: 49; ansic: 8
file content (132 lines) | stat: -rw-r--r-- 2,451 bytes parent folder | download | duplicates (3)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
// Copyright 2022 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

package main

func a() (r string) {
	s := "initial"
	var p *struct{ i int }
	defer func() {
		recover()
		r = s
	}()

	s, p.i = "set", 2 // s must be set before p.i panics
	return "unreachable"
}

func b() (r string) {
	s := "initial"
	fn := func() []int { panic("") }
	defer func() {
		recover()
		r = s
	}()

	s, fn()[0] = "set", 2 // fn() panics before any assignment occurs
	return "unreachable"
}

func c() (r string) {
	s := "initial"
	var p map[int]int
	defer func() {
		recover()
		r = s
	}()

	s, p[0] = "set", 2 //s must be set before p[0] index panics"
	return "unreachable"
}

func d() (r string) {
	s := "initial"
	var p map[int]int
	defer func() {
		recover()
		r = s
	}()
	fn := func() int { panic("") }

	s, p[0] = "set", fn() // fn() panics before s is set
	return "unreachable"
}

func e() (r string) {
	s := "initial"
	p := map[int]int{}
	defer func() {
		recover()
		r = s
	}()
	fn := func() int { panic("") }

	s, p[fn()] = "set", 0 // fn() panics before any assignment occurs
	return "unreachable"
}

func f() (r string) {
	s := "initial"
	p := []int{}
	defer func() {
		recover()
		r = s
	}()

	s, p[1] = "set", 0 // p[1] panics after s is set
	return "unreachable"
}

func g() (r string) {
	s := "initial"
	p := map[any]any{}
	defer func() {
		recover()
		r = s
	}()
	var i any = func() {}
	s, p[i] = "set", 0 // p[i] panics after s is set
	return "unreachable"
}

func h() (r string) {
	fail := false
	defer func() {
		recover()
		if fail {
			r = "fail"
		} else {
			r = "success"
		}
	}()

	type T struct{ f int }
	var p *struct{ *T }

	// The implicit "p.T" operand should be evaluated in phase 1 (and panic),
	// before the "fail = true" assignment in phase 2.
	fail, p.f = true, 0
	return "unreachable"
}

func main() {
	for _, test := range []struct {
		fn   func() string
		want string
		desc string
	}{
		{a, "set", "s must be set before p.i panics"},
		{b, "initial", "p() panics before s is set"},
		{c, "set", "s must be set before p[0] index panics"},
		{d, "initial", "fn() panics before s is set"},
		{e, "initial", "fn() panics before s is set"},
		{f, "set", "p[1] panics after s is set"},
		{g, "set", "p[i] panics after s is set"},
		{h, "success", "p.T panics before fail is set"},
	} {
		if test.fn() != test.want {
			panic(test.desc)
		}
	}
}