Skip to content

Commit

Permalink
interp: fix nested calls with variadic interfaces
Browse files Browse the repository at this point in the history
Fixes #1326
  • Loading branch information
mvertes committed Dec 8, 2021
1 parent 5b62f9f commit 8323068
Show file tree
Hide file tree
Showing 2 changed files with 47 additions and 5 deletions.
42 changes: 42 additions & 0 deletions _test/issue-1326.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
package main

type Option interface {
apply(*T)
}

type T struct {
s string
}

type opt struct {
name string
}

func (o *opt) apply(t *T) {
println(o.name)
}

func BuildOptions() []Option {
return []Option{
&opt{"opt1"},
&opt{"opt2"},
}
}

func NewT(name string, options ...Option) *T {
t := &T{name}
for _, opt := range options {
opt.apply(t)
}
return t
}

func main() {
t := NewT("hello", BuildOptions()...)
println(t.s)
}

// Output:
// opt1
// opt2
// hello
10 changes: 5 additions & 5 deletions interp/run.go
Original file line number Diff line number Diff line change
Expand Up @@ -1151,6 +1151,7 @@ func call(n *node) {
child := n.child[1:]
tnext := getExec(n.tnext)
fnext := getExec(n.fnext)
hasVariadicArgs := n.action == aCallSlice // callSlice implies variadic call with ellipsis.

// Compute input argument value functions.
for i, c := range child {
Expand All @@ -1166,7 +1167,7 @@ func call(n *node) {
numOut := c.child[0].typ.rtype.NumOut()
for j := 0; j < numOut; j++ {
ind := c.findex + j
if !isInterfaceSrc(arg) || isEmptyInterface(arg) {
if hasVariadicArgs || !isInterfaceSrc(arg) || isEmptyInterface(arg) {
values = append(values, func(f *frame) reflect.Value { return f.data[ind] })
continue
}
Expand All @@ -1179,7 +1180,7 @@ func call(n *node) {
cc0 := c.child[0]
for j := range cc0.typ.ret {
ind := c.findex + j
if !isInterfaceSrc(arg) || isEmptyInterface(arg) {
if hasVariadicArgs || !isInterfaceSrc(arg) || isEmptyInterface(arg) {
values = append(values, func(f *frame) reflect.Value { return f.data[ind] })
continue
}
Expand All @@ -1195,8 +1196,7 @@ func call(n *node) {
switch {
case isEmptyInterface(arg):
values = append(values, genValue(c))
case isInterfaceSrc(arg) && n.action != aCallSlice:
// callSlice implies variadic call with ellipsis, do not wrap in valueInterface.
case isInterfaceSrc(arg) && !hasVariadicArgs:
values = append(values, genValueInterface(c))
case isInterfaceBin(arg):
values = append(values, genInterfaceWrapper(c, arg.rtype))
Expand Down Expand Up @@ -1926,7 +1926,7 @@ func getMethodByName(n *node) {
}
return next
}
m, li := val.node.typ.lookupMethod(name)
m, li := typ.lookupMethod(name)
if m == nil {
panic(n.cfgErrorf("method not found: %s", name))
}
Expand Down

0 comments on commit 8323068

Please sign in to comment.