Source file src/go/types/predicates.go
1
2
3
4
5
6
7 package types
8
9 import "sort"
10
11 func isNamed(typ Type) bool {
12 if _, ok := typ.(*Basic); ok {
13 return ok
14 }
15 _, ok := typ.(*Named)
16 return ok
17 }
18
19 func isBoolean(typ Type) bool {
20 t, ok := typ.Underlying().(*Basic)
21 return ok && t.info&IsBoolean != 0
22 }
23
24 func isInteger(typ Type) bool {
25 t, ok := typ.Underlying().(*Basic)
26 return ok && t.info&IsInteger != 0
27 }
28
29 func isUnsigned(typ Type) bool {
30 t, ok := typ.Underlying().(*Basic)
31 return ok && t.info&IsUnsigned != 0
32 }
33
34 func isFloat(typ Type) bool {
35 t, ok := typ.Underlying().(*Basic)
36 return ok && t.info&IsFloat != 0
37 }
38
39 func isComplex(typ Type) bool {
40 t, ok := typ.Underlying().(*Basic)
41 return ok && t.info&IsComplex != 0
42 }
43
44 func isNumeric(typ Type) bool {
45 t, ok := typ.Underlying().(*Basic)
46 return ok && t.info&IsNumeric != 0
47 }
48
49 func isString(typ Type) bool {
50 t, ok := typ.Underlying().(*Basic)
51 return ok && t.info&IsString != 0
52 }
53
54 func isTyped(typ Type) bool {
55 t, ok := typ.Underlying().(*Basic)
56 return !ok || t.info&IsUntyped == 0
57 }
58
59 func isUntyped(typ Type) bool {
60 t, ok := typ.Underlying().(*Basic)
61 return ok && t.info&IsUntyped != 0
62 }
63
64 func isOrdered(typ Type) bool {
65 t, ok := typ.Underlying().(*Basic)
66 return ok && t.info&IsOrdered != 0
67 }
68
69 func isConstType(typ Type) bool {
70 t, ok := typ.Underlying().(*Basic)
71 return ok && t.info&IsConstType != 0
72 }
73
74
75 func IsInterface(typ Type) bool {
76 _, ok := typ.Underlying().(*Interface)
77 return ok
78 }
79
80
81 func Comparable(T Type) bool {
82 switch t := T.Underlying().(type) {
83 case *Basic:
84
85
86 return t.kind != UntypedNil
87 case *Pointer, *Interface, *Chan:
88 return true
89 case *Struct:
90 for _, f := range t.fields {
91 if !Comparable(f.typ) {
92 return false
93 }
94 }
95 return true
96 case *Array:
97 return Comparable(t.elem)
98 }
99 return false
100 }
101
102
103 func hasNil(typ Type) bool {
104 switch t := typ.Underlying().(type) {
105 case *Basic:
106 return t.kind == UnsafePointer
107 case *Slice, *Pointer, *Signature, *Interface, *Map, *Chan:
108 return true
109 }
110 return false
111 }
112
113
114
115 func Identical(x, y Type) bool {
116 return identical(x, y, true, nil)
117 }
118
119
120
121 func IdenticalIgnoreTags(x, y Type) bool {
122 return identical(x, y, false, nil)
123 }
124
125
126 type ifacePair struct {
127 x, y *Interface
128 prev *ifacePair
129 }
130
131 func (p *ifacePair) identical(q *ifacePair) bool {
132 return p.x == q.x && p.y == q.y || p.x == q.y && p.y == q.x
133 }
134
135 func identical(x, y Type, cmpTags bool, p *ifacePair) bool {
136 if x == y {
137 return true
138 }
139
140 switch x := x.(type) {
141 case *Basic:
142
143
144
145 if y, ok := y.(*Basic); ok {
146 return x.kind == y.kind
147 }
148
149 case *Array:
150
151
152 if y, ok := y.(*Array); ok {
153
154
155 return (x.len < 0 || y.len < 0 || x.len == y.len) && identical(x.elem, y.elem, cmpTags, p)
156 }
157
158 case *Slice:
159
160 if y, ok := y.(*Slice); ok {
161 return identical(x.elem, y.elem, cmpTags, p)
162 }
163
164 case *Struct:
165
166
167
168
169 if y, ok := y.(*Struct); ok {
170 if x.NumFields() == y.NumFields() {
171 for i, f := range x.fields {
172 g := y.fields[i]
173 if f.embedded != g.embedded ||
174 cmpTags && x.Tag(i) != y.Tag(i) ||
175 !f.sameId(g.pkg, g.name) ||
176 !identical(f.typ, g.typ, cmpTags, p) {
177 return false
178 }
179 }
180 return true
181 }
182 }
183
184 case *Pointer:
185
186 if y, ok := y.(*Pointer); ok {
187 return identical(x.base, y.base, cmpTags, p)
188 }
189
190 case *Tuple:
191
192
193 if y, ok := y.(*Tuple); ok {
194 if x.Len() == y.Len() {
195 if x != nil {
196 for i, v := range x.vars {
197 w := y.vars[i]
198 if !identical(v.typ, w.typ, cmpTags, p) {
199 return false
200 }
201 }
202 }
203 return true
204 }
205 }
206
207 case *Signature:
208
209
210
211
212 if y, ok := y.(*Signature); ok {
213 return x.variadic == y.variadic &&
214 identical(x.params, y.params, cmpTags, p) &&
215 identical(x.results, y.results, cmpTags, p)
216 }
217
218 case *Interface:
219
220
221
222 if y, ok := y.(*Interface); ok {
223 a := x.allMethods
224 b := y.allMethods
225 if len(a) == len(b) {
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248 q := &ifacePair{x, y, p}
249 for p != nil {
250 if p.identical(q) {
251 return true
252 }
253 p = p.prev
254 }
255 if debug {
256 assert(sort.IsSorted(byUniqueMethodName(a)))
257 assert(sort.IsSorted(byUniqueMethodName(b)))
258 }
259 for i, f := range a {
260 g := b[i]
261 if f.Id() != g.Id() || !identical(f.typ, g.typ, cmpTags, q) {
262 return false
263 }
264 }
265 return true
266 }
267 }
268
269 case *Map:
270
271 if y, ok := y.(*Map); ok {
272 return identical(x.key, y.key, cmpTags, p) && identical(x.elem, y.elem, cmpTags, p)
273 }
274
275 case *Chan:
276
277
278 if y, ok := y.(*Chan); ok {
279 return x.dir == y.dir && identical(x.elem, y.elem, cmpTags, p)
280 }
281
282 case *Named:
283
284
285 if y, ok := y.(*Named); ok {
286 return x.obj == y.obj
287 }
288
289 case nil:
290
291 default:
292 unreachable()
293 }
294
295 return false
296 }
297
298
299
300
301
302 func Default(typ Type) Type {
303 if t, ok := typ.(*Basic); ok {
304 switch t.kind {
305 case UntypedBool:
306 return Typ[Bool]
307 case UntypedInt:
308 return Typ[Int]
309 case UntypedRune:
310 return universeRune
311 case UntypedFloat:
312 return Typ[Float64]
313 case UntypedComplex:
314 return Typ[Complex128]
315 case UntypedString:
316 return Typ[String]
317 }
318 }
319 return typ
320 }
321
View as plain text