2013-03-20 17:11:09 -04:00
// run
2016-04-10 14:32:26 -07:00
// Copyright 2013 The Go Authors. All rights reserved.
2013-03-20 17:11:09 -04:00
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
package main
// Concrete types implementing M method.
// Smaller than a word, word-sized, larger than a word.
// Value and pointer receivers.
type Tinter interface {
M ( int , byte ) ( byte , int )
}
type Tsmallv byte
func ( v Tsmallv ) M ( x int , b byte ) ( byte , int ) { return b , x + int ( v ) }
type Tsmallp byte
func ( p * Tsmallp ) M ( x int , b byte ) ( byte , int ) { return b , x + int ( * p ) }
type Twordv uintptr
func ( v Twordv ) M ( x int , b byte ) ( byte , int ) { return b , x + int ( v ) }
type Twordp uintptr
func ( p * Twordp ) M ( x int , b byte ) ( byte , int ) { return b , x + int ( * p ) }
type Tbigv [ 2 ] uintptr
func ( v Tbigv ) M ( x int , b byte ) ( byte , int ) { return b , x + int ( v [ 0 ] ) + int ( v [ 1 ] ) }
type Tbigp [ 2 ] uintptr
func ( p * Tbigp ) M ( x int , b byte ) ( byte , int ) { return b , x + int ( p [ 0 ] ) + int ( p [ 1 ] ) }
// Again, with an unexported method.
type tsmallv byte
func ( v tsmallv ) m ( x int , b byte ) ( byte , int ) { return b , x + int ( v ) }
type tsmallp byte
func ( p * tsmallp ) m ( x int , b byte ) ( byte , int ) { return b , x + int ( * p ) }
type twordv uintptr
func ( v twordv ) m ( x int , b byte ) ( byte , int ) { return b , x + int ( v ) }
type twordp uintptr
func ( p * twordp ) m ( x int , b byte ) ( byte , int ) { return b , x + int ( * p ) }
type tbigv [ 2 ] uintptr
func ( v tbigv ) m ( x int , b byte ) ( byte , int ) { return b , x + int ( v [ 0 ] ) + int ( v [ 1 ] ) }
type tbigp [ 2 ] uintptr
func ( p * tbigp ) m ( x int , b byte ) ( byte , int ) { return b , x + int ( p [ 0 ] ) + int ( p [ 1 ] ) }
type tinter interface {
m ( int , byte ) ( byte , int )
}
// Embedding via pointer.
type T1 struct {
T2
}
type T2 struct {
* T3
}
type T3 struct {
* T4
}
type T4 struct {
}
func ( t4 T4 ) M ( x int , b byte ) ( byte , int ) { return b , x + 40 }
var failed = false
func CheckI ( name string , i Tinter , inc int ) {
b , x := i . M ( 1000 , 99 )
if b != 99 || x != 1000 + inc {
failed = true
print ( name , ".M(1000, 99) = " , b , ", " , x , " want 99, " , 1000 + inc , "\n" )
}
CheckF ( "(i=" + name + ")" , i . M , inc )
}
func CheckF ( name string , f func ( int , byte ) ( byte , int ) , inc int ) {
b , x := f ( 1000 , 99 )
if b != 99 || x != 1000 + inc {
failed = true
print ( name , "(1000, 99) = " , b , ", " , x , " want 99, " , 1000 + inc , "\n" )
}
}
func checkI ( name string , i tinter , inc int ) {
b , x := i . m ( 1000 , 99 )
if b != 99 || x != 1000 + inc {
failed = true
print ( name , ".m(1000, 99) = " , b , ", " , x , " want 99, " , 1000 + inc , "\n" )
}
checkF ( "(i=" + name + ")" , i . m , inc )
}
func checkF ( name string , f func ( int , byte ) ( byte , int ) , inc int ) {
b , x := f ( 1000 , 99 )
if b != 99 || x != 1000 + inc {
failed = true
print ( name , "(1000, 99) = " , b , ", " , x , " want 99, " , 1000 + inc , "\n" )
}
}
func shouldPanic ( f func ( ) ) {
defer func ( ) {
if recover ( ) == nil {
panic ( "not panicking" )
}
} ( )
f ( )
}
func shouldNotPanic ( f func ( ) ) {
f ( )
}
func main ( ) {
sv := Tsmallv ( 1 )
CheckI ( "sv" , sv , 1 )
CheckF ( "sv.M" , sv . M , 1 )
CheckF ( "(&sv).M" , ( & sv ) . M , 1 )
psv := & sv
CheckI ( "psv" , psv , 1 )
CheckF ( "psv.M" , psv . M , 1 )
CheckF ( "(*psv).M" , ( * psv ) . M , 1 )
sp := Tsmallp ( 2 )
CheckI ( "&sp" , & sp , 2 )
CheckF ( "sp.M" , sp . M , 2 )
CheckF ( "(&sp).M" , ( & sp ) . M , 2 )
psp := & sp
CheckI ( "psp" , psp , 2 )
CheckF ( "psp.M" , psp . M , 2 )
CheckF ( "(*psp).M" , ( * psp ) . M , 2 )
wv := Twordv ( 3 )
CheckI ( "wv" , wv , 3 )
CheckF ( "wv.M" , wv . M , 3 )
CheckF ( "(&wv).M" , ( & wv ) . M , 3 )
pwv := & wv
CheckI ( "pwv" , pwv , 3 )
CheckF ( "pwv.M" , pwv . M , 3 )
CheckF ( "(*pwv).M" , ( * pwv ) . M , 3 )
wp := Twordp ( 4 )
CheckI ( "&wp" , & wp , 4 )
CheckF ( "wp.M" , wp . M , 4 )
CheckF ( "(&wp).M" , ( & wp ) . M , 4 )
pwp := & wp
CheckI ( "pwp" , pwp , 4 )
CheckF ( "pwp.M" , pwp . M , 4 )
CheckF ( "(*pwp).M" , ( * pwp ) . M , 4 )
bv := Tbigv ( [ 2 ] uintptr { 5 , 6 } )
pbv := & bv
CheckI ( "bv" , bv , 11 )
CheckF ( "bv.M" , bv . M , 11 )
CheckF ( "(&bv).M" , ( & bv ) . M , 11 )
CheckI ( "pbv" , pbv , 11 )
CheckF ( "pbv.M" , pbv . M , 11 )
CheckF ( "(*pbv).M" , ( * pbv ) . M , 11 )
bp := Tbigp ( [ 2 ] uintptr { 7 , 8 } )
CheckI ( "&bp" , & bp , 15 )
CheckF ( "bp.M" , bp . M , 15 )
CheckF ( "(&bp).M" , ( & bp ) . M , 15 )
pbp := & bp
CheckI ( "pbp" , pbp , 15 )
CheckF ( "pbp.M" , pbp . M , 15 )
CheckF ( "(*pbp).M" , ( * pbp ) . M , 15 )
_sv := tsmallv ( 1 )
checkI ( "_sv" , _sv , 1 )
checkF ( "_sv.m" , _sv . m , 1 )
checkF ( "(&_sv).m" , ( & _sv ) . m , 1 )
_psv := & _sv
checkI ( "_psv" , _psv , 1 )
checkF ( "_psv.m" , _psv . m , 1 )
checkF ( "(*_psv).m" , ( * _psv ) . m , 1 )
_sp := tsmallp ( 2 )
checkI ( "&_sp" , & _sp , 2 )
checkF ( "_sp.m" , _sp . m , 2 )
checkF ( "(&_sp).m" , ( & _sp ) . m , 2 )
_psp := & _sp
checkI ( "_psp" , _psp , 2 )
checkF ( "_psp.m" , _psp . m , 2 )
checkF ( "(*_psp).m" , ( * _psp ) . m , 2 )
_wv := twordv ( 3 )
checkI ( "_wv" , _wv , 3 )
checkF ( "_wv.m" , _wv . m , 3 )
checkF ( "(&_wv).m" , ( & _wv ) . m , 3 )
_pwv := & _wv
checkI ( "_pwv" , _pwv , 3 )
checkF ( "_pwv.m" , _pwv . m , 3 )
checkF ( "(*_pwv).m" , ( * _pwv ) . m , 3 )
_wp := twordp ( 4 )
checkI ( "&_wp" , & _wp , 4 )
checkF ( "_wp.m" , _wp . m , 4 )
checkF ( "(&_wp).m" , ( & _wp ) . m , 4 )
_pwp := & _wp
checkI ( "_pwp" , _pwp , 4 )
checkF ( "_pwp.m" , _pwp . m , 4 )
checkF ( "(*_pwp).m" , ( * _pwp ) . m , 4 )
_bv := tbigv ( [ 2 ] uintptr { 5 , 6 } )
_pbv := & _bv
checkI ( "_bv" , _bv , 11 )
checkF ( "_bv.m" , _bv . m , 11 )
checkF ( "(&_bv).m" , ( & _bv ) . m , 11 )
checkI ( "_pbv" , _pbv , 11 )
checkF ( "_pbv.m" , _pbv . m , 11 )
checkF ( "(*_pbv).m" , ( * _pbv ) . m , 11 )
_bp := tbigp ( [ 2 ] uintptr { 7 , 8 } )
checkI ( "&_bp" , & _bp , 15 )
checkF ( "_bp.m" , _bp . m , 15 )
checkF ( "(&_bp).m" , ( & _bp ) . m , 15 )
_pbp := & _bp
checkI ( "_pbp" , _pbp , 15 )
checkF ( "_pbp.m" , _pbp . m , 15 )
checkF ( "(*_pbp).m" , ( * _pbp ) . m , 15 )
t4 := T4 { }
t3 := T3 { & t4 }
t2 := T2 { & t3 }
t1 := T1 { t2 }
CheckI ( "t4" , t4 , 40 )
CheckI ( "&t4" , & t4 , 40 )
CheckI ( "t3" , t3 , 40 )
CheckI ( "&t3" , & t3 , 40 )
CheckI ( "t2" , t2 , 40 )
CheckI ( "&t2" , & t2 , 40 )
CheckI ( "t1" , t1 , 40 )
CheckI ( "&t1" , & t1 , 40 )
// x.M panics if x is an interface type and is nil,
// or if x.M expands to (*x).M where x is nil,
// or if x.M expands to x.y.z.w.M where something
// along the evaluation of x.y.z.w is nil.
var f func ( int , byte ) ( byte , int )
shouldPanic ( func ( ) { psv = nil ; f = psv . M } )
shouldPanic ( func ( ) { pwv = nil ; f = pwv . M } )
shouldPanic ( func ( ) { pbv = nil ; f = pbv . M } )
shouldPanic ( func ( ) { var i Tinter ; f = i . M } )
shouldPanic ( func ( ) { _psv = nil ; f = _psv . m } )
shouldPanic ( func ( ) { _pwv = nil ; f = _pwv . m } )
shouldPanic ( func ( ) { _pbv = nil ; f = _pbv . m } )
shouldPanic ( func ( ) { var _i tinter ; f = _i . m } )
shouldPanic ( func ( ) { var t1 T1 ; f = t1 . M } )
shouldPanic ( func ( ) { var t2 T2 ; f = t2 . M } )
shouldPanic ( func ( ) { var t3 * T3 ; f = t3 . M } )
shouldPanic ( func ( ) { var t3 T3 ; f = t3 . M } )
if f != nil {
panic ( "something set f" )
}
// x.M does not panic if x is a nil pointer and
// M is a method with a pointer receiver.
shouldNotPanic ( func ( ) { psp = nil ; f = psp . M } )
shouldNotPanic ( func ( ) { pwp = nil ; f = pwp . M } )
shouldNotPanic ( func ( ) { pbp = nil ; f = pbp . M } )
shouldNotPanic ( func ( ) { _psp = nil ; f = _psp . m } )
shouldNotPanic ( func ( ) { _pwp = nil ; f = _pwp . m } )
shouldNotPanic ( func ( ) { _pbp = nil ; f = _pbp . m } )
shouldNotPanic ( func ( ) { var t4 T4 ; f = t4 . M } )
if f == nil {
panic ( "nothing set f" )
}
}