1package cty 2 3// Type represents value types within the type system. 4// 5// This is a closed interface type, meaning that only the concrete 6// implementations provided within this package are considered valid. 7type Type struct { 8 typeImpl 9} 10 11type typeImpl interface { 12 // isTypeImpl is a do-nothing method that exists only to express 13 // that a type is an implementation of typeImpl. 14 isTypeImpl() typeImplSigil 15 16 // Equals returns true if the other given Type exactly equals the 17 // receiver Type. 18 Equals(other Type) bool 19 20 // FriendlyName returns a human-friendly *English* name for the given 21 // type. 22 FriendlyName(mode friendlyTypeNameMode) string 23 24 // GoString implements the GoStringer interface from package fmt. 25 GoString() string 26} 27 28// Base implementation of Type to embed into concrete implementations 29// to signal that they are implementations of Type. 30type typeImplSigil struct{} 31 32func (t typeImplSigil) isTypeImpl() typeImplSigil { 33 return typeImplSigil{} 34} 35 36// Equals returns true if the other given Type exactly equals the receiver 37// type. 38func (t Type) Equals(other Type) bool { 39 if t == NilType || other == NilType { 40 return t == other 41 } 42 return t.typeImpl.Equals(other) 43} 44 45// FriendlyName returns a human-friendly *English* name for the given type. 46func (t Type) FriendlyName() string { 47 return t.typeImpl.FriendlyName(friendlyTypeName) 48} 49 50// FriendlyNameForConstraint is similar to FriendlyName except that the 51// result is specialized for describing type _constraints_ rather than types 52// themselves. This is more appropriate when reporting that a particular value 53// does not conform to an expected type constraint. 54// 55// In particular, this function uses the term "any type" to refer to 56// cty.DynamicPseudoType, rather than "dynamic" as returned by FriendlyName. 57func (t Type) FriendlyNameForConstraint() string { 58 return t.typeImpl.FriendlyName(friendlyTypeConstraintName) 59} 60 61// friendlyNameMode is an internal combination of the various FriendlyName* 62// variants that just directly takes a mode, for easy passthrough for 63// recursive name construction. 64func (t Type) friendlyNameMode(mode friendlyTypeNameMode) string { 65 return t.typeImpl.FriendlyName(mode) 66} 67 68// GoString returns a string approximating how the receiver type would be 69// expressed in Go source code. 70func (t Type) GoString() string { 71 if t.typeImpl == nil { 72 return "cty.NilType" 73 } 74 75 return t.typeImpl.GoString() 76} 77 78// NilType is an invalid type used when a function is returning an error 79// and has no useful type to return. It should not be used and any methods 80// called on it will panic. 81var NilType = Type{} 82 83// HasDynamicTypes returns true either if the receiver is itself 84// DynamicPseudoType or if it is a compound type whose descendent elements 85// are DynamicPseudoType. 86func (t Type) HasDynamicTypes() bool { 87 switch { 88 case t == DynamicPseudoType: 89 return true 90 case t.IsPrimitiveType(): 91 return false 92 case t.IsCollectionType(): 93 return t.ElementType().HasDynamicTypes() 94 case t.IsObjectType(): 95 attrTypes := t.AttributeTypes() 96 for _, at := range attrTypes { 97 if at.HasDynamicTypes() { 98 return true 99 } 100 } 101 return false 102 case t.IsTupleType(): 103 elemTypes := t.TupleElementTypes() 104 for _, et := range elemTypes { 105 if et.HasDynamicTypes() { 106 return true 107 } 108 } 109 return false 110 case t.IsCapsuleType(): 111 return false 112 default: 113 // Should never happen, since above should be exhaustive 114 panic("HasDynamicTypes does not support the given type") 115 } 116} 117 118type friendlyTypeNameMode rune 119 120const ( 121 friendlyTypeName friendlyTypeNameMode = 'N' 122 friendlyTypeConstraintName friendlyTypeNameMode = 'C' 123) 124