80 lines
1.8 KiB
Go
80 lines
1.8 KiB
Go
|
package unused
|
||
|
|
||
|
import "go/types"
|
||
|
|
||
|
// lookupMethod returns the index of and method with matching package and name, or (-1, nil).
|
||
|
func lookupMethod(T *types.Interface, pkg *types.Package, name string) (int, *types.Func) {
|
||
|
if name != "_" {
|
||
|
for i := 0; i < T.NumMethods(); i++ {
|
||
|
m := T.Method(i)
|
||
|
if sameId(m, pkg, name) {
|
||
|
return i, m
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
return -1, nil
|
||
|
}
|
||
|
|
||
|
func sameId(obj types.Object, pkg *types.Package, name string) bool {
|
||
|
// spec:
|
||
|
// "Two identifiers are different if they are spelled differently,
|
||
|
// or if they appear in different packages and are not exported.
|
||
|
// Otherwise, they are the same."
|
||
|
if name != obj.Name() {
|
||
|
return false
|
||
|
}
|
||
|
// obj.Name == name
|
||
|
if obj.Exported() {
|
||
|
return true
|
||
|
}
|
||
|
// not exported, so packages must be the same (pkg == nil for
|
||
|
// fields in Universe scope; this can only happen for types
|
||
|
// introduced via Eval)
|
||
|
if pkg == nil || obj.Pkg() == nil {
|
||
|
return pkg == obj.Pkg()
|
||
|
}
|
||
|
// pkg != nil && obj.pkg != nil
|
||
|
return pkg.Path() == obj.Pkg().Path()
|
||
|
}
|
||
|
|
||
|
func (c *Checker) implements(V types.Type, T *types.Interface) bool {
|
||
|
// fast path for common case
|
||
|
if T.Empty() {
|
||
|
return true
|
||
|
}
|
||
|
|
||
|
if ityp, _ := V.Underlying().(*types.Interface); ityp != nil {
|
||
|
for i := 0; i < T.NumMethods(); i++ {
|
||
|
m := T.Method(i)
|
||
|
_, obj := lookupMethod(ityp, m.Pkg(), m.Name())
|
||
|
switch {
|
||
|
case obj == nil:
|
||
|
return false
|
||
|
case !types.Identical(obj.Type(), m.Type()):
|
||
|
return false
|
||
|
}
|
||
|
}
|
||
|
return true
|
||
|
}
|
||
|
|
||
|
// A concrete type implements T if it implements all methods of T.
|
||
|
ms := c.msCache.MethodSet(V)
|
||
|
for i := 0; i < T.NumMethods(); i++ {
|
||
|
m := T.Method(i)
|
||
|
sel := ms.Lookup(m.Pkg(), m.Name())
|
||
|
if sel == nil {
|
||
|
return false
|
||
|
}
|
||
|
|
||
|
f, _ := sel.Obj().(*types.Func)
|
||
|
if f == nil {
|
||
|
return false
|
||
|
}
|
||
|
|
||
|
if !types.Identical(f.Type(), m.Type()) {
|
||
|
return false
|
||
|
}
|
||
|
}
|
||
|
return true
|
||
|
}
|