aboutsummaryrefslogtreecommitdiff
path: root/src/reflect
diff options
context:
space:
mode:
authorhopehook <hopehook.com@gmail.com>2022-10-07 22:42:15 +0800
committerGopher Robot <gobot@golang.org>2022-10-17 14:53:58 +0000
commit7ffc1e47b4e3b163f06fc33c9adbc29cb1622d47 (patch)
treea12106d1c0daf4b24fedb21a161a2c1f7b8d3401 /src/reflect
parent9abcc487f8b04db8fd46eaa429a7eef5a5228241 (diff)
downloadgo-7ffc1e47b4e3b163f06fc33c9adbc29cb1622d47.tar.xz
reflect: panic when Value.Equal using two non-comparable values
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>
Diffstat (limited to 'src/reflect')
-rw-r--r--src/reflect/all_test.go50
-rw-r--r--src/reflect/value.go5
2 files changed, 38 insertions, 17 deletions
diff --git a/src/reflect/all_test.go b/src/reflect/all_test.go
index 40377178a5..e5d0b2c07c 100644
--- a/src/reflect/all_test.go
+++ b/src/reflect/all_test.go
@@ -8245,16 +8245,6 @@ var valueEqualTests = []ValueEqualTest{
true, false,
},
{
- &equalSlice, []int{1},
- false,
- true, false,
- },
- {
- map[int]int{}, map[int]int{},
- false,
- false, false,
- },
- {
(chan int)(nil), nil,
false,
false, 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
diff --git a/src/reflect/value.go b/src/reflect/value.go
index eeee6fac0f..448ffa2058 100644
--- a/src/reflect/value.go
+++ b/src/reflect/value.go
@@ -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