mirror of
https://github.com/golang/go
synced 2024-11-18 05:54:49 -07:00
reflect: handling flagIndir in DeepEqual potential cycles
Fixes #39607 Change-Id: Ia7e597e0da8a193a25382cc633a1c6080b4f7cbf Reviewed-on: https://go-review.googlesource.com/c/go/+/238361 Run-TryBot: Ian Lance Taylor <iant@golang.org> TryBot-Result: Gobot Gobot <gobot@golang.org> Reviewed-by: Keith Randall <khr@golang.org>
This commit is contained in:
parent
84baf4162a
commit
d872bbcfec
@ -824,6 +824,11 @@ var loop1, loop2 Loop
|
|||||||
var loopy1, loopy2 Loopy
|
var loopy1, loopy2 Loopy
|
||||||
var cycleMap1, cycleMap2, cycleMap3 map[string]interface{}
|
var cycleMap1, cycleMap2, cycleMap3 map[string]interface{}
|
||||||
|
|
||||||
|
type structWithSelfPtr struct {
|
||||||
|
p *structWithSelfPtr
|
||||||
|
s string
|
||||||
|
}
|
||||||
|
|
||||||
func init() {
|
func init() {
|
||||||
loop1 = &loop2
|
loop1 = &loop2
|
||||||
loop2 = &loop1
|
loop2 = &loop1
|
||||||
@ -880,6 +885,7 @@ var deepEqualTests = []DeepEqualTest{
|
|||||||
{[]float64{math.NaN()}, self{}, true},
|
{[]float64{math.NaN()}, self{}, true},
|
||||||
{map[float64]float64{math.NaN(): 1}, map[float64]float64{1: 2}, false},
|
{map[float64]float64{math.NaN(): 1}, map[float64]float64{1: 2}, false},
|
||||||
{map[float64]float64{math.NaN(): 1}, self{}, true},
|
{map[float64]float64{math.NaN(): 1}, self{}, true},
|
||||||
|
{&structWithSelfPtr{p: &structWithSelfPtr{s: "a"}}, &structWithSelfPtr{p: &structWithSelfPtr{s: "b"}}, false},
|
||||||
|
|
||||||
// Nil vs empty: not the same.
|
// Nil vs empty: not the same.
|
||||||
{[]int{}, []int(nil), false},
|
{[]int{}, []int(nil), false},
|
||||||
|
@ -45,8 +45,20 @@ func deepValueEqual(v1, v2 Value, visited map[visit]bool, depth int) bool {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if hard(v1, v2) {
|
if hard(v1, v2) {
|
||||||
addr1 := v1.ptr
|
// For a Ptr or Map value, we need to check flagIndir,
|
||||||
addr2 := v2.ptr
|
// which we do by calling the pointer method.
|
||||||
|
// For Slice or Interface, flagIndir is always set,
|
||||||
|
// and using v.ptr suffices.
|
||||||
|
ptrval := func(v Value) unsafe.Pointer {
|
||||||
|
switch v.Kind() {
|
||||||
|
case Ptr, Map:
|
||||||
|
return v.pointer()
|
||||||
|
default:
|
||||||
|
return v.ptr
|
||||||
|
}
|
||||||
|
}
|
||||||
|
addr1 := ptrval(v1)
|
||||||
|
addr2 := ptrval(v2)
|
||||||
if uintptr(addr1) > uintptr(addr2) {
|
if uintptr(addr1) > uintptr(addr2) {
|
||||||
// Canonicalize order to reduce number of entries in visited.
|
// Canonicalize order to reduce number of entries in visited.
|
||||||
// Assumes non-moving garbage collector.
|
// Assumes non-moving garbage collector.
|
||||||
|
Loading…
Reference in New Issue
Block a user