1 // Copyright 2012 The Go Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style
3 // license that can be found in the LICENSE file.
5 // This file implements commonly used type predicates.
11 func isNamed(typ Type
) bool {
12 if _
, ok
:= typ
.(*Basic
); ok
{
19 func isBoolean(typ Type
) bool {
20 t
, ok
:= typ
.Underlying().(*Basic
)
21 return ok
&& t
.info
&IsBoolean
!= 0
24 func isInteger(typ Type
) bool {
25 t
, ok
:= typ
.Underlying().(*Basic
)
26 return ok
&& t
.info
&IsInteger
!= 0
29 func isUnsigned(typ Type
) bool {
30 t
, ok
:= typ
.Underlying().(*Basic
)
31 return ok
&& t
.info
&IsUnsigned
!= 0
34 func isFloat(typ Type
) bool {
35 t
, ok
:= typ
.Underlying().(*Basic
)
36 return ok
&& t
.info
&IsFloat
!= 0
39 func isComplex(typ Type
) bool {
40 t
, ok
:= typ
.Underlying().(*Basic
)
41 return ok
&& t
.info
&IsComplex
!= 0
44 func isNumeric(typ Type
) bool {
45 t
, ok
:= typ
.Underlying().(*Basic
)
46 return ok
&& t
.info
&IsNumeric
!= 0
49 func isString(typ Type
) bool {
50 t
, ok
:= typ
.Underlying().(*Basic
)
51 return ok
&& t
.info
&IsString
!= 0
54 func isTyped(typ Type
) bool {
55 t
, ok
:= typ
.Underlying().(*Basic
)
56 return !ok || t
.info
&IsUntyped
== 0
59 func isUntyped(typ Type
) bool {
60 t
, ok
:= typ
.Underlying().(*Basic
)
61 return ok
&& t
.info
&IsUntyped
!= 0
64 func isOrdered(typ Type
) bool {
65 t
, ok
:= typ
.Underlying().(*Basic
)
66 return ok
&& t
.info
&IsOrdered
!= 0
69 func isConstType(typ Type
) bool {
70 t
, ok
:= typ
.Underlying().(*Basic
)
71 return ok
&& t
.info
&IsConstType
!= 0
74 // IsInterface reports whether typ is an interface type.
75 func IsInterface(typ Type
) bool {
76 _
, ok
:= typ
.Underlying().(*Interface
)
80 // Comparable reports whether values of type T are comparable.
81 func Comparable(T Type
) bool {
82 switch t
:= T
.Underlying().(type) {
84 // assume invalid types to be comparable
85 // to avoid follow-up errors
86 return t
.kind
!= UntypedNil
87 case *Pointer
, *Interface
, *Chan
:
90 for _
, f
:= range t
.fields
{
91 if !Comparable(f
.typ
) {
97 return Comparable(t
.elem
)
102 // hasNil reports whether a type includes the nil value.
103 func hasNil(typ Type
) bool {
104 switch t
:= typ
.Underlying().(type) {
106 return t
.kind
== UnsafePointer
107 case *Slice
, *Pointer
, *Signature
, *Interface
, *Map
, *Chan
:
113 // Identical reports whether x and y are identical.
114 func Identical(x
, y Type
) bool {
115 return identical(x
, y
, true, nil)
118 // IdenticalIgnoreTags reports whether x and y are identical if tags are ignored.
119 func IdenticalIgnoreTags(x
, y Type
) bool {
120 return identical(x
, y
, false, nil)
123 // An ifacePair is a node in a stack of interface type pairs compared for identity.
124 type ifacePair
struct {
129 func (p
*ifacePair
) identical(q
*ifacePair
) bool {
130 return p
.x
== q
.x
&& p
.y
== q
.y || p
.x
== q
.y
&& p
.y
== q
.x
133 func identical(x
, y Type
, cmpTags
bool, p
*ifacePair
) bool {
138 switch x
:= x
.(type) {
140 // Basic types are singletons except for the rune and byte
141 // aliases, thus we cannot solely rely on the x == y check
142 // above. See also comment in TypeName.IsAlias.
143 if y
, ok
:= y
.(*Basic
); ok
{
144 return x
.kind
== y
.kind
148 // Two array types are identical if they have identical element types
149 // and the same array length.
150 if y
, ok
:= y
.(*Array
); ok
{
151 return x
.len == y
.len && identical(x
.elem
, y
.elem
, cmpTags
, p
)
155 // Two slice types are identical if they have identical element types.
156 if y
, ok
:= y
.(*Slice
); ok
{
157 return identical(x
.elem
, y
.elem
, cmpTags
, p
)
161 // Two struct types are identical if they have the same sequence of fields,
162 // and if corresponding fields have the same names, and identical types,
163 // and identical tags. Two anonymous fields are considered to have the same
164 // name. Lower-case field names from different packages are always different.
165 if y
, ok
:= y
.(*Struct
); ok
{
166 if x
.NumFields() == y
.NumFields() {
167 for i
, f
:= range x
.fields
{
169 if f
.anonymous
!= g
.anonymous ||
170 cmpTags
&& x
.Tag(i
) != y
.Tag(i
) ||
171 !f
.sameId(g
.pkg
, g
.name
) ||
172 !identical(f
.typ
, g
.typ
, cmpTags
, p
) {
181 // Two pointer types are identical if they have identical base types.
182 if y
, ok
:= y
.(*Pointer
); ok
{
183 return identical(x
.base
, y
.base
, cmpTags
, p
)
187 // Two tuples types are identical if they have the same number of elements
188 // and corresponding elements have identical types.
189 if y
, ok
:= y
.(*Tuple
); ok
{
190 if x
.Len() == y
.Len() {
192 for i
, v
:= range x
.vars
{
194 if !identical(v
.typ
, w
.typ
, cmpTags
, p
) {
204 // Two function types are identical if they have the same number of parameters
205 // and result values, corresponding parameter and result types are identical,
206 // and either both functions are variadic or neither is. Parameter and result
207 // names are not required to match.
208 if y
, ok
:= y
.(*Signature
); ok
{
209 return x
.variadic
== y
.variadic
&&
210 identical(x
.params
, y
.params
, cmpTags
, p
) &&
211 identical(x
.results
, y
.results
, cmpTags
, p
)
215 // Two interface types are identical if they have the same set of methods with
216 // the same names and identical function types. Lower-case method names from
217 // different packages are always different. The order of the methods is irrelevant.
218 if y
, ok
:= y
.(*Interface
); ok
{
221 if len(a
) == len(b
) {
222 // Interface types are the only types where cycles can occur
223 // that are not "terminated" via named types; and such cycles
224 // can only be created via method parameter types that are
225 // anonymous interfaces (directly or indirectly) embedding
226 // the current interface. Example:
228 // type T interface {
232 // If two such (differently named) interfaces are compared,
233 // endless recursion occurs if the cycle is not detected.
235 // If x and y were compared before, they must be equal
236 // (if they were not, the recursion would have stopped);
237 // search the ifacePair stack for the same pair.
239 // This is a quadratic algorithm, but in practice these stacks
240 // are extremely short (bounded by the nesting depth of interface
241 // type declarations that recur via parameter types, an extremely
242 // rare occurrence). An alternative implementation might use a
243 // "visited" map, but that is probably less efficient overall.
244 q
:= &ifacePair
{x
, y
, p
}
247 return true // same pair was compared before
252 assert(sort
.IsSorted(byUniqueMethodName(a
)))
253 assert(sort
.IsSorted(byUniqueMethodName(b
)))
255 for i
, f
:= range a
{
257 if f
.Id() != g
.Id() ||
!identical(f
.typ
, g
.typ
, cmpTags
, q
) {
266 // Two map types are identical if they have identical key and value types.
267 if y
, ok
:= y
.(*Map
); ok
{
268 return identical(x
.key
, y
.key
, cmpTags
, p
) && identical(x
.elem
, y
.elem
, cmpTags
, p
)
272 // Two channel types are identical if they have identical value types
273 // and the same direction.
274 if y
, ok
:= y
.(*Chan
); ok
{
275 return x
.dir
== y
.dir
&& identical(x
.elem
, y
.elem
, cmpTags
, p
)
279 // Two named types are identical if their type names originate
280 // in the same type declaration.
281 if y
, ok
:= y
.(*Named
); ok
{
282 return x
.obj
== y
.obj
294 // Default returns the default "typed" type for an "untyped" type;
295 // it returns the incoming type for all other types. The default type
296 // for untyped nil is untyped nil.
298 func Default(typ Type
) Type
{
299 if t
, ok
:= typ
.(*Basic
); ok
{
306 return universeRune
// use 'rune' name
310 return Typ
[Complex128
]