fix: correct handling of function in struct field (#226)
This commit is contained in:
committed by
Ludovic Fernandez
parent
cd12274ec6
commit
25ddbbad03
21
_test/struct20.go
Normal file
21
_test/struct20.go
Normal 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
22
_test/struct21.go
Normal 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
|
||||
@@ -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)
|
||||
|
||||
@@ -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)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -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 {
|
||||
|
||||
Reference in New Issue
Block a user