1
0
mirror of https://github.com/golang/go synced 2024-10-01 01:28:32 -06:00

go.tools/go/types: call Context.Ident for selectors

Fixes golang/go#5669.

R=adonovan
CC=golang-dev
https://golang.org/cl/9714045
This commit is contained in:
Robert Griesemer 2013-06-10 16:42:22 -07:00
parent 73612ddbfd
commit 63f3103b6f
5 changed files with 20 additions and 17 deletions

View File

@ -64,9 +64,9 @@ type Context struct {
// filename:line:column: message // filename:line:column: message
Error func(err error) Error func(err error)
// If Ident != nil, it is called for each identifier id in the AST // If Ident != nil, it is called for each identifier id that is type-
// (including package names, dots "." of dot-imports, and blank "_" // checked (including package names, dots "." of dot-imports, and blank
// identifiers), and obj is the object denoted by ident. The object // "_" identifiers), and obj is the object denoted by ident. The object
// is nil if the identifier was not declared. Ident may be called // is nil if the identifier was not declared. Ident may be called
// multiple times for the same identifier (e.g., for typed variable // multiple times for the same identifier (e.g., for typed variable
// declarations with multiple initialization statements); but Ident // declarations with multiple initialization statements); but Ident

View File

@ -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) check.invalidOp(e.Pos(), "%s has no single field or method %s", x, sel)
goto Error goto Error
} }
check.callIdent(e.Sel, res.obj)
if x.mode == typexpr { if x.mode == typexpr {
// method expression // method expression
sig, ok := res.typ.(*Signature) sig, ok := res.obj.Type().(*Signature)
if !ok { if !ok {
check.invalidOp(e.Pos(), "%s has no method %s", x, sel) check.invalidOp(e.Pos(), "%s has no method %s", x, sel)
goto Error goto Error
@ -1352,7 +1353,7 @@ func (check *checker) rawExpr(x *operand, e ast.Expr, hint Type, iota int, cycle
} else { } else {
// regular selector // regular selector
x.mode = res.mode x.mode = res.mode
x.typ = res.typ x.typ = res.obj.Type()
} }
case *ast.IndexExpr: case *ast.IndexExpr:

View File

@ -209,8 +209,8 @@ func (x *operand) isInteger() bool {
// lookupResult represents the result of a struct field/method lookup. // lookupResult represents the result of a struct field/method lookup.
type lookupResult struct { type lookupResult struct {
mode operandMode mode operandMode
typ Type obj Object // *Field or *Func; valid if mode != invalid
index []int // field index sequence; nil for methods index []int // field index sequence; nil for methods
} }
type embeddedType struct { type embeddedType struct {
@ -232,7 +232,7 @@ func lookupFieldBreadthFirst(list []embeddedType, pkg *Package, name string) (re
var next []embeddedType var next []embeddedType
// potentialMatch is invoked every time a match is found. // 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 { if multiples || res.mode != invalid {
// name appeared already at this level - annihilate // name appeared already at this level - annihilate
res.mode = invalid res.mode = invalid
@ -240,7 +240,7 @@ func lookupFieldBreadthFirst(list []embeddedType, pkg *Package, name string) (re
} }
// first appearance of name // first appearance of name
res.mode = mode res.mode = mode
res.typ = typ res.obj = obj
res.index = nil res.index = nil
return true return true
} }
@ -267,7 +267,7 @@ func lookupFieldBreadthFirst(list []embeddedType, pkg *Package, name string) (re
if obj := typ.methods.Lookup(pkg, name); obj != nil { if obj := typ.methods.Lookup(pkg, name); obj != nil {
m := obj.(*Func) m := obj.(*Func)
assert(m.typ != nil) assert(m.typ != nil)
if !potentialMatch(e.multiples, value, m.typ) { if !potentialMatch(e.multiples, value, m) {
return // name collision return // name collision
} }
} }
@ -282,7 +282,7 @@ func lookupFieldBreadthFirst(list []embeddedType, pkg *Package, name string) (re
f := obj.(*Field) f := obj.(*Field)
if f.isMatch(pkg, name) { if f.isMatch(pkg, name) {
assert(f.typ != nil) assert(f.typ != nil)
if !potentialMatch(e.multiples, variable, f.typ) { if !potentialMatch(e.multiples, variable, f) {
return // name collision return // name collision
} }
var index []int 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 { if obj := t.methods.Lookup(pkg, name); obj != nil {
m := obj.(*Func) m := obj.(*Func)
assert(m.typ != nil) assert(m.typ != nil)
if !potentialMatch(e.multiples, value, m.typ) { if !potentialMatch(e.multiples, value, m) {
return // name collision 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 { if obj := t.methods.Lookup(pkg, name); obj != nil {
m := obj.(*Func) m := obj.(*Func)
assert(m.typ != nil) assert(m.typ != nil)
return lookupResult{value, m.typ, nil} return lookupResult{value, m, nil}
} }
typ = t.underlying typ = t.underlying
} }
@ -381,7 +381,7 @@ func lookupField(typ Type, pkg *Package, name string) lookupResult {
for i, obj := range t.fields.entries { for i, obj := range t.fields.entries {
f := obj.(*Field) f := obj.(*Field)
if f.isMatch(pkg, name) { if f.isMatch(pkg, name) {
return lookupResult{variable, f.typ, []int{i}} return lookupResult{variable, f, []int{i}}
} }
if f.anonymous { if f.anonymous {
// Possible optimization: If the embedded type // 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 { if obj := t.methods.Lookup(pkg, name); obj != nil {
m := obj.(*Func) m := obj.(*Func)
assert(m.typ != nil) assert(m.typ != nil)
return lookupResult{value, m.typ, nil} return lookupResult{value, m, nil}
} }
} }

View File

@ -289,7 +289,7 @@ func missingMethod(typ Type, T *Interface) (method *Func, wrongType bool) {
for _, obj := range T.methods.entries { for _, obj := range T.methods.entries {
m := obj.(*Func) m := obj.(*Func)
res := lookupField(ityp, m.pkg, m.name) // TODO(gri) no need to go via lookupField 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 return m, true
} }
} }
@ -303,7 +303,7 @@ func missingMethod(typ Type, T *Interface) (method *Func, wrongType bool) {
if res.mode == invalid { if res.mode == invalid {
return m, false return m, false
} }
if !IsIdentical(res.typ, m.typ) { if !IsIdentical(res.obj.Type(), m.typ) {
return m, true return m, true
} }
} }

View File

@ -43,6 +43,8 @@ var sources = []string{
type I interface{ m() } type I interface{ m() }
var _ = T{a: 1, b: 2, c: 3} var _ = T{a: 1, b: 2, c: 3}
func (_ T) m() {} func (_ T) m() {}
var i I
var _ = i.m
`, `,
} }