fix: correct handling of function in struct field (#226)

This commit is contained in:
Marc Vertes
2019-06-17 14:40:55 +02:00
committed by Ludovic Fernandez
parent cd12274ec6
commit 25ddbbad03
5 changed files with 67 additions and 5 deletions

21
_test/struct20.go Normal file
View File

@@ -0,0 +1,21 @@
package main
type SecretProvider func(user, realm string) string
type BasicAuth struct {
Realm string
Secrets SecretProvider
}
func (a *BasicAuth) CheckAuth() string { return a.Secrets("me", a.Realm) }
func secretBasic(user, realm string) string { return user + "-" + realm }
func main() {
b := &BasicAuth{"test", secretBasic}
s := b.CheckAuth()
println(s)
}
// Output:
// me-test

22
_test/struct21.go Normal file
View File

@@ -0,0 +1,22 @@
package main
type SecretProvider func(user, realm string) string
type BasicAuth struct {
Realm string
Secrets SecretProvider
}
func (a *BasicAuth) CheckAuth() string { return a.Secrets("me", a.Realm) }
func (a *BasicAuth) secretBasic(user, realm string) string { return a.Realm + "-" + user + "-" + realm }
func main() {
b := &BasicAuth{Realm: "test"}
b.Secrets = b.secretBasic
s := b.CheckAuth()
println(s)
}
// Output:
// test-me-test

View File

@@ -1151,6 +1151,11 @@ func (interp *Interpreter) Cfg(root *Node) ([]*Node, error) {
case PtrT:
n.typ = n.typ.fieldSeq(ti)
n.gen = getPtrIndexSeq
if n.typ.cat == FuncT {
// function in a struct field is always wrapped in reflect.Value
rtype := n.typ.TypeOf()
n.typ = &Type{cat: ValueT, rtype: rtype}
}
default:
n.gen = getIndexSeq
n.typ = n.typ.fieldSeq(ti)

View File

@@ -8,6 +8,8 @@ import (
"reflect"
)
func init() { log.SetFlags(log.Lshortfile) }
// Builtin type defines functions which run at CFG execution
type Builtin func(f *Frame) Builtin
@@ -400,7 +402,11 @@ func _panic(n *Node) {
}
func genFunctionWrapper(n *Node) func(*Frame) reflect.Value {
def := n.val.(*Node)
var def *Node
var ok bool
if def, ok = n.val.(*Node); !ok {
return genValueAsFunctionWrapper(n)
}
setExec(def.child[3].start)
start := def.child[3].start
numRet := len(def.typ.ret)
@@ -1446,12 +1452,13 @@ func compositeSparse(n *Node) {
values := make(map[int]func(*Frame) reflect.Value)
a, _ := n.typ.zero()
for _, c := range child {
c1 := c.child[1]
field := n.typ.fieldIndex(c.child[0].ident)
convertLiteralValue(c.child[1], n.typ.field[field].typ.TypeOf())
if c.typ.cat == FuncT {
values[field] = genFunctionWrapper(c.child[1])
convertLiteralValue(c1, n.typ.field[field].typ.TypeOf())
if c1.typ.cat == FuncT {
values[field] = genFunctionWrapper(c1)
} else {
values[field] = genValue(c.child[1])
values[field] = genValue(c1)
}
}

View File

@@ -44,6 +44,13 @@ func genValueRecv(n *Node) func(*Frame) reflect.Value {
}
}
func genValueAsFunctionWrapper(n *Node) func(*Frame) reflect.Value {
v := genValue(n)
return func(f *Frame) reflect.Value {
return genFunctionWrapper(v(f).Interface().(*Node))(f)
}
}
func genValueAs(n *Node, t reflect.Type) func(*Frame) reflect.Value {
v := genValue(n)
return func(f *Frame) reflect.Value {