// Identical reports whether x and y are identical types.
// Receivers of Signature types are ignored.
func Identical(x, y Type) bool {
- return identical(x, y, true, nil)
+ var c comparer
+ return c.identical(x, y, nil)
}
// IdenticalIgnoreTags reports whether x and y are identical types if tags are ignored.
// Receivers of Signature types are ignored.
func IdenticalIgnoreTags(x, y Type) bool {
- return identical(x, y, false, nil)
+ var c comparer
+ c.ignoreTags = true
+ return c.identical(x, y, nil)
}
return p.x == q.x && p.y == q.y || p.x == q.y && p.y == q.x
}
+// A comparer is used to compare types.
+type comparer struct {
+ ignoreTags bool // if set, identical ignores struct tags
+}
+
// For changes to this code the corresponding changes should be made to unifier.nify.
-func identical(x, y Type, cmpTags bool, p *ifacePair) bool {
+func (c *comparer) identical(x, y Type, p *ifacePair) bool {
if x == y {
return true
}
if y, ok := y.(*Array); ok {
// If one or both array lengths are unknown (< 0) due to some error,
// assume they are the same to avoid spurious follow-on errors.
- return (x.len < 0 || y.len < 0 || x.len == y.len) && identical(x.elem, y.elem, cmpTags, p)
+ return (x.len < 0 || y.len < 0 || x.len == y.len) && c.identical(x.elem, y.elem, p)
}
case *Slice:
// Two slice types are identical if they have identical element types.
if y, ok := y.(*Slice); ok {
- return identical(x.elem, y.elem, cmpTags, p)
+ return c.identical(x.elem, y.elem, p)
}
case *Struct:
for i, f := range x.fields {
g := y.fields[i]
if f.embedded != g.embedded ||
- cmpTags && x.Tag(i) != y.Tag(i) ||
+ !c.ignoreTags && x.Tag(i) != y.Tag(i) ||
!f.sameId(g.pkg, g.name) ||
- !identical(f.typ, g.typ, cmpTags, p) {
+ !c.identical(f.typ, g.typ, p) {
return false
}
}
case *Pointer:
// Two pointer types are identical if they have identical base types.
if y, ok := y.(*Pointer); ok {
- return identical(x.base, y.base, cmpTags, p)
+ return c.identical(x.base, y.base, p)
}
case *Tuple:
if x != nil {
for i, v := range x.vars {
w := y.vars[i]
- if !identical(v.typ, w.typ, cmpTags, p) {
+ if !c.identical(v.typ, w.typ, p) {
return false
}
}
// Constraints must be pair-wise identical, after substitution.
for i, xtparam := range xtparams {
ybound := check.subst(nopos, ytparams[i].bound, smap, nil, ctxt)
- if !identical(xtparam.bound, ybound, cmpTags, p) {
+ if !c.identical(xtparam.bound, ybound, p) {
return false
}
}
}
return x.variadic == y.variadic &&
- identical(x.params, yparams, cmpTags, p) &&
- identical(x.results, yresults, cmpTags, p)
+ c.identical(x.params, yparams, p) &&
+ c.identical(x.results, yresults, p)
case *Union:
if y, _ := y.(*Union); y != nil {
}
for i, f := range a {
g := b[i]
- if f.Id() != g.Id() || !identical(f.typ, g.typ, cmpTags, q) {
+ if f.Id() != g.Id() || !c.identical(f.typ, g.typ, q) {
return false
}
}
case *Map:
// Two map types are identical if they have identical key and value types.
if y, ok := y.(*Map); ok {
- return identical(x.key, y.key, cmpTags, p) && identical(x.elem, y.elem, cmpTags, p)
+ return c.identical(x.key, y.key, p) && c.identical(x.elem, y.elem, p)
}
case *Chan:
// Two channel types are identical if they have identical value types
// and the same direction.
if y, ok := y.(*Chan); ok {
- return x.dir == y.dir && identical(x.elem, y.elem, cmpTags, p)
+ return x.dir == y.dir && c.identical(x.elem, y.elem, p)
}
case *Named:
// Identical reports whether x and y are identical types.
// Receivers of Signature types are ignored.
func Identical(x, y Type) bool {
- return identical(x, y, true, nil)
+ var c comparer
+ return c.identical(x, y, nil)
}
// IdenticalIgnoreTags reports whether x and y are identical types if tags are ignored.
// Receivers of Signature types are ignored.
func IdenticalIgnoreTags(x, y Type) bool {
- return identical(x, y, false, nil)
+ var c comparer
+ c.ignoreTags = true
+ return c.identical(x, y, nil)
}
return p.x == q.x && p.y == q.y || p.x == q.y && p.y == q.x
}
+// A comparer is used to compare types.
+type comparer struct {
+ ignoreTags bool // if set, identical ignores struct tags
+}
+
// For changes to this code the corresponding changes should be made to unifier.nify.
-func identical(x, y Type, cmpTags bool, p *ifacePair) bool {
+func (c *comparer) identical(x, y Type, p *ifacePair) bool {
if x == y {
return true
}
if y, ok := y.(*Array); ok {
// If one or both array lengths are unknown (< 0) due to some error,
// assume they are the same to avoid spurious follow-on errors.
- return (x.len < 0 || y.len < 0 || x.len == y.len) && identical(x.elem, y.elem, cmpTags, p)
+ return (x.len < 0 || y.len < 0 || x.len == y.len) && c.identical(x.elem, y.elem, p)
}
case *Slice:
// Two slice types are identical if they have identical element types.
if y, ok := y.(*Slice); ok {
- return identical(x.elem, y.elem, cmpTags, p)
+ return c.identical(x.elem, y.elem, p)
}
case *Struct:
for i, f := range x.fields {
g := y.fields[i]
if f.embedded != g.embedded ||
- cmpTags && x.Tag(i) != y.Tag(i) ||
+ !c.ignoreTags && x.Tag(i) != y.Tag(i) ||
!f.sameId(g.pkg, g.name) ||
- !identical(f.typ, g.typ, cmpTags, p) {
+ !c.identical(f.typ, g.typ, p) {
return false
}
}
case *Pointer:
// Two pointer types are identical if they have identical base types.
if y, ok := y.(*Pointer); ok {
- return identical(x.base, y.base, cmpTags, p)
+ return c.identical(x.base, y.base, p)
}
case *Tuple:
if x != nil {
for i, v := range x.vars {
w := y.vars[i]
- if !identical(v.typ, w.typ, cmpTags, p) {
+ if !c.identical(v.typ, w.typ, p) {
return false
}
}
// Constraints must be pair-wise identical, after substitution.
for i, xtparam := range xtparams {
ybound := check.subst(nopos, ytparams[i].bound, smap, nil, ctxt)
- if !identical(xtparam.bound, ybound, cmpTags, p) {
+ if !c.identical(xtparam.bound, ybound, p) {
return false
}
}
}
return x.variadic == y.variadic &&
- identical(x.params, yparams, cmpTags, p) &&
- identical(x.results, yresults, cmpTags, p)
+ c.identical(x.params, yparams, p) &&
+ c.identical(x.results, yresults, p)
case *Union:
if y, _ := y.(*Union); y != nil {
}
for i, f := range a {
g := b[i]
- if f.Id() != g.Id() || !identical(f.typ, g.typ, cmpTags, q) {
+ if f.Id() != g.Id() || !c.identical(f.typ, g.typ, q) {
return false
}
}
case *Map:
// Two map types are identical if they have identical key and value types.
if y, ok := y.(*Map); ok {
- return identical(x.key, y.key, cmpTags, p) && identical(x.elem, y.elem, cmpTags, p)
+ return c.identical(x.key, y.key, p) && c.identical(x.elem, y.elem, p)
}
case *Chan:
// Two channel types are identical if they have identical value types
// and the same direction.
if y, ok := y.(*Chan); ok {
- return x.dir == y.dir && identical(x.elem, y.elem, cmpTags, p)
+ return x.dir == y.dir && c.identical(x.elem, y.elem, p)
}
case *Named: