148 lines
2.2 KiB
Go
148 lines
2.2 KiB
Go
// 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" {
|
|
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()
|
|
}
|