go.tools/go/types: fix isAssignable and IsIdentical
- Imported objects that are explicitly exported may have a nil package; don't use it for qualified name computation (it's not needed). - isAssignable must check all possibilities before declaring failure. Fixes golang/go#5675. R=adonovan CC=golang-dev https://golang.org/cl/10141044
This commit is contained in:
parent
63f3103b6f
commit
0d2f7d411b
|
|
@ -139,19 +139,20 @@ func (x *operand) isAssignable(ctxt *Context, T Type) bool {
|
||||||
Vu := V.Underlying()
|
Vu := V.Underlying()
|
||||||
Tu := T.Underlying()
|
Tu := T.Underlying()
|
||||||
|
|
||||||
// x's type V and T have identical underlying types
|
|
||||||
// and at least one of V or T is not a named type
|
|
||||||
if IsIdentical(Vu, Tu) {
|
|
||||||
return !isNamed(V) || !isNamed(T)
|
|
||||||
}
|
|
||||||
|
|
||||||
// T is an interface type and x implements T
|
// T is an interface type and x implements T
|
||||||
|
// (Do this check first as it might succeed early.)
|
||||||
if Ti, ok := Tu.(*Interface); ok {
|
if Ti, ok := Tu.(*Interface); ok {
|
||||||
if m, _ := missingMethod(x.typ, Ti); m == nil {
|
if m, _ := missingMethod(x.typ, Ti); m == nil {
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// x's type V and T have identical underlying types
|
||||||
|
// and at least one of V or T is not a named type
|
||||||
|
if IsIdentical(Vu, Tu) && (!isNamed(V) || !isNamed(T)) {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
// x is a bidirectional channel value, T is a channel
|
// x is a bidirectional channel value, T is a channel
|
||||||
// type, x's type V and T have identical element types,
|
// type, x's type V and T have identical element types,
|
||||||
// and at least one of V or T is not a named type
|
// and at least one of V or T is not a named type
|
||||||
|
|
|
||||||
|
|
@ -6,6 +6,8 @@
|
||||||
|
|
||||||
package types
|
package types
|
||||||
|
|
||||||
|
import "go/ast"
|
||||||
|
|
||||||
func isNamed(typ Type) bool {
|
func isNamed(typ Type) bool {
|
||||||
if _, ok := typ.(*Basic); ok {
|
if _, ok := typ.(*Basic); ok {
|
||||||
return ok
|
return ok
|
||||||
|
|
@ -211,6 +213,19 @@ func identicalTypes(a, b *Tuple) bool {
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// qname computes the "qualified name" of a function.
|
||||||
|
// TODO(gri) This is similar in functionality to Field.isMatch.
|
||||||
|
// Try to consolidate.
|
||||||
|
func qname(f *Func) string {
|
||||||
|
if ast.IsExported(f.name) {
|
||||||
|
return f.name
|
||||||
|
}
|
||||||
|
if f.pkg == nil {
|
||||||
|
panic("unexported function without package information")
|
||||||
|
}
|
||||||
|
return f.pkg.path + "." + f.name
|
||||||
|
}
|
||||||
|
|
||||||
// identicalMethods returns true if both object sets a and b have the
|
// identicalMethods returns true if both object sets a and b have the
|
||||||
// same length and corresponding methods have identical types.
|
// same length and corresponding methods have identical types.
|
||||||
// TODO(gri) make this more efficient (e.g., sort them on completion)
|
// TODO(gri) make this more efficient (e.g., sort them on completion)
|
||||||
|
|
@ -226,14 +241,15 @@ func identicalMethods(a, b *Scope) bool {
|
||||||
m := make(map[string]*Func)
|
m := make(map[string]*Func)
|
||||||
for _, obj := range a.entries {
|
for _, obj := range a.entries {
|
||||||
x := obj.(*Func)
|
x := obj.(*Func)
|
||||||
qname := x.pkg.path + "." + x.name
|
k := qname(x)
|
||||||
assert(m[qname] == nil) // method list must not have duplicate entries
|
assert(m[k] == nil) // method list must not have duplicate entries
|
||||||
m[qname] = x
|
m[k] = x
|
||||||
}
|
}
|
||||||
|
|
||||||
for _, obj := range b.entries {
|
for _, obj := range b.entries {
|
||||||
y := obj.(*Func)
|
y := obj.(*Func)
|
||||||
qname := y.pkg.path + "." + y.name
|
k := qname(y)
|
||||||
if x := m[qname]; x == nil || !IsIdentical(x.typ, y.typ) {
|
if x := m[k]; x == nil || !IsIdentical(x.typ, y.typ) {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue