aboutsummaryrefslogtreecommitdiffhomepage
path: root/vendor/github.com/zclconf/go-cty/cty/convert/unify.go
diff options
context:
space:
mode:
Diffstat (limited to 'vendor/github.com/zclconf/go-cty/cty/convert/unify.go')
-rw-r--r--vendor/github.com/zclconf/go-cty/cty/convert/unify.go66
1 files changed, 66 insertions, 0 deletions
diff --git a/vendor/github.com/zclconf/go-cty/cty/convert/unify.go b/vendor/github.com/zclconf/go-cty/cty/convert/unify.go
new file mode 100644
index 0000000..bd6736b
--- /dev/null
+++ b/vendor/github.com/zclconf/go-cty/cty/convert/unify.go
@@ -0,0 +1,66 @@
1package convert
2
3import (
4 "github.com/zclconf/go-cty/cty"
5)
6
7// The current unify implementation is somewhat inefficient, but we accept this
8// under the assumption that it will generally be used with small numbers of
9// types and with types of reasonable complexity. However, it does have a
10// "happy path" where all of the given types are equal.
11//
12// This function is likely to have poor performance in cases where any given
13// types are very complex (lots of deeply-nested structures) or if the list
14// of types itself is very large. In particular, it will walk the nested type
15// structure under the given types several times, especially when given a
16// list of types for which unification is not possible, since each permutation
17// will be tried to determine that result.
18func unify(types []cty.Type, unsafe bool) (cty.Type, []Conversion) {
19 if len(types) == 0 {
20 // Degenerate case
21 return cty.NilType, nil
22 }
23
24 prefOrder := sortTypes(types)
25
26 // sortTypes gives us an order where earlier items are preferable as
27 // our result type. We'll now walk through these and choose the first
28 // one we encounter for which conversions exist for all source types.
29 conversions := make([]Conversion, len(types))
30Preferences:
31 for _, wantTypeIdx := range prefOrder {
32 wantType := types[wantTypeIdx]
33 for i, tryType := range types {
34 if i == wantTypeIdx {
35 // Don't need to convert our wanted type to itself
36 conversions[i] = nil
37 continue
38 }
39
40 if tryType.Equals(wantType) {
41 conversions[i] = nil
42 continue
43 }
44
45 if unsafe {
46 conversions[i] = GetConversionUnsafe(tryType, wantType)
47 } else {
48 conversions[i] = GetConversion(tryType, wantType)
49 }
50
51 if conversions[i] == nil {
52 // wantType is not a suitable unification type, so we'll
53 // try the next one in our preference order.
54 continue Preferences
55 }
56 }
57
58 return wantType, conversions
59 }
60
61 // TODO: For structural types, try to invent a new type that they
62 // can all be unified to, by unifying their respective attributes.
63
64 // If we fall out here, no unification is possible
65 return cty.NilType, nil
66}