1
0
mirror of https://github.com/golang/go synced 2024-09-30 22:48: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
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

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)
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:

View File

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

View File

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

View File

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