Skip to content

Commit

Permalink
fix: handle type assertion from literal interface type
Browse files Browse the repository at this point in the history
  • Loading branch information
mvertes authored and traefiker committed Nov 19, 2019
1 parent c5ec5e4 commit 08a37fc
Show file tree
Hide file tree
Showing 4 changed files with 69 additions and 4 deletions.
12 changes: 12 additions & 0 deletions _test/composite3.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
package main

func main() {
var err error
var ok bool

_, ok = err.(interface{ IsSet() bool })
println(ok)
}

// Output:
// false
11 changes: 11 additions & 0 deletions _test/composite4.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
package main

func main() {
var err error

_, ok := err.(interface{ IsSet() bool })
println(ok)
}

// Output:
// false
19 changes: 15 additions & 4 deletions interp/cfg.go
Original file line number Diff line number Diff line change
Expand Up @@ -517,7 +517,11 @@ func (interp *Interpreter) cfg(root *node) ([]*node, error) {
n.child[l].gen = getIndexMap2
n.gen = nop
case typeAssertExpr:
n.child[l].gen = typeAssert2
if n.child[0].ident == "_" {
n.child[l].gen = typeAssertStatus
} else {
n.child[l].gen = typeAssert2
}
n.gen = nop
case unaryExpr:
if n.child[l].action == aRecv {
Expand Down Expand Up @@ -1314,7 +1318,9 @@ func (interp *Interpreter) cfg(root *node) ([]*node, error) {
if len(n.child) > 1 {
wireChild(n)
if n.child[1].typ == nil {
n.child[1].typ = sc.getType(n.child[1].ident)
if n.child[1].typ, err = nodeType(interp, sc, n.child[1]); err != nil {
return
}
}
if n.anc.action != aAssignX {
n.typ = n.child[1].typ
Expand Down Expand Up @@ -1386,8 +1392,12 @@ func compDefineX(sc *scope, n *node) error {
n.gen = nop

case typeAssertExpr:
if n.child[0].ident == "_" {
n.child[l].gen = typeAssertStatus
} else {
n.child[l].gen = typeAssert2
}
types = append(types, n.child[l].child[1].typ, sc.getType("bool"))
n.child[l].gen = typeAssert2
n.gen = nop

case unaryExpr:
Expand Down Expand Up @@ -1595,7 +1605,8 @@ func isKey(n *node) bool {
return n.anc.kind == fileStmt ||
(n.anc.kind == selectorExpr && n.anc.child[0] != n) ||
(n.anc.kind == funcDecl && isMethod(n.anc)) ||
(n.anc.kind == keyValueExpr && isStruct(n.anc.typ) && n.anc.child[0] == n)
(n.anc.kind == keyValueExpr && isStruct(n.anc.typ) && n.anc.child[0] == n) ||
(n.anc.kind == fieldExpr && len(n.anc.child) > 1 && n.anc.child[0] == n)
}

// isNewDefine returns true if node refers to a new definition
Expand Down
31 changes: 31 additions & 0 deletions interp/run.go
Original file line number Diff line number Diff line change
Expand Up @@ -119,6 +119,37 @@ func runCfg(n *node, f *frame) {
}
}

func typeAssertStatus(n *node) {
value := genValue(n.child[0]) // input value
value1 := genValue(n.anc.child[1]) // returned status
next := getExec(n.tnext)

switch {
case n.child[0].typ.cat == valueT:
n.exec = func(f *frame) bltn {
if !value(f).IsValid() || value(f).IsNil() {
value1(f).SetBool(false)
}
value1(f).SetBool(true)
return next
}
case n.child[1].typ.cat == interfaceT:
n.exec = func(f *frame) bltn {
_, ok := value(f).Interface().(valueInterface)
//value0(f).Set(reflect.ValueOf(valueInterface{v.node, v.value}))
value1(f).SetBool(ok)
return next
}
default:
n.exec = func(f *frame) bltn {
_, ok := value(f).Interface().(valueInterface)
//value0(f).Set(v.value)
value1(f).SetBool(ok)
return next
}
}
}

func typeAssert(n *node) {
value := genValue(n.child[0])
i := n.findex
Expand Down

0 comments on commit 08a37fc

Please sign in to comment.