github.com/llvm-mirror/llgo@v0.0.0-20190322182713-bf6f0a60fce1/third_party/gotools/go/ssa/interp/testdata/boundmeth.go (about)

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