1
0
mirror of https://github.com/golang/go synced 2024-11-17 13:54:46 -07:00

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>
This commit is contained in:
hopehook 2022-10-07 22:42:15 +08:00 committed by Gopher Robot
parent 9abcc487f8
commit 7ffc1e47b4
2 changed files with 38 additions and 17 deletions

View 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

View 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