diff --git a/_test/issue-1355.go b/_test/issue-1355.go new file mode 100644 index 000000000..329af0489 --- /dev/null +++ b/_test/issue-1355.go @@ -0,0 +1,22 @@ +package main + +import "github.com/traefik/yaegi/_test/p2" + +func f(i interface{}) { + _, ok := i.(p2.I) + println("ok:", ok) +} + +func main() { + var v *p2.T + var i interface{} + + i = v + _, ok := i.(p2.I) + println("ok:", ok) + f(v) +} + +// Output: +// ok: true +// ok: true diff --git a/_test/p2/p2.go b/_test/p2/p2.go new file mode 100644 index 000000000..7842a5c8b --- /dev/null +++ b/_test/p2/p2.go @@ -0,0 +1,9 @@ +package p2 + +type I interface { + isI() +} + +type T struct{} + +func (t *T) isI() {} diff --git a/interp/run.go b/interp/run.go index c86b68a5a..228d7bbfe 100644 --- a/interp/run.go +++ b/interp/run.go @@ -1228,13 +1228,13 @@ func call(n *node) { convertLiteralValue(c, argType) } switch { - case isEmptyInterface(arg): + case hasVariadicArgs: values = append(values, genValue(c)) - case isInterfaceSrc(arg) && !hasVariadicArgs: + case isInterfaceSrc(arg) && (!isEmptyInterface(arg) || len(c.typ.method) > 0): values = append(values, genValueInterface(c)) case isInterfaceBin(arg): values = append(values, genInterfaceWrapper(c, arg.rtype)) - case isFuncSrc(arg) && !hasVariadicArgs: + case isFuncSrc(arg): values = append(values, genValueNode(c)) default: values = append(values, genValue(c)) @@ -2690,7 +2690,7 @@ func doComposite(n *node, hasType bool, keyed bool) { values[fieldIndex] = genValueAsFunctionWrapper(val) case isArray(val.typ) && val.typ.val != nil && isInterfaceSrc(val.typ.val) && !isEmptyInterface(val.typ.val): values[fieldIndex] = genValueInterfaceArray(val) - case isInterfaceSrc(ft) && !isEmptyInterface(ft): + case isInterfaceSrc(ft) && (!isEmptyInterface(ft) || len(val.typ.method) > 0): values[fieldIndex] = genValueInterface(val) case isInterface(ft): values[fieldIndex] = genInterfaceWrapper(val, rft) @@ -3131,9 +3131,7 @@ func _append(n *node) { values := make([]func(*frame) reflect.Value, l) for i, arg := range args { switch elem := n.typ.elem(); { - case isEmptyInterface(elem): - values[i] = genValue(arg) - case isInterfaceSrc(elem): + case isInterfaceSrc(elem) && (!isEmptyInterface(elem) || len(arg.typ.method) > 0): values[i] = genValueInterface(arg) case isInterfaceBin(elem): values[i] = genInterfaceWrapper(arg, elem.rtype) @@ -3155,9 +3153,7 @@ func _append(n *node) { default: var value0 func(*frame) reflect.Value switch elem := n.typ.elem(); { - case isEmptyInterface(elem): - value0 = genValue(n.child[2]) - case isInterfaceSrc(elem): + case isInterfaceSrc(elem) && (!isEmptyInterface(elem) || len(n.child[2].typ.method) > 0): value0 = genValueInterface(n.child[2]) case isInterfaceBin(elem): value0 = genInterfaceWrapper(n.child[2], elem.rtype) diff --git a/interp/value.go b/interp/value.go index 980773bde..f3a0acf2b 100644 --- a/interp/value.go +++ b/interp/value.go @@ -219,7 +219,7 @@ func genValue(n *node) func(*frame) reflect.Value { func genDestValue(typ *itype, n *node) func(*frame) reflect.Value { convertLiteralValue(n, typ.TypeOf()) switch { - case isInterfaceSrc(typ) && !isEmptyInterface(typ): + case isInterfaceSrc(typ) && (!isEmptyInterface(typ) || len(n.typ.method) > 0): return genValueInterface(n) case isFuncSrc(typ) && (n.typ.cat == valueT || n.typ.cat == nilT): return genValueNode(n)