mirror of
https://github.com/golang/go
synced 2024-11-18 20:04:52 -07: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:
parent
73612ddbfd
commit
63f3103b6f
@ -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
|
||||||
|
@ -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:
|
||||||
|
@ -209,7 +209,7 @@ 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
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -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}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -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
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -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
|
||||||
`,
|
`,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user