fix: type assertion expression was not forwarding type

The detection of special cases of interpreter functions and interfaces
is more precise. It allows at least to complete parsing of
code where type is derived from a type assertion expression.

Fixes #770.
This commit is contained in:
Marc Vertes
2020-07-23 11:51:53 +02:00
committed by GitHub
parent e5a7b0de11
commit 68911f8b4e
3 changed files with 34 additions and 6 deletions

25
_test/issue-770.go Normal file
View File

@@ -0,0 +1,25 @@
package main
import "reflect"
type I interface {
Foo() int
}
type T struct {
Name string
}
func (t T) Foo() int { return 0 }
func f(v reflect.Value) int {
i := v.Interface().(I)
return i.Foo()
}
func main() {
println("hello")
}
// Output:
// hello

View File

@@ -1725,17 +1725,18 @@ func (interp *Interpreter) cfg(root *node, pkgID string) ([]*node, error) {
case typeAssertExpr:
if len(n.child) > 1 {
wireChild(n)
if n.child[1].typ == nil {
if n.child[1].typ, err = nodeType(interp, sc, n.child[1]); err != nil {
c1 := n.child[1]
if c1.typ == nil {
if c1.typ, err = nodeType(interp, sc, c1); err != nil {
return
}
}
if n.anc.action != aAssignX {
if n.child[0].typ.cat == valueT && !isStruct(n.child[1].typ) {
if n.child[0].typ.cat == valueT && isFunc(c1.typ) {
// Avoid special wrapping of interfaces and func types.
n.typ = &itype{cat: valueT, rtype: n.child[1].typ.TypeOf()}
n.typ = &itype{cat: valueT, rtype: c1.typ.TypeOf()}
} else {
n.typ = n.child[1].typ
n.typ = c1.typ
}
n.findex = sc.add(n.typ)
}

View File

@@ -1536,11 +1536,13 @@ func chanElement(t *itype) *itype {
func isBool(t *itype) bool { return t.TypeOf().Kind() == reflect.Bool }
func isChan(t *itype) bool { return t.TypeOf().Kind() == reflect.Chan }
func isFunc(t *itype) bool { return t.TypeOf().Kind() == reflect.Func }
func isMap(t *itype) bool { return t.TypeOf().Kind() == reflect.Map }
func isSendChan(t *itype) bool {
rt := t.TypeOf()
return rt.Kind() == reflect.Chan && rt.ChanDir() == reflect.SendDir
}
func isMap(t *itype) bool { return t.TypeOf().Kind() == reflect.Map }
func isArray(t *itype) bool {
k := t.TypeOf().Kind()
return k == reflect.Array || k == reflect.Slice