]> Cypherpunks repositories - gostls13.git/commitdiff
go/types, types2: use a comparer struct to control the identical predicate
authorRobert Griesemer <gri@golang.org>
Thu, 2 Feb 2023 22:16:23 +0000 (14:16 -0800)
committerGopher Robot <gobot@golang.org>
Thu, 2 Feb 2023 23:39:19 +0000 (23:39 +0000)
This makes it easier to configure the behavior of identical: we can
simply add fields to the comparer instead of adding more parameters
to identical.

Change-Id: I9a6f5451b3ee5c37e71486060653c5a6e8f24304
Reviewed-on: https://go-review.googlesource.com/c/go/+/464937
Auto-Submit: Robert Griesemer <gri@google.com>
Reviewed-by: Robert Findley <rfindley@google.com>
Run-TryBot: Robert Griesemer <gri@google.com>
TryBot-Result: Gopher Robot <gobot@golang.org>
Reviewed-by: Robert Griesemer <gri@google.com>
src/cmd/compile/internal/types2/api.go
src/cmd/compile/internal/types2/predicates.go
src/go/types/api.go
src/go/types/predicates.go

index d9e6d5ad40e9749e397e25a8138ca94fa081f766..eebecce0376bf56ee3582532326076ecb8278d8c 100644 (file)
@@ -494,11 +494,14 @@ func Satisfies(V Type, T *Interface) bool {
 // 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)
 }
index acc15490846a9ca7c15bb1cc4247d2baf5cf251d..c30badfe173f07920b809dd18c47a05bdab95492 100644 (file)
@@ -199,8 +199,13 @@ func (p *ifacePair) identical(q *ifacePair) bool {
        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
        }
@@ -220,13 +225,13 @@ func identical(x, y Type, cmpTags bool, p *ifacePair) bool {
                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:
@@ -239,9 +244,9 @@ func identical(x, y Type, cmpTags bool, p *ifacePair) bool {
                                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
                                        }
                                }
@@ -252,7 +257,7 @@ func identical(x, y Type, cmpTags bool, p *ifacePair) bool {
        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:
@@ -263,7 +268,7 @@ func identical(x, y Type, cmpTags bool, p *ifacePair) bool {
                                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
                                                }
                                        }
@@ -311,7 +316,7 @@ func identical(x, y Type, cmpTags bool, p *ifacePair) bool {
                        // 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
                                }
                        }
@@ -321,8 +326,8 @@ func identical(x, y Type, cmpTags bool, p *ifacePair) bool {
                }
 
                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 {
@@ -389,7 +394,7 @@ func identical(x, y Type, cmpTags bool, p *ifacePair) bool {
                                }
                                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
                                        }
                                }
@@ -400,14 +405,14 @@ func identical(x, y Type, cmpTags bool, p *ifacePair) bool {
        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:
index d59e6d9b490f7b6ee6b5917fa3f399970119cca7..ae46ccaabbc6d9e9bc54421688d0fc9973665328 100644 (file)
@@ -480,11 +480,14 @@ func Satisfies(V Type, T *Interface) bool {
 // 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)
 }
index 1927844732e2364ab4b86cd8fb90180333214036..9a156a040c085f9cf71ccb907b6bb9266609dfa3 100644 (file)
@@ -201,8 +201,13 @@ func (p *ifacePair) identical(q *ifacePair) bool {
        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
        }
@@ -222,13 +227,13 @@ func identical(x, y Type, cmpTags bool, p *ifacePair) bool {
                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:
@@ -241,9 +246,9 @@ func identical(x, y Type, cmpTags bool, p *ifacePair) bool {
                                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
                                        }
                                }
@@ -254,7 +259,7 @@ func identical(x, y Type, cmpTags bool, p *ifacePair) bool {
        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:
@@ -265,7 +270,7 @@ func identical(x, y Type, cmpTags bool, p *ifacePair) bool {
                                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
                                                }
                                        }
@@ -313,7 +318,7 @@ func identical(x, y Type, cmpTags bool, p *ifacePair) bool {
                        // 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
                                }
                        }
@@ -323,8 +328,8 @@ func identical(x, y Type, cmpTags bool, p *ifacePair) bool {
                }
 
                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 {
@@ -391,7 +396,7 @@ func identical(x, y Type, cmpTags bool, p *ifacePair) bool {
                                }
                                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
                                        }
                                }
@@ -402,14 +407,14 @@ func identical(x, y Type, cmpTags bool, p *ifacePair) bool {
        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: