Skip to content

Commit

Permalink
fix: correct handling of types alias of interfaces
Browse files Browse the repository at this point in the history
  • Loading branch information
mvertes authored and traefiker committed Sep 25, 2019
1 parent 03596da commit 35e645c
Show file tree
Hide file tree
Showing 6 changed files with 53 additions and 7 deletions.
27 changes: 27 additions & 0 deletions _test/interface11.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
package main

import "fmt"

type Error interface {
error
Code() string
}

type MyError Error

type T struct {
Name string
}

func (t *T) Error() string { return "err: " + t.Name }
func (t *T) Code() string { return "code: " + t.Name }

func newT(s string) MyError { return &T{s} }

func main() {
t := newT("foo")
fmt.Println(t.Code())
}

// Output:
// code: foo
2 changes: 1 addition & 1 deletion example/pkg/pkg_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -109,7 +109,7 @@ func TestPackagesError(t *testing.T) {
{
desc: "different packages in the same directory",
goPath: "./_pkg9/",
expected: "found packages pkg and pkgfalse in _pkg9/src/github.com/foo/pkg",
expected: "1:21: import \"github.com/foo/pkg\" error: found packages pkg and pkgfalse in _pkg9/src/github.com/foo/pkg",
},
}

Expand Down
6 changes: 3 additions & 3 deletions interp/cfg.go
Original file line number Diff line number Diff line change
Expand Up @@ -1119,12 +1119,12 @@ func (interp *Interpreter) cfg(root *node) ([]*node, error) {
} else if ti := n.typ.lookupField(n.child[1].ident); len(ti) > 0 {
// Handle struct field
n.val = ti
switch n.typ.cat {
case interfaceT:
switch {
case isInterfaceSrc(n.typ):
n.typ = n.typ.fieldSeq(ti)
n.gen = getMethodByName
n.action = aMethod
case ptrT:
case n.typ.cat == ptrT:
n.typ = n.typ.fieldSeq(ti)
n.gen = getPtrIndexSeq
if n.typ.cat == funcT {
Expand Down
5 changes: 4 additions & 1 deletion interp/gta.go
Original file line number Diff line number Diff line change
Expand Up @@ -156,6 +156,8 @@ func (interp *Interpreter) gta(root *node, rpath string) ([]*node, error) {
default: // import symbols in package namespace
sc.sym[name] = &symbol{kind: pkgSym, typ: &itype{cat: srcPkgT, path: ipath}}
}
} else {
err = n.cfgErrorf("import %q error: %v", ipath, err)
}

case typeSpec:
Expand All @@ -165,7 +167,8 @@ func (interp *Interpreter) gta(root *node, rpath string) ([]*node, error) {
return false
}
if n.child[1].kind == identExpr {
n.typ = &itype{cat: aliasT, val: typ, name: typeName, path: rpath, incomplete: typ.incomplete}
n.typ = &itype{cat: aliasT, val: typ, name: typeName, path: rpath, field: typ.field, incomplete: typ.incomplete}
copy(n.typ.method, typ.method)
} else {
n.typ = typ
n.typ.name = typeName
Expand Down
6 changes: 6 additions & 0 deletions interp/run.go
Original file line number Diff line number Diff line change
Expand Up @@ -1278,6 +1278,12 @@ func _return(n *node) {
switch t := def.typ.ret[i]; t.cat {
case errorT:
values[i] = genInterfaceWrapper(c, t.TypeOf())
case aliasT:
if isInterfaceSrc(t) {
values[i] = genValueInterface(c)
} else {
values[i] = genValue(c)
}
case interfaceT:
values[i] = genValueInterface(c)
default:
Expand Down
14 changes: 12 additions & 2 deletions interp/type.go
Original file line number Diff line number Diff line change
Expand Up @@ -688,7 +688,7 @@ func (t *itype) lookupField(name string) []int {

for i, f := range t.field {
switch f.typ.cat {
case ptrT, structT:
case ptrT, structT, interfaceT, aliasT:
if index2 := f.typ.lookupField(name); len(index2) > 0 {
return append([]int{i}, index2...)
}
Expand Down Expand Up @@ -800,6 +800,8 @@ func (t *itype) refType(defined map[string]bool) reflect.Type {
t.val.rtype = interf
}
switch t.cat {
case aliasT:
t.rtype = t.val.refType(defined)
case arrayT, variadicT:
if t.size > 0 {
t.rtype = reflect.ArrayOf(t.size, t.val.refType(defined))
Expand Down Expand Up @@ -861,6 +863,8 @@ func (t *itype) frameType() (r reflect.Type) {
panic(err)
}
switch t.cat {
case aliasT:
r = t.val.frameType()
case arrayT, variadicT:
if t.size > 0 {
r = reflect.ArrayOf(t.size, t.val.frameType())
Expand Down Expand Up @@ -903,7 +907,13 @@ func isShiftNode(n *node) bool {
return false
}

func isInterface(t *itype) bool { return t.cat == interfaceT || t.TypeOf().Kind() == reflect.Interface }
func isInterfaceSrc(t *itype) bool {
return t.cat == interfaceT || (t.cat == aliasT && isInterfaceSrc(t.val))
}

func isInterface(t *itype) bool {
return isInterfaceSrc(t) || t.TypeOf().Kind() == reflect.Interface
}

func isStruct(t *itype) bool { return t.TypeOf().Kind() == reflect.Struct }

Expand Down

0 comments on commit 35e645c

Please sign in to comment.