Skip to content

Commit

Permalink
fix: resolve receiver for binary methods on non interface types
Browse files Browse the repository at this point in the history
  • Loading branch information
mvertes authored Mar 12, 2020
1 parent 78bbcda commit 9b07e73
Show file tree
Hide file tree
Showing 4 changed files with 27 additions and 7 deletions.
21 changes: 21 additions & 0 deletions _test/struct36.go
Original file line number Diff line number Diff line change
@@ -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
1 change: 1 addition & 0 deletions interp/cfg.go
Original file line number Diff line number Diff line change
Expand Up @@ -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 {
Expand Down
6 changes: 3 additions & 3 deletions interp/run.go
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand All @@ -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
}
Expand Down
6 changes: 2 additions & 4 deletions interp/type.go
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down

0 comments on commit 9b07e73

Please sign in to comment.