MCPcopy
hub / github.com/purpleidea/mgmt / Unify

Function Unify

lang/unification/util/util.go:48–276  ·  view source on GitHub ↗

Unify takes two types and tries to make them equivalent. If they are both basic types without any unification variables, then we compare them directly, and this is equivalent to running the *types.Type Cmp method. This function works by drawing conclusions from the assertion that the two sides are e

(typ1, typ2 *types.Type)

Source from the content-addressed store, hash-verified

46// modify the input types, copy them before use if this is an issue. If you only
47// want to do a compare, you can safely use UnifyCmp.
48func Unify(typ1, typ2 *types.Type) error {
49 if typ1 == nil || typ2 == nil {
50 return fmt.Errorf("nil type")
51 }
52
53 // Both types are real and don't contain any unification variables, so
54 // we just compare them directly. -- Actually don't, these could contain
55 // unification variables, so leave that to the recursive call below.
56 //if typ1.Uni == nil && typ2.Uni == nil {
57 // return typ1.Cmp(typ2)
58 //}
59
60 // Here we have one type that is a ?1 type, and the other one *might* be
61 // a full type or it might even contain a ?2 for example. It could be a
62 // [?2] or [[?2]] for example.
63 if typ1.Uni != nil && typ2.Uni == nil { // aka && typ2.Kind != nil
64 root := typ1.Uni.Find()
65
66 // We don't yet know anything about this unification variable.
67 if root.Data == nil {
68 if err := OccursCheck(root, typ2); err != nil {
69 return err
70 }
71
72 root.Data = typ2 // learn!
73 return nil
74 }
75 // otherwise, cmp root.Data with typ2
76
77 return Unify(root.Data, typ2)
78 }
79
80 // This is the same case as above, except it's the opposite scenario.
81 if typ1.Uni == nil && typ2.Uni != nil {
82 root := typ2.Uni.Find()
83
84 // We don't yet know anything about this unification variable.
85 if root.Data == nil {
86 if err := OccursCheck(root, typ1); err != nil {
87 return err
88 }
89
90 root.Data = typ1 // learn!
91 return nil
92 }
93 // otherwise, cmp root.Data with typ1
94
95 return Unify(root.Data, typ1)
96 }
97
98 // Both of these are of the form ?1 and ?2 so we compare them directly.
99 if typ1.Uni != nil && typ2.Uni != nil {
100 root1 := typ1.Uni.Find()
101 root2 := typ2.Uni.Find()
102
103 if root1.Data == nil && root2.Data == nil {
104 // We don't need a merge function to wrap the Union call
105 // because in this scenario, both data fields are empty!

Callers 7

TestUnify1Function · 0.85
TestUnify2Function · 0.85
TestUnify3Function · 0.85
TestUnify4Function · 0.85
TestUnifyTableFunction · 0.85
TestExtract1Function · 0.85
UnifyCmpFunction · 0.85

Calls 3

OccursCheckFunction · 0.85
FindMethod · 0.80
UnionMethod · 0.80

Tested by 6

TestUnify1Function · 0.68
TestUnify2Function · 0.68
TestUnify3Function · 0.68
TestUnify4Function · 0.68
TestUnifyTableFunction · 0.68
TestExtract1Function · 0.68