Skip to content

Commit

Permalink
interp: support two more type assertion cases
Browse files Browse the repository at this point in the history
Fixes #967
  • Loading branch information
mpl authored Dec 1, 2020
1 parent 1e0f6ec commit 101633c
Show file tree
Hide file tree
Showing 2 changed files with 84 additions and 5 deletions.
36 changes: 36 additions & 0 deletions _test/assert1.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
package main

import (
"fmt"
"time"
)

type TestStruct struct{}

func (t TestStruct) String() string {
return "hello world"
}

func main() {
var t interface{}
t = time.Nanosecond
s, ok := t.(fmt.Stringer)
if !ok {
fmt.Println("time.Nanosecond does not implement fmt.Stringer")
return
}
fmt.Println(s.String())

var tt interface{}
tt = TestStruct{}
ss, ok := tt.(fmt.Stringer)
if !ok {
fmt.Println("TestStuct does not implement fmt.Stringer")
return
}
fmt.Println(ss.String())
}

// Output:
// 1ns
// hello world
53 changes: 48 additions & 5 deletions interp/run.go
Original file line number Diff line number Diff line change
Expand Up @@ -380,14 +380,54 @@ func typeAssert2(n *node) {
}
case isInterface(typ):
n.exec = func(f *frame) bltn {
v := value(f).Elem()
ok := v.IsValid() && canAssertTypes(v.Type(), rtype)
if ok {
var leftType reflect.Type
v := value(f)
val, ok := v.Interface().(valueInterface)
defer func() {
assertOk := ok
if setStatus {
value1(f).SetBool(assertOk)
}
}()
if ok && val.node.typ.cat != valueT {
m0 := val.node.typ.methods()
m1 := typ.methods()
if len(m0) < len(m1) {
ok = false
return next
}

for k, meth1 := range m1 {
var meth0 string
meth0, ok = m0[k]
if !ok {
return next
}
if meth0 != meth1 {
ok = false
return next
}
}

v = genInterfaceWrapper(val.node, rtype)(f)
value0(f).Set(v)
ok = true
return next
}
if setStatus {
value1(f).SetBool(ok)

if ok {
v = val.value
leftType = val.node.typ.rtype
} else {
v = v.Elem()
leftType = v.Type()
ok = true
}
ok = v.IsValid() && canAssertTypes(leftType, rtype)
if !ok {
return next
}
value0(f).Set(v)
return next
}
case n.child[0].typ.cat == valueT || n.child[0].typ.cat == errorT:
Expand Down Expand Up @@ -844,6 +884,9 @@ func genFunctionWrapper(n *node) func(*frame) reflect.Value {
if src.Type().Kind() != dest.Type().Kind() {
dest.Set(src.Addr())
} else {
if wrappedSrc, ok := src.Interface().(valueInterface); ok {
src = wrappedSrc.value
}
dest.Set(src)
}
d = d[numRet+1:]
Expand Down

0 comments on commit 101633c

Please sign in to comment.