interp: fix method lookup on pointers to binary types
This case was missing in the selector expression processing. Fixes #1083.
This commit is contained in:
19
_test/method37.go
Normal file
19
_test/method37.go
Normal file
@@ -0,0 +1,19 @@
|
|||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"net"
|
||||||
|
"os"
|
||||||
|
)
|
||||||
|
|
||||||
|
func writeBufs(bufs ...[]byte) error {
|
||||||
|
b := net.Buffers(bufs)
|
||||||
|
_, err := b.WriteTo(os.Stdout)
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
writeBufs([]byte("hello"))
|
||||||
|
}
|
||||||
|
|
||||||
|
// Output:
|
||||||
|
// hello
|
||||||
@@ -1490,28 +1490,28 @@ func (interp *Interpreter) cfg(root *node, importPath string) ([]*node, error) {
|
|||||||
n.typ = &itype{cat: valueT, rtype: field.Type}
|
n.typ = &itype{cat: valueT, rtype: field.Type}
|
||||||
n.val = field.Index
|
n.val = field.Index
|
||||||
n.gen = getPtrIndexSeq
|
n.gen = getPtrIndexSeq
|
||||||
} else {
|
break
|
||||||
err = n.cfgErrorf("undefined field or method: %s", n.child[1].ident)
|
|
||||||
}
|
}
|
||||||
|
err = n.cfgErrorf("undefined field or method: %s", n.child[1].ident)
|
||||||
case n.typ.rtype.Kind() == reflect.Struct:
|
case n.typ.rtype.Kind() == reflect.Struct:
|
||||||
if field, ok := n.typ.rtype.FieldByName(n.child[1].ident); ok {
|
if field, ok := n.typ.rtype.FieldByName(n.child[1].ident); ok {
|
||||||
n.typ = &itype{cat: valueT, rtype: field.Type}
|
n.typ = &itype{cat: valueT, rtype: field.Type}
|
||||||
n.val = field.Index
|
n.val = field.Index
|
||||||
n.gen = getIndexSeq
|
n.gen = getIndexSeq
|
||||||
} else {
|
break
|
||||||
// method lookup failed on type, now lookup on pointer to type
|
|
||||||
pt := reflect.PtrTo(n.typ.rtype)
|
|
||||||
if m2, ok2 := pt.MethodByName(n.child[1].ident); ok2 {
|
|
||||||
n.val = m2.Index
|
|
||||||
n.gen = getIndexBinPtrMethod
|
|
||||||
n.typ = &itype{cat: valueT, rtype: m2.Type, recv: &itype{cat: valueT, rtype: pt}}
|
|
||||||
n.recv = &receiver{node: n.child[0]}
|
|
||||||
n.action = aGetMethod
|
|
||||||
} else {
|
|
||||||
err = n.cfgErrorf("undefined field or method: %s", n.child[1].ident)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
fallthrough
|
||||||
default:
|
default:
|
||||||
|
// method lookup failed on type, now lookup on pointer to type
|
||||||
|
pt := reflect.PtrTo(n.typ.rtype)
|
||||||
|
if m2, ok2 := pt.MethodByName(n.child[1].ident); ok2 {
|
||||||
|
n.val = m2.Index
|
||||||
|
n.gen = getIndexBinPtrMethod
|
||||||
|
n.typ = &itype{cat: valueT, rtype: m2.Type, recv: &itype{cat: valueT, rtype: pt}}
|
||||||
|
n.recv = &receiver{node: n.child[0]}
|
||||||
|
n.action = aGetMethod
|
||||||
|
break
|
||||||
|
}
|
||||||
err = n.cfgErrorf("undefined field or method: %s", n.child[1].ident)
|
err = n.cfgErrorf("undefined field or method: %s", n.child[1].ident)
|
||||||
}
|
}
|
||||||
} else if n.typ.cat == ptrT && (n.typ.val.cat == valueT || n.typ.val.cat == errorT) {
|
} else if n.typ.cat == ptrT && (n.typ.val.cat == valueT || n.typ.val.cat == errorT) {
|
||||||
|
|||||||
Reference in New Issue
Block a user