Skip to content

Commit

Permalink
interp: improve handling of empty interface values (#1393)
Browse files Browse the repository at this point in the history
At variable, function parameter, slice, map or field element assign,
if the destination type is an empty interface, the value was never
wrapped into a valueInterface (to preserve type mutability in case
of re-assign). Now we wrap it in a valueInterface if the source
type has a non empty set of methods, to allow a future use as a non
empty interface.

There are still corner cases, but it extends notably the support
of interfaces within the interpreter.

Fixes #1355.
  • Loading branch information
mvertes authored May 19, 2022
1 parent 821e9ee commit d183f42
Show file tree
Hide file tree
Showing 4 changed files with 38 additions and 11 deletions.
22 changes: 22 additions & 0 deletions _test/issue-1355.go
Original file line number Diff line number Diff line change
@@ -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
9 changes: 9 additions & 0 deletions _test/p2/p2.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
package p2

type I interface {
isI()
}

type T struct{}

func (t *T) isI() {}
16 changes: 6 additions & 10 deletions interp/run.go
Original file line number Diff line number Diff line change
Expand Up @@ -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))
Expand Down Expand Up @@ -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)
Expand Down Expand Up @@ -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)
Expand All @@ -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)
Expand Down
2 changes: 1 addition & 1 deletion interp/value.go
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down

0 comments on commit d183f42

Please sign in to comment.