Skip to content

Commit

Permalink
fix: correct handling of dynamic type for interface values
Browse files Browse the repository at this point in the history
  • Loading branch information
mvertes authored and traefiker committed Nov 25, 2019
1 parent 9f1f312 commit e506969
Show file tree
Hide file tree
Showing 3 changed files with 49 additions and 6 deletions.
32 changes: 32 additions & 0 deletions _test/interface13.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
package main

import (
"fmt"
)

type X struct{}

func (X) Foo() int {
return 1
}
func (X) Bar() int {
return 2
}

type Foo interface {
Foo() int
}
type Bar interface {
Bar() int
}

func main() {
var x X
var i Foo = x
j := i.(Bar)

fmt.Println(j.Bar())
}

// Output:
// 2
10 changes: 5 additions & 5 deletions interp/run.go
Original file line number Diff line number Diff line change
Expand Up @@ -151,26 +151,26 @@ func typeAssertStatus(n *node) {
}

func typeAssert(n *node) {
value := genValue(n.child[0])
i := n.findex
value := genValue(n.child[0]) // input value
dest := genValue(n) // returned result
next := getExec(n.tnext)

switch {
case n.child[0].typ.cat == valueT:
n.exec = func(f *frame) bltn {
f.data[i].Set(value(f).Elem())
dest(f).Set(value(f).Elem())
return next
}
case n.child[1].typ.cat == interfaceT:
n.exec = func(f *frame) bltn {
v := value(f).Interface().(valueInterface)
f.data[i] = reflect.ValueOf(valueInterface{v.node, v.value})
dest(f).Set(reflect.ValueOf(valueInterface{v.node, v.value}))
return next
}
default:
n.exec = func(f *frame) bltn {
v := value(f).Interface().(valueInterface)
f.data[i].Set(v.value)
dest(f).Set(v.value)
return next
}
}
Expand Down
13 changes: 12 additions & 1 deletion interp/value.go
Original file line number Diff line number Diff line change
Expand Up @@ -159,7 +159,18 @@ func genValueInterface(n *node) func(*frame) reflect.Value {
value := genValue(n)

return func(f *frame) reflect.Value {
return reflect.ValueOf(valueInterface{n, value(f)})
v := value(f)
nod := n
for {
// traverse interface indirections to find out concrete type
vi, ok := v.Interface().(valueInterface)
if !ok {
break
}
v = vi.value
nod = vi.node
}
return reflect.ValueOf(valueInterface{nod, v})
}
}

Expand Down

0 comments on commit e506969

Please sign in to comment.