interp: types should not recover data for aliases

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 #1158
This commit is contained in:
Nicholas Wiersma
2021-09-06 18:24:04 +02:00
committed by GitHub
parent 45d569c215
commit 4653d87298
4 changed files with 43 additions and 7 deletions

19
_test/alias3.go Normal file
View File

@@ -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
_test/alias3/alias3.go Normal file
View File

@@ -0,0 +1,12 @@
package alias3
type T struct {
A string
}
func (t *T) Print() {
println(t.A)
}
// Output:
// test

View File

@@ -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() {

View File

@@ -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
}