]> Cypherpunks repositories - gostls13.git/commitdiff
reflect: add Type.Comparable
authorRuss Cox <rsc@golang.org>
Tue, 16 Sep 2014 21:40:10 +0000 (17:40 -0400)
committerRuss Cox <rsc@golang.org>
Tue, 16 Sep 2014 21:40:10 +0000 (17:40 -0400)
Like most of the Type methods, the definition of Comparable
is what the Go spec says it is.

Fixes #7911.

LGTM=gri
R=gri, r
CC=golang-codereviews
https://golang.org/cl/144020043

src/reflect/all_test.go
src/reflect/type.go

index 688b5d31074061e11de2842b157d1bbd30c10375..4be0e353df7cb7e8b763ee5280e3a9ab2bc72673 100644 (file)
@@ -3185,6 +3185,44 @@ func TestConvert(t *testing.T) {
        }
 }
 
+type ComparableStruct struct {
+       X int
+}
+
+type NonComparableStruct struct {
+       X int
+       Y map[string]int
+}
+
+var comparableTests = []struct {
+       typ Type
+       ok  bool
+}{
+       {TypeOf(1), true},
+       {TypeOf("hello"), true},
+       {TypeOf(new(byte)), true},
+       {TypeOf((func())(nil)), false},
+       {TypeOf([]byte{}), false},
+       {TypeOf(map[string]int{}), false},
+       {TypeOf(make(chan int)), true},
+       {TypeOf(1.5), true},
+       {TypeOf(false), true},
+       {TypeOf(1i), true},
+       {TypeOf(ComparableStruct{}), true},
+       {TypeOf(NonComparableStruct{}), false},
+       {TypeOf([10]map[string]int{}), false},
+       {TypeOf([10]string{}), true},
+       {TypeOf(new(interface{})).Elem(), true},
+}
+
+func TestComparable(t *testing.T) {
+       for _, tt := range comparableTests {
+               if ok := tt.typ.Comparable(); ok != tt.ok {
+                       t.Errorf("TypeOf(%v).Comparable() = %v, want %v", tt.typ, ok, tt.ok)
+               }
+       }
+}
+
 func TestOverflow(t *testing.T) {
        if ovf := V(float64(0)).OverflowFloat(1e300); ovf {
                t.Errorf("%v wrongly overflows float64", 1e300)
index 67818f7f4c8241df88082f3d1a46aa93b56a382d..f099546d270fd80fe39083d7a2e2d5780734f70f 100644 (file)
@@ -96,6 +96,9 @@ type Type interface {
        // ConvertibleTo returns true if a value of the type is convertible to type u.
        ConvertibleTo(u Type) bool
 
+       // Comparable returns true if values of this type are comparable.
+       Comparable() bool
+
        // Methods applicable only to some types, depending on Kind.
        // The methods allowed for each kind are:
        //
@@ -248,7 +251,7 @@ type rtype struct {
        align         uint8             // alignment of variable with this type
        fieldAlign    uint8             // alignment of struct field with this type
        kind          uint8             // enumeration for C
-       alg           *uintptr          // algorithm table (../runtime/runtime.h:/Alg)
+       alg           *typeAlg          // algorithm table (../runtime/runtime.h:/Alg)
        gc            [2]unsafe.Pointer // garbage collection data
        string        *string           // string form; unnecessary but undeniably useful
        *uncommonType                   // (relatively) uncommon fields
@@ -256,6 +259,15 @@ type rtype struct {
        zero          unsafe.Pointer    // pointer to zero value
 }
 
+type typeAlg struct {
+       // function for hashing objects of this type
+       // (ptr to object, size, seed) -> hash
+       hash func(unsafe.Pointer, uintptr, uintptr) uintptr
+       // function for comparing objects of this type
+       // (ptr to object A, ptr to object B, size) -> ==?
+       equal func(unsafe.Pointer, unsafe.Pointer, uintptr) bool
+}
+
 // Method on non-interface type
 type method struct {
        name    *string        // name of method
@@ -1096,6 +1108,10 @@ func (t *rtype) ConvertibleTo(u Type) bool {
        return convertOp(uu, t) != nil
 }
 
+func (t *rtype) Comparable() bool {
+       return t.alg != nil && t.alg.equal != nil
+}
+
 // implements returns true if the type V implements the interface type T.
 func implements(T, V *rtype) bool {
        if T.Kind() != Interface {