GoPLS Viewer

Home|gopls/go/ssa/interp/testdata/boundmeth.go
1// Tests of bound method closures.
2
3package main
4
5import (
6    "errors"
7    "fmt"
8)
9
10func assert(b bool) {
11    if !b {
12        panic("oops")
13    }
14}
15
16type I int
17
18func (i Iadd(x intint {
19    return int(i) + x
20}
21
22func valueReceiver() {
23    var three I = 3
24    assert(three.add(5) == 8)
25    var add3 func(intint = three.add
26    assert(add3(5) == 8)
27}
28
29type S struct{ x int }
30
31func (s *Sincr() {
32    s.x++
33}
34
35func (s *Sget() int {
36    return s.x
37}
38
39func pointerReceiver() {
40    ps := new(S)
41    incr := ps.incr
42    get := ps.get
43    assert(get() == 0)
44    incr()
45    incr()
46    incr()
47    assert(get() == 3)
48}
49
50func addressibleValuePointerReceiver() {
51    var s S
52    incr := s.incr
53    get := s.get
54    assert(get() == 0)
55    incr()
56    incr()
57    incr()
58    assert(get() == 3)
59}
60
61type S2 struct {
62    S
63}
64
65func promotedReceiver() {
66    var s2 S2
67    incr := s2.incr
68    get := s2.get
69    assert(get() == 0)
70    incr()
71    incr()
72    incr()
73    assert(get() == 3)
74}
75
76func anonStruct() {
77    var s struct{ S }
78    incr := s.incr
79    get := s.get
80    assert(get() == 0)
81    incr()
82    incr()
83    incr()
84    assert(get() == 3)
85}
86
87func typeCheck() {
88    var i interface{}
89    i = (*S).incr
90    _ = i.(func(*S)) // type assertion: receiver type prepended to params
91
92    var s S
93    i = s.incr
94    _ = i.(func()) // type assertion: receiver type disappears
95}
96
97type errString string
98
99func (err errStringError() string {
100    return string(err)
101}
102
103// Regression test for a builder crash.
104func regress1(x error) func() string {
105    return x.Error
106}
107
108// Regression test for b/7269:
109// taking the value of an interface method performs a nil check.
110func nilInterfaceMethodValue() {
111    err := errors.New("ok")
112    f := err.Error
113    if got := f(); got != "ok" {
114        panic(got)
115    }
116
117    err = nil
118    if got := f(); got != "ok" {
119        panic(got)
120    }
121
122    defer func() {
123        r := fmt.Sprint(recover())
124        // runtime panic string varies across toolchains
125        if r != "interface conversion: interface is nil, not error" &&
126            r != "runtime error: invalid memory address or nil pointer dereference" &&
127            r != "method value: interface is nil" {
128            panic("want runtime panic from nil interface method value, got " + r)
129        }
130    }()
131    f = err.Error // runtime panic: err is nil
132    panic("unreachable")
133}
134
135func main() {
136    valueReceiver()
137    pointerReceiver()
138    addressibleValuePointerReceiver()
139    promotedReceiver()
140    anonStruct()
141    typeCheck()
142
143    if e := regress1(errString("hi"))(); e != "hi" {
144        panic(e)
145    }
146
147    nilInterfaceMethodValue()
148}
149
MembersX
S.incr.s
S.get.s
promotedReceiver.s2
nilInterfaceMethodValue.err
valueReceiver
S.x
anonStruct
typeCheck.s
regress1.x
assert.b
addressibleValuePointerReceiver.s
typeCheck
errString
nilInterfaceMethodValue
pointerReceiver.incr
anonStruct.incr
addressibleValuePointerReceiver.incr
promotedReceiver
nilInterfaceMethodValue.f
nilInterfaceMethodValue.BlockStmt.r
fmt
pointerReceiver.get
addressibleValuePointerReceiver
S2
errString.Error
main.e
errors
pointerReceiver.ps
S.incr
addressibleValuePointerReceiver.get
anonStruct.get
errString.Error.err
I.add
S
I.add.x
valueReceiver.three
promotedReceiver.incr
promotedReceiver.get
regress1
assert
I
pointerReceiver
nilInterfaceMethodValue.got
main
I.add.i
S.get
Members
X