From 63f3103b6fa5e5a7062c252e2e07e8de55b0e11d Mon Sep 17 00:00:00 2001 From: Robert Griesemer Date: Mon, 10 Jun 2013 16:42:22 -0700 Subject: [PATCH] go.tools/go/types: call Context.Ident for selectors Fixes golang/go#5669. R=adonovan CC=golang-dev https://golang.org/cl/9714045 --- go/types/api.go | 6 +++--- go/types/expr.go | 5 +++-- go/types/operand.go | 20 ++++++++++---------- go/types/predicates.go | 4 ++-- go/types/resolver_test.go | 2 ++ 5 files changed, 20 insertions(+), 17 deletions(-) diff --git a/go/types/api.go b/go/types/api.go index 3a0f0953210..357c541c715 100644 --- a/go/types/api.go +++ b/go/types/api.go @@ -64,9 +64,9 @@ type Context struct { // filename:line:column: message Error func(err error) - // If Ident != nil, it is called for each identifier id in the AST - // (including package names, dots "." of dot-imports, and blank "_" - // identifiers), and obj is the object denoted by ident. The object + // If Ident != nil, it is called for each identifier id that is type- + // checked (including package names, dots "." of dot-imports, and blank + // "_" identifiers), and obj is the object denoted by ident. The object // is nil if the identifier was not declared. Ident may be called // multiple times for the same identifier (e.g., for typed variable // declarations with multiple initialization statements); but Ident diff --git a/go/types/expr.go b/go/types/expr.go index aa3af52af75..38bbc4bb15f 100644 --- a/go/types/expr.go +++ b/go/types/expr.go @@ -1328,9 +1328,10 @@ func (check *checker) rawExpr(x *operand, e ast.Expr, hint Type, iota int, cycle check.invalidOp(e.Pos(), "%s has no single field or method %s", x, sel) goto Error } + check.callIdent(e.Sel, res.obj) if x.mode == typexpr { // method expression - sig, ok := res.typ.(*Signature) + sig, ok := res.obj.Type().(*Signature) if !ok { check.invalidOp(e.Pos(), "%s has no method %s", x, sel) goto Error @@ -1352,7 +1353,7 @@ func (check *checker) rawExpr(x *operand, e ast.Expr, hint Type, iota int, cycle } else { // regular selector x.mode = res.mode - x.typ = res.typ + x.typ = res.obj.Type() } case *ast.IndexExpr: diff --git a/go/types/operand.go b/go/types/operand.go index fd755f868ae..d001daba012 100644 --- a/go/types/operand.go +++ b/go/types/operand.go @@ -209,8 +209,8 @@ func (x *operand) isInteger() bool { // lookupResult represents the result of a struct field/method lookup. type lookupResult struct { mode operandMode - typ Type - index []int // field index sequence; nil for methods + obj Object // *Field or *Func; valid if mode != invalid + index []int // field index sequence; nil for methods } type embeddedType struct { @@ -232,7 +232,7 @@ func lookupFieldBreadthFirst(list []embeddedType, pkg *Package, name string) (re var next []embeddedType // potentialMatch is invoked every time a match is found. - potentialMatch := func(multiples bool, mode operandMode, typ Type) bool { + potentialMatch := func(multiples bool, mode operandMode, obj Object) bool { if multiples || res.mode != invalid { // name appeared already at this level - annihilate res.mode = invalid @@ -240,7 +240,7 @@ func lookupFieldBreadthFirst(list []embeddedType, pkg *Package, name string) (re } // first appearance of name res.mode = mode - res.typ = typ + res.obj = obj res.index = nil return true } @@ -267,7 +267,7 @@ func lookupFieldBreadthFirst(list []embeddedType, pkg *Package, name string) (re if obj := typ.methods.Lookup(pkg, name); obj != nil { m := obj.(*Func) assert(m.typ != nil) - if !potentialMatch(e.multiples, value, m.typ) { + if !potentialMatch(e.multiples, value, m) { return // name collision } } @@ -282,7 +282,7 @@ func lookupFieldBreadthFirst(list []embeddedType, pkg *Package, name string) (re f := obj.(*Field) if f.isMatch(pkg, name) { assert(f.typ != nil) - if !potentialMatch(e.multiples, variable, f.typ) { + if !potentialMatch(e.multiples, variable, f) { return // name collision } var index []int @@ -317,7 +317,7 @@ func lookupFieldBreadthFirst(list []embeddedType, pkg *Package, name string) (re if obj := t.methods.Lookup(pkg, name); obj != nil { m := obj.(*Func) assert(m.typ != nil) - if !potentialMatch(e.multiples, value, m.typ) { + if !potentialMatch(e.multiples, value, m) { return // name collision } } @@ -367,7 +367,7 @@ func lookupField(typ Type, pkg *Package, name string) lookupResult { if obj := t.methods.Lookup(pkg, name); obj != nil { m := obj.(*Func) assert(m.typ != nil) - return lookupResult{value, m.typ, nil} + return lookupResult{value, m, nil} } typ = t.underlying } @@ -381,7 +381,7 @@ func lookupField(typ Type, pkg *Package, name string) lookupResult { for i, obj := range t.fields.entries { f := obj.(*Field) if f.isMatch(pkg, name) { - return lookupResult{variable, f.typ, []int{i}} + return lookupResult{variable, f, []int{i}} } if f.anonymous { // Possible optimization: If the embedded type @@ -402,7 +402,7 @@ func lookupField(typ Type, pkg *Package, name string) lookupResult { if obj := t.methods.Lookup(pkg, name); obj != nil { m := obj.(*Func) assert(m.typ != nil) - return lookupResult{value, m.typ, nil} + return lookupResult{value, m, nil} } } diff --git a/go/types/predicates.go b/go/types/predicates.go index 0ab836b4732..c4bdf2f0df8 100644 --- a/go/types/predicates.go +++ b/go/types/predicates.go @@ -289,7 +289,7 @@ func missingMethod(typ Type, T *Interface) (method *Func, wrongType bool) { for _, obj := range T.methods.entries { m := obj.(*Func) res := lookupField(ityp, m.pkg, m.name) // TODO(gri) no need to go via lookupField - if res.mode != invalid && !IsIdentical(res.typ, m.typ) { + if res.mode != invalid && !IsIdentical(res.obj.Type(), m.typ) { return m, true } } @@ -303,7 +303,7 @@ func missingMethod(typ Type, T *Interface) (method *Func, wrongType bool) { if res.mode == invalid { return m, false } - if !IsIdentical(res.typ, m.typ) { + if !IsIdentical(res.obj.Type(), m.typ) { return m, true } } diff --git a/go/types/resolver_test.go b/go/types/resolver_test.go index 53e6fdb87c1..7996014d3ef 100644 --- a/go/types/resolver_test.go +++ b/go/types/resolver_test.go @@ -43,6 +43,8 @@ var sources = []string{ type I interface{ m() } var _ = T{a: 1, b: 2, c: 3} func (_ T) m() {} + var i I + var _ = i.m `, }