blob: 47b94068591abd378a2a9892e06cb87142871fad (
plain)
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
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
|
// Tests of bound method closures.
package main
import (
"errors"
"fmt"
)
func assert(b bool) {
if !b {
panic("oops")
}
}
type I int
func (i I) add(x int) int {
return int(i) + x
}
func valueReceiver() {
var three I = 3
assert(three.add(5) == 8)
var add3 func(int) int = three.add
assert(add3(5) == 8)
}
type S struct{ x int }
func (s *S) incr() {
s.x++
}
func (s *S) get() int {
return s.x
}
func pointerReceiver() {
ps := new(S)
incr := ps.incr
get := ps.get
assert(get() == 0)
incr()
incr()
incr()
assert(get() == 3)
}
func addressibleValuePointerReceiver() {
var s S
incr := s.incr
get := s.get
assert(get() == 0)
incr()
incr()
incr()
assert(get() == 3)
}
type S2 struct {
S
}
func promotedReceiver() {
var s2 S2
incr := s2.incr
get := s2.get
assert(get() == 0)
incr()
incr()
incr()
assert(get() == 3)
}
func anonStruct() {
var s struct{ S }
incr := s.incr
get := s.get
assert(get() == 0)
incr()
incr()
incr()
assert(get() == 3)
}
func typeCheck() {
var i interface{}
i = (*S).incr
_ = i.(func(*S)) // type assertion: receiver type prepended to params
var s S
i = s.incr
_ = i.(func()) // type assertion: receiver type disappears
}
type errString string
func (err errString) Error() string {
return string(err)
}
// Regression test for a builder crash.
func regress1(x error) func() string {
return x.Error
}
// Regression test for b/7269:
// taking the value of an interface method performs a nil check.
func nilInterfaceMethodValue() {
err := errors.New("ok")
f := err.Error
if got := f(); got != "ok" {
panic(got)
}
err = nil
if got := f(); got != "ok" {
panic(got)
}
defer func() {
r := fmt.Sprint(recover())
// runtime panic string varies across toolchains
if r != "interface conversion: interface is nil, not error" &&
r != "runtime error: invalid memory address or nil pointer dereference" &&
r != "method value: interface is nil" {
panic("want runtime panic from nil interface method value, got " + r)
}
}()
f = err.Error // runtime panic: err is nil
panic("unreachable")
}
func main() {
valueReceiver()
pointerReceiver()
addressibleValuePointerReceiver()
promotedReceiver()
anonStruct()
typeCheck()
if e := regress1(errString("hi"))(); e != "hi" {
panic(e)
}
nilInterfaceMethodValue()
}
|