diff --git a/_test/alias3.go b/_test/alias3.go index 87bedf6e..06d0b2f8 100644 --- a/_test/alias3.go +++ b/_test/alias3.go @@ -17,3 +17,6 @@ func (t *T) PrintT() { func main() { globalT.PrintT() } + +// Output: +// test diff --git a/_test/alias3/alias3.go b/_test/alias3/alias3.go index 1ca647a3..3117e9bc 100644 --- a/_test/alias3/alias3.go +++ b/_test/alias3/alias3.go @@ -7,6 +7,3 @@ type T struct { func (t *T) Print() { println(t.A) } - -// Output: -// test diff --git a/_test/selector-scope0.go b/_test/selector-scope0.go index cb9486d8..6575e63f 100644 --- a/_test/selector-scope0.go +++ b/_test/selector-scope0.go @@ -9,10 +9,20 @@ func test(time string, t time.Time) string { return time } +var zero = time.Time{} + +func test2(time string) time.Time { + return zero +} + func main() { str := test("test", time.Now()) fmt.Println(str) + + str2 := test2("test2") + fmt.Println(str2) } // Output: // test +// 0001-01-01 00:00:00 +0000 UTC diff --git a/interp/type.go b/interp/type.go index b8c4cd4e..544461e8 100644 --- a/interp/type.go +++ b/interp/type.go @@ -777,28 +777,17 @@ func nodeType2(interp *Interpreter, sc *scope, n *node, seen map[*node]bool) (t // Resolve the left part of selector, then lookup the right part on it var lt *itype - // If we are in a list of func parameters, and we are a selector on a binPkgT, but - // one of the other parameters has the same name as the pkg name, in the list of - // symbols we would find the other parameter instead of the pkg because it comes - // first when looking up in the stack of scopes. So in that case we force the - // lookup directly in the root scope to shortcircuit that issue. - var localScope *scope - localScope = sc - if n.anc != nil && len(n.anc.child) > 1 && n.anc.child[1] == n && - // This check is weaker than what we actually want to know, i.e. whether - // n.anc.child[0] is a variable, but it seems at this point in the run we have no - // way of knowing that yet (typ is nil, so there's no typ.cat yet). - n.anc.child[0].kind == identExpr { - for { - if localScope.level == 0 { - break - } - localScope = localScope.anc - } + // Lookup the package symbol first if we are in a field expression as + // a previous parameter has the same name as the package, we need to + // prioritize the package type. + if n.anc.kind == fieldExpr { + lt = findPackageType(interp, sc, n.child[0]) } - - if lt, err = nodeType2(interp, localScope, n.child[0], seen); err != nil { - return nil, err + if lt == nil { + // No package was found or we are not in a field expression, we are looking for a variable. + if lt, err = nodeType2(interp, sc, n.child[0], seen); err != nil { + return nil, err + } } if lt.incomplete { @@ -927,6 +916,24 @@ func nodeType2(interp *Interpreter, sc *scope, n *node, seen map[*node]bool) (t return t, err } +// findPackageType searches the top level scope for a package type. +func findPackageType(interp *Interpreter, sc *scope, n *node) *itype { + // Find the root scope, the package symbols will exist there. + for { + if sc.level == 0 { + break + } + sc = sc.anc + } + + baseName := filepath.Base(interp.fset.Position(n.pos).Filename) + sym, _, found := sc.lookup(filepath.Join(n.ident, baseName)) + if !found || sym.typ == nil && sym.typ.cat != srcPkgT && sym.typ.cat != binPkgT { + return nil + } + return sym.typ +} + func isBuiltinCall(n *node, sc *scope) bool { if n.kind != callExpr { return false