GoPLS Viewer

Home|gopls/go/ssa/interp/testdata/src/reflect/deepequal.go
1package reflect
2
3// Not an actual implementation of DeepEqual. This is a model that supports
4// the bare minimum needed to get through testing interp.
5//
6// Does not handle cycles.
7//
8// Note: unclear if reflect.go can support this.
9func DeepEqual(xy interface{}) bool {
10    if x == nil || y == nil {
11        return x == y
12    }
13    v1 := ValueOf(x)
14    v2 := ValueOf(y)
15
16    return deepValueEqual(v1v2make(map[visit]bool))
17}
18
19// Key for the visitedMap in deepValueEqual.
20type visit struct {
21    a1a2 uintptr
22    typ    Type
23}
24
25func deepValueEqual(v1v2 Valuevisited map[visit]boolbool {
26    if !v1.IsValid() || !v2.IsValid() {
27        return v1.IsValid() == v2.IsValid()
28    }
29    if v1.Type() != v2.Type() {
30        return false
31    }
32
33    // Short circuit on reference types that can lead to cycles in comparison.
34    switch v1.Kind() {
35    case PointerMapSliceInterface:
36        k := visit{v1.Pointer(), v2.Pointer(), v1.Type()} // Not safe for moving GC.
37        if visited[k] {
38            // The comparison algorithm assumes that all checks in progress are true when it reencounters them.
39            return true
40        }
41        visited[k] = true
42    }
43
44    switch v1.Kind() {
45    case Array:
46        for i := 0i < v1.Len(); i++ {
47            if !deepValueEqual(v1.Index(i), v2.Index(i), visited) {
48                return false
49            }
50        }
51        return true
52    case Slice:
53        if v1.IsNil() != v2.IsNil() {
54            return false
55        }
56        if v1.Len() != v2.Len() {
57            return false
58        }
59        if v1.Pointer() == v2.Pointer() {
60            return true
61        }
62        for i := 0i < v1.Len(); i++ {
63            if !deepValueEqual(v1.Index(i), v2.Index(i), visited) {
64                return false
65            }
66        }
67        return true
68    case Interface:
69        if v1.IsNil() || v2.IsNil() {
70            return v1.IsNil() == v2.IsNil()
71        }
72        return deepValueEqual(v1.Elem(), v2.Elem(), visited)
73    case Ptr:
74        if v1.Pointer() == v2.Pointer() {
75            return true
76        }
77        return deepValueEqual(v1.Elem(), v2.Elem(), visited)
78    case Struct:
79        for in := 0v1.NumField(); i < ni++ {
80            if !deepValueEqual(v1.Field(i), v2.Field(i), visited) {
81                return false
82            }
83        }
84        return true
85    case Map:
86        if v1.IsNil() != v2.IsNil() {
87            return false
88        }
89        if v1.Len() != v2.Len() {
90            return false
91        }
92        if v1.Pointer() == v2.Pointer() {
93            return true
94        }
95        for _k := range v1.MapKeys() {
96            val1 := v1.MapIndex(k)
97            val2 := v2.MapIndex(k)
98            if !val1.IsValid() || !val2.IsValid() || !deepValueEqual(val1val2visited) {
99                return false
100            }
101        }
102        return true
103    case Func:
104        return v1.IsNil() && v2.IsNil()
105    default:
106        // Normal equality suffices
107        return v1.Interface() == v2.Interface() // try interface comparison as a fallback.
108    }
109}
110
MembersX
deepValueEqual
deepValueEqual.BlockStmt.i
DeepEqual
DeepEqual.v2
visit.typ
deepValueEqual.v2
deepValueEqual.BlockStmt.k
deepValueEqual.BlockStmt.n
DeepEqual.x
DeepEqual.v1
deepValueEqual.v1
deepValueEqual.visited
deepValueEqual.BlockStmt.RangeStmt_2135.k
DeepEqual.y
visit
visit.a1
visit.a2
deepValueEqual.BlockStmt.RangeStmt_2135.BlockStmt.val1
deepValueEqual.BlockStmt.RangeStmt_2135.BlockStmt.val2
Members
X