in apidiff/correspondence.go [28:132]
func (d *differ) corr(old, new types.Type, p *ifacePair) bool {
// Structure copied from types.Identical.
switch old := old.(type) {
case *types.Basic:
return types.Identical(old, new)
case *types.Array:
if new, ok := new.(*types.Array); ok {
return d.corr(old.Elem(), new.Elem(), p) && old.Len() == new.Len()
}
case *types.Slice:
if new, ok := new.(*types.Slice); ok {
return d.corr(old.Elem(), new.Elem(), p)
}
case *types.Map:
if new, ok := new.(*types.Map); ok {
return d.corr(old.Key(), new.Key(), p) && d.corr(old.Elem(), new.Elem(), p)
}
case *types.Chan:
if new, ok := new.(*types.Chan); ok {
return d.corr(old.Elem(), new.Elem(), p) && old.Dir() == new.Dir()
}
case *types.Pointer:
if new, ok := new.(*types.Pointer); ok {
return d.corr(old.Elem(), new.Elem(), p)
}
case *types.Signature:
if new, ok := new.(*types.Signature); ok {
pe := d.corr(old.Params(), new.Params(), p)
re := d.corr(old.Results(), new.Results(), p)
return old.Variadic() == new.Variadic() && pe && re
}
case *types.Tuple:
if new, ok := new.(*types.Tuple); ok {
for i := 0; i < old.Len(); i++ {
if i >= new.Len() || !d.corr(old.At(i).Type(), new.At(i).Type(), p) {
return false
}
}
return old.Len() == new.Len()
}
case *types.Struct:
if new, ok := new.(*types.Struct); ok {
for i := 0; i < old.NumFields(); i++ {
if i >= new.NumFields() {
return false
}
of := old.Field(i)
nf := new.Field(i)
if of.Anonymous() != nf.Anonymous() ||
old.Tag(i) != new.Tag(i) ||
!d.corr(of.Type(), nf.Type(), p) ||
!d.corrFieldNames(of, nf) {
return false
}
}
return old.NumFields() == new.NumFields()
}
case *types.Interface:
if new, ok := new.(*types.Interface); ok {
// Deal with circularity. See the comment in types.Identical.
q := &ifacePair{old, new, p}
for p != nil {
if p.identical(q) {
return true // same pair was compared before
}
p = p.prev
}
oldms := d.sortedMethods(old)
newms := d.sortedMethods(new)
for i, om := range oldms {
if i >= len(newms) {
return false
}
nm := newms[i]
if d.methodID(om) != d.methodID(nm) || !d.corr(om.Type(), nm.Type(), q) {
return false
}
}
return old.NumMethods() == new.NumMethods()
}
case *types.Named:
if new, ok := new.(*types.Named); ok {
return d.establishCorrespondence(old, new)
}
if new, ok := new.(*types.Basic); ok {
// Basic types are defined types, too, so we have to support them.
return d.establishCorrespondence(old, new)
}
default:
panic("unknown type kind")
}
return false
}