Skip to content

Commit

Permalink
interp: types should not recover data for aliases
Browse files Browse the repository at this point in the history
When `nodeType` recovers names and methods, it can overwrite the data if the type is an aliasT. When aliasing a type, do not recover the methods, this will be done in the GTA typeSpec pass.

Related to traefik#1158
  • Loading branch information
nrwiersma authored and Bai-Yingjie committed Sep 12, 2021
1 parent 1c7e3ca commit de16837
Show file tree
Hide file tree
Showing 4 changed files with 43 additions and 7 deletions.
19 changes: 19 additions & 0 deletions _test/alias3.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
package main

import "github.com/traefik/yaegi/_test/alias3"

var globalT *T

func init() {
globalT = &T{A: "test"}
}

type T alias3.T

func (t *T) PrintT() {
(*alias3.T)(t).Print()
}

func main() {
globalT.PrintT()
}
12 changes: 12 additions & 0 deletions _test/alias3/alias3.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
package alias3

type T struct {
A string
}

func (t *T) Print() {
println(t.A)
}

// Output:
// test
13 changes: 9 additions & 4 deletions interp/gta.go
Original file line number Diff line number Diff line change
Expand Up @@ -285,10 +285,15 @@ func (interp *Interpreter) gta(root *node, rpath, importPath, pkgName string) ([
sym, exists := sc.sym[typeName]
if !exists {
sc.sym[typeName] = &symbol{kind: typeSym}
} else if sym.typ == nil || len(sym.typ.method) == 0 {
// TODO(mpl): figure out how to detect redeclarations without breaking type aliases.
// Allow redeclarations for now.
sc.sym[typeName] = &symbol{kind: typeSym}
} else {
if sym.typ != nil && (len(sym.typ.method) > 0) {
// Type has already been seen as a receiver in a method function
n.typ.method = append(n.typ.method, sym.typ.method...)
} else {
// TODO(mpl): figure out how to detect redeclarations without breaking type aliases.
// Allow redeclarations for now.
sc.sym[typeName] = &symbol{kind: typeSym}
}
}
sc.sym[typeName].typ = n.typ
if !n.typ.isComplete() {
Expand Down
6 changes: 3 additions & 3 deletions interp/type.go
Original file line number Diff line number Diff line change
Expand Up @@ -888,11 +888,11 @@ func nodeType(interp *Interpreter, sc *scope, n *node) (*itype, error) {
err = n.cfgErrorf("use of untyped nil %s", t.name)
}

if n.anc.kind == typeSpec {
// The existing symbol data needs to be recovered, but not in the
// case where we are aliasing another type.
if n.anc.kind == typeSpec && n.kind != selectorExpr && n.kind != identExpr {
name := n.anc.child[0].ident
if sym := sc.sym[name]; sym != nil {
// Recover previously declared methods and set the type name.
t.method = sym.typ.method
t.path = sc.pkgName
t.name = name
}
Expand Down

0 comments on commit de16837

Please sign in to comment.