summaryrefslogtreecommitdiff
path: root/src/reflect
diff options
context:
space:
mode:
authorRuss Cox <rsc@golang.org>2014-09-16 17:40:10 -0400
committerRuss Cox <rsc@golang.org>2014-09-16 17:40:10 -0400
commit520597830a086deec278c98b5782713ca40b661e (patch)
treeeff64eb8d80d5af7a15548df326d148b15965ac7 /src/reflect
parent49f4c39e491fe81c849d206d91e47b8a757b232a (diff)
downloadgo-520597830a086deec278c98b5782713ca40b661e.tar.gz
reflect: add Type.Comparable
Like most of the Type methods, the definition of Comparable is what the Go spec says it is. Fixes issue 7911. LGTM=gri R=gri, r CC=golang-codereviews https://codereview.appspot.com/144020043
Diffstat (limited to 'src/reflect')
-rw-r--r--src/reflect/all_test.go38
-rw-r--r--src/reflect/type.go18
2 files changed, 55 insertions, 1 deletions
diff --git a/src/reflect/all_test.go b/src/reflect/all_test.go
index 688b5d310..4be0e353d 100644
--- a/src/reflect/all_test.go
+++ b/src/reflect/all_test.go
@@ -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)
diff --git a/src/reflect/type.go b/src/reflect/type.go
index 67818f7f4..f099546d2 100644
--- a/src/reflect/type.go
+++ b/src/reflect/type.go
@@ -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 {