]> Cypherpunks.ru repositories - gostls13.git/commitdiff
reflect: panic when Value.Equal using two non-comparable values
authorhopehook <hopehook.com@gmail.com>
Fri, 7 Oct 2022 14:42:15 +0000 (22:42 +0800)
committerGopher Robot <gobot@golang.org>
Mon, 17 Oct 2022 14:53:58 +0000 (14:53 +0000)
Assuming the two values are valid and non-comparable, Equal should panic.

x := reflect.ValueOf([]int{1, 2, 3})
x.Equal(x) // can not report false, should panic

Assuming one of them is non-comparable and the other is invalid, it should
always report false.

x := reflect.ValueOf([]int{1, 2, 3})
y := reflect.ValueOf(nil)
x.Equal(y) // should report false

For #46746.

Change-Id: Ifecd77ca0b3de3019fae2be39048f9277831676c
Reviewed-on: https://go-review.googlesource.com/c/go/+/440037
Reviewed-by: Ian Lance Taylor <iant@google.com>
Reviewed-by: David Chase <drchase@google.com>
Run-TryBot: Ian Lance Taylor <iant@google.com>
Auto-Submit: Ian Lance Taylor <iant@google.com>
TryBot-Result: Gopher Robot <gobot@golang.org>

src/reflect/all_test.go
src/reflect/value.go

index 40377178a5eb37c1c709a8e26e8393bf4d1d311e..e5d0b2c07c7ab8d7de5f5fc7abb839b364399a88 100644 (file)
@@ -8244,16 +8244,6 @@ var valueEqualTests = []ValueEqualTest{
                true,
                true, false,
        },
-       {
-               &equalSlice, []int{1},
-               false,
-               true, false,
-       },
-       {
-               map[int]int{}, map[int]int{},
-               false,
-               false, false,
-       },
        {
                (chan int)(nil), nil,
                false,
@@ -8289,11 +8279,6 @@ var valueEqualTests = []ValueEqualTest{
                true,
                false, false,
        },
-       {
-               &mapInterface, &mapInterface,
-               false,
-               true, true,
-       },
 }
 
 func TestValue_Equal(t *testing.T) {
@@ -8324,6 +8309,41 @@ func TestValue_Equal(t *testing.T) {
        }
 }
 
+func TestValue_EqualNonComparable(t *testing.T) {
+       var invalid = Value{} // ValueOf(nil)
+       var values = []Value{
+               // Value of slice is non-comparable.
+               ValueOf([]int(nil)),
+               ValueOf(([]int{})),
+
+               // Value of map is non-comparable.
+               ValueOf(map[int]int(nil)),
+               ValueOf((map[int]int{})),
+
+               // Value of func is non-comparable.
+               ValueOf(((func())(nil))),
+               ValueOf(func() {}),
+
+               // Value of struct is non-comparable because of non-comparable elements.
+               ValueOf((NonComparableStruct{})),
+
+               // Value of array is non-comparable because of non-comparable elements.
+               ValueOf([0]map[int]int{}),
+               ValueOf([0]func(){}),
+               ValueOf(([1]struct{ I interface{} }{{[]int{}}})),
+               ValueOf(([1]interface{}{[1]interface{}{map[int]int{}}})),
+       }
+       for _, value := range values {
+               // Panic when reflect.Value.Equal using two valid non-comparable values.
+               shouldPanic("reflect.Value.Equal using two non-comparable values", func() { value.Equal(value) })
+
+               // If one is non-comparable and the other is invalid, the expected result is always false.
+               if r := value.Equal(invalid); r != false {
+                       t.Errorf("%s == invalid got %t, want false", value.Type(), r)
+               }
+       }
+}
+
 func TestInitFuncTypes(t *testing.T) {
        n := 100
        var wg sync.WaitGroup
index eeee6fac0fbc19f2bc3bbadf517c55c571313b31..448ffa20589eed020551c63023c451e6efc89910 100644 (file)
@@ -3320,7 +3320,8 @@ func (v Value) Comparable() bool {
 }
 
 // Equal reports true if v is equal to u.
-// For valid values, if either v or u is non-comparable, Equal returns false.
+// For valid values, if one of them is non-comparable, and the other is comparable,
+// Equal reports false; if v and u are both non-comparable, Equal will panic.
 func (v Value) Equal(u Value) bool {
        if !v.IsValid() || !u.IsValid() {
                return v.IsValid() == u.IsValid()
@@ -3334,7 +3335,7 @@ func (v Value) Equal(u Value) bool {
                return v.Elem().Equal(u.Elem())
        }
 
-       return false
+       panic("reflect.Value.Equal using two non-comparable values")
 }
 
 // convertOp returns the function to convert a value of type src