]> Cypherpunks repositories - gostls13.git/commitdiff
go/types: expose types.IsIdentical, the Type equivalence relation.
authorAlan Donovan <adonovan@google.com>
Thu, 24 Jan 2013 19:22:17 +0000 (14:22 -0500)
committerAlan Donovan <adonovan@google.com>
Thu, 24 Jan 2013 19:22:17 +0000 (14:22 -0500)
This function is absolutely critical for clients such as
exp/ssa, and too complex for clients to duplicate.

As with CL 7200046, gri expressed in the doc below [gophers
only] before going on leave that he intended to expose such a
predicate, though his wording suggests as an interface method
of Type rather than a standalone function.  (My preference is
for binary methods to be standalone; see "On Binary Methods",
Kim Bruce, 1995).  In any case if he wishes to move it that's
easily accommodated by clients.

https://docs.google.com/a/google.com/document/d/1-DQ4fxlMDs9cYtnkKhAAehX6MArjOQyJsRXp-6kiJLA/edit#heading=h.k3bwja7xony9

R=iant, gri, iant
CC=golang-dev
https://golang.org/cl/7203051

src/pkg/go/types/builtins.go
src/pkg/go/types/conversions.go
src/pkg/go/types/expr.go
src/pkg/go/types/operand.go
src/pkg/go/types/predicates.go

index 3875a3cac91302d33e467fc97389d15a37887b23..867f1e9c6de0545f581dd81830c2cb1974db5907 100644 (file)
@@ -142,7 +142,7 @@ func (check *checker) builtin(x *operand, call *ast.CallExpr, bin *builtin, iota
                        goto Error
                }
 
-               if !isIdentical(x.typ, y.typ) {
+               if !IsIdentical(x.typ, y.typ) {
                        check.invalidArg(x.pos(), "mismatched types %s and %s", x.typ, y.typ)
                        goto Error
                }
@@ -191,7 +191,7 @@ func (check *checker) builtin(x *operand, call *ast.CallExpr, bin *builtin, iota
                        goto Error
                }
 
-               if !isIdentical(dst, src) {
+               if !IsIdentical(dst, src) {
                        check.invalidArg(x.pos(), "arguments to copy %s and %s have different element types %s and %s", x, &y, dst, src)
                        goto Error
                }
index 0c7c9f706dd921257c4764c72d0dca925576291f..65359f319d1ed9edf6944e8b48dd830659518313 100644 (file)
@@ -58,14 +58,14 @@ func (x *operand) isConvertible(T Type) bool {
        V := x.typ
        Vu := underlying(V)
        Tu := underlying(T)
-       if isIdentical(Vu, Tu) {
+       if IsIdentical(Vu, Tu) {
                return true
        }
 
        // "x's type and T are unnamed pointer types and their pointer base types have identical underlying types"
        if V, ok := V.(*Pointer); ok {
                if T, ok := T.(*Pointer); ok {
-                       if isIdentical(underlying(V.Base), underlying(T.Base)) {
+                       if IsIdentical(underlying(V.Base), underlying(T.Base)) {
                                return true
                        }
                }
index f475cacc5a0d3ef89728effe687a7c0d123ae01a..696a0cae684e6c70cb035a8b103dfa8f3a96724a 100644 (file)
@@ -444,7 +444,7 @@ func (check *checker) binary(x, y *operand, op token.Token, hint Type) {
                return
        }
 
-       if !isIdentical(x.typ, y.typ) {
+       if !IsIdentical(x.typ, y.typ) {
                check.invalidOp(x.pos(), "mismatched types %s and %s", x.typ, y.typ)
                x.mode = invalid
                return
index ee6ae0c5228ea72b35313f6496ac1bb84b73b042..6c2281027c3aaed0853500d49f37d3584dc0faac 100644 (file)
@@ -137,7 +137,7 @@ func (x *operand) isAssignable(T Type) bool {
        V := x.typ
 
        // x's type is identical to T
-       if isIdentical(V, T) {
+       if IsIdentical(V, T) {
                return true
        }
 
@@ -146,7 +146,7 @@ func (x *operand) isAssignable(T Type) bool {
 
        // 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) {
+       if IsIdentical(Vu, Tu) {
                return !isNamed(V) || !isNamed(T)
        }
 
@@ -161,7 +161,7 @@ func (x *operand) isAssignable(T Type) bool {
        // type, x's type V and T have identical element types,
        // and at least one of V or T is not a named type
        if Vc, ok := Vu.(*Chan); ok && Vc.Dir == ast.SEND|ast.RECV {
-               if Tc, ok := Tu.(*Chan); ok && isIdentical(Vc.Elt, Tc.Elt) {
+               if Tc, ok := Tu.(*Chan); ok && IsIdentical(Vc.Elt, Tc.Elt) {
                        return !isNamed(V) || !isNamed(T)
                }
        }
index 21781ea9792ec6a34ff9b0f0142cf884022ce590..3468da5a5761fc7e6426030956f7b051cf397229 100644 (file)
@@ -92,8 +92,8 @@ func hasNil(typ Type) bool {
        return false
 }
 
-// identical returns true if x and y are identical.
-func isIdentical(x, y Type) bool {
+// IsIdentical returns true if x and y are identical.
+func IsIdentical(x, y Type) bool {
        if x == y {
                return true
        }
@@ -111,13 +111,13 @@ func isIdentical(x, y Type) bool {
                // Two array types are identical if they have identical element types
                // and the same array length.
                if y, ok := y.(*Array); ok {
-                       return x.Len == y.Len && isIdentical(x.Elt, y.Elt)
+                       return x.Len == y.Len && IsIdentical(x.Elt, y.Elt)
                }
 
        case *Slice:
                // Two slice types are identical if they have identical element types.
                if y, ok := y.(*Slice); ok {
-                       return isIdentical(x.Elt, y.Elt)
+                       return IsIdentical(x.Elt, y.Elt)
                }
 
        case *Struct:
@@ -130,7 +130,7 @@ func isIdentical(x, y Type) bool {
                                for i, f := range x.Fields {
                                        g := y.Fields[i]
                                        if !f.QualifiedName.IsSame(g.QualifiedName) ||
-                                               !isIdentical(f.Type, g.Type) ||
+                                               !IsIdentical(f.Type, g.Type) ||
                                                f.Tag != g.Tag ||
                                                f.IsAnonymous != g.IsAnonymous {
                                                return false
@@ -143,7 +143,7 @@ func isIdentical(x, y Type) bool {
        case *Pointer:
                // Two pointer types are identical if they have identical base types.
                if y, ok := y.(*Pointer); ok {
-                       return isIdentical(x.Base, y.Base)
+                       return IsIdentical(x.Base, y.Base)
                }
 
        case *Signature:
@@ -168,14 +168,14 @@ func isIdentical(x, y Type) bool {
        case *Map:
                // Two map types are identical if they have identical key and value types.
                if y, ok := y.(*Map); ok {
-                       return isIdentical(x.Key, y.Key) && isIdentical(x.Elt, y.Elt)
+                       return IsIdentical(x.Key, y.Key) && IsIdentical(x.Elt, y.Elt)
                }
 
        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 && isIdentical(x.Elt, y.Elt)
+                       return x.Dir == y.Dir && IsIdentical(x.Elt, y.Elt)
                }
 
        case *NamedType:
@@ -197,7 +197,7 @@ func identicalTypes(a, b []*Var) bool {
        }
        for i, x := range a {
                y := b[i]
-               if !isIdentical(x.Type, y.Type) {
+               if !IsIdentical(x.Type, y.Type) {
                        return false
                }
        }
@@ -217,7 +217,7 @@ func identicalMethods(a, b []*Method) bool {
                m[x.QualifiedName] = x
        }
        for _, y := range b {
-               if x := m[y.QualifiedName]; x == nil || !isIdentical(x.Type, y.Type) {
+               if x := m[y.QualifiedName]; x == nil || !IsIdentical(x.Type, y.Type) {
                        return false
                }
        }
@@ -282,7 +282,7 @@ func missingMethod(typ Type, T *Interface) (method *Method, wrongType bool) {
        if ityp, _ := underlying(typ).(*Interface); ityp != nil {
                for _, m := range T.Methods {
                        mode, sig := lookupField(ityp, m.QualifiedName) // TODO(gri) no need to go via lookupField
-                       if mode != invalid && !isIdentical(sig, m.Type) {
+                       if mode != invalid && !IsIdentical(sig, m.Type) {
                                return m, true
                        }
                }
@@ -295,7 +295,7 @@ func missingMethod(typ Type, T *Interface) (method *Method, wrongType bool) {
                if mode == invalid {
                        return m, false
                }
-               if !isIdentical(sig, m.Type) {
+               if !IsIdentical(sig, m.Type) {
                        return m, true
                }
        }