]> Cypherpunks repositories - gostls13.git/commitdiff
reflect: fix DeepEqual for some cyclic corner cases
authorRuss Cox <rsc@golang.org>
Fri, 21 Oct 2016 00:05:41 +0000 (20:05 -0400)
committerRuss Cox <rsc@golang.org>
Mon, 24 Oct 2016 15:20:23 +0000 (15:20 +0000)
Fixes #15610.

Change-Id: Idbc8a9b328b92034d53b8009471678a166d5cf3f
Reviewed-on: https://go-review.googlesource.com/31588
TryBot-Result: Gobot Gobot <gobot@golang.org>
Run-TryBot: Russ Cox <rsc@golang.org>
Reviewed-by: Ian Lance Taylor <iant@golang.org>
Reviewed-by: Quentin Smith <quentin@golang.org>
src/reflect/all_test.go
src/reflect/deepequal.go

index 9f8fd0df1975783102dadd266d63b36da869d92d..1d423f438615d3783a2f5cfb3f1f71e1df5162fc 100644 (file)
@@ -648,6 +648,20 @@ var (
 
 type self struct{}
 
+type Loop *Loop
+type Loopy interface{}
+
+var loop1, loop2 Loop
+var loopy1, loopy2 Loopy
+
+func init() {
+       loop1 = &loop2
+       loop2 = &loop1
+
+       loopy1 = &loopy2
+       loopy2 = &loopy1
+}
+
 var deepEqualTests = []DeepEqualTest{
        // Equalities
        {nil, nil, true},
@@ -706,6 +720,12 @@ var deepEqualTests = []DeepEqualTest{
        {&[3]interface{}{1, 2, 4}, &[3]interface{}{1, 2, "s"}, false},
        {Basic{1, 0.5}, NotBasic{1, 0.5}, false},
        {map[uint]string{1: "one", 2: "two"}, map[int]string{2: "two", 1: "one"}, false},
+
+       // Possible loops.
+       {&loop1, &loop1, true},
+       {&loop1, &loop2, true},
+       {&loopy1, &loopy1, true},
+       {&loopy1, &loopy2, true},
 }
 
 func TestDeepEqual(t *testing.T) {
index d33976885424c754897ba18c51a78639e84d9bf0..f3fd7043e5acef020430c780c4abff90979fecdc 100644 (file)
@@ -30,9 +30,13 @@ func deepValueEqual(v1, v2 Value, visited map[visit]bool, depth int) bool {
        }
 
        // if depth > 10 { panic("deepValueEqual") }    // for debugging
+
+       // We want to avoid putting more in the visited map than we need to.
+       // For any possible reference cycle that might be encountered,
+       // hard(t) needs to return true for at least one of the types in the cycle.
        hard := func(k Kind) bool {
                switch k {
-               case Array, Map, Slice, Struct:
+               case Map, Slice, Ptr, Interface:
                        return true
                }
                return false