fix: resolve receiver for binary methods on non interface types

This commit is contained in:
Marc Vertes
2020-03-12 14:42:04 +01:00
committed by GitHub
parent 78bbcda1f8
commit 9b07e73b5e
4 changed files with 27 additions and 7 deletions

21
_test/struct36.go Normal file
View File

@@ -0,0 +1,21 @@
package main
import (
"net/http"
"strings"
)
type S struct {
http.Client
}
func main() {
var s S
if _, err := s.Get("url"); err != nil {
println(strings.Contains(err.Error(), "unsupported protocol scheme"))
}
return
}
// Output:
// true

View File

@@ -1219,6 +1219,7 @@ func (interp *Interpreter) cfg(root *node, pkgID string) ([]*node, error) {
} else {
n.gen = getIndexSeqMethod
}
n.recv = &receiver{node: n.child[0], index: lind}
n.val = append([]int{m.Index}, lind...)
n.typ = &itype{cat: valueT, rtype: m.Type}
} else if ti := n.typ.lookupField(n.child[1].ident); len(ti) > 0 {

View File

@@ -803,7 +803,7 @@ func pindex(i, variadic int) int {
return variadic
}
// Call a function from a bin import, accessible through reflect
// Callbin calls a function from a bin import, accessible through reflect.
func callBin(n *node) {
tnext := getExec(n.tnext)
fnext := getExec(n.fnext)
@@ -815,9 +815,9 @@ func callBin(n *node) {
if funcType.IsVariadic() {
variadic = funcType.NumIn() - 1
}
// method signature obtained from reflect.Type include receiver as 1st arg, except for interface types
// A method signature obtained from reflect.Type includes receiver as 1st arg, except for interface types.
rcvrOffset := 0
if recv := n.child[0].recv; recv != nil && recv.node.typ.TypeOf().Kind() != reflect.Interface {
if recv := n.child[0].recv; recv != nil && !isInterface(recv.node.typ) {
if funcType.NumIn() > len(child) {
rcvrOffset = 1
}

View File

@@ -871,13 +871,11 @@ func (t *itype) lookupMethod(name string) (*node, []int) {
}
// lookupBinMethod returns a method and a path to access a field in a struct object (the receiver)
func (t *itype) lookupBinMethod(name string) (reflect.Method, []int, bool, bool) {
var isPtr bool
func (t *itype) lookupBinMethod(name string) (m reflect.Method, index []int, isPtr bool, ok bool) {
if t.cat == ptrT {
return t.val.lookupBinMethod(name)
}
var index []int
m, ok := t.TypeOf().MethodByName(name)
m, ok = t.TypeOf().MethodByName(name)
if !ok {
m, ok = reflect.PtrTo(t.TypeOf()).MethodByName(name)
isPtr = ok