Source file
src/go/types/predicates.go
1
2
3
4
5
6
7 package types
8
9 import (
10 "go/token"
11 )
12
13
14
15 func isNamed(typ Type) bool {
16 switch typ.(type) {
17 case *Basic, *Named, *_TypeParam, *instance:
18 return true
19 }
20 return false
21 }
22
23
24
25 func isGeneric(typ Type) bool {
26
27 named, _ := typ.(*Named)
28 return named != nil && named.obj != nil && named.tparams != nil && named.targs == nil
29 }
30
31 func is(typ Type, what BasicInfo) bool {
32 switch t := optype(typ).(type) {
33 case *Basic:
34 return t.info&what != 0
35 case *_Sum:
36 return t.is(func(typ Type) bool { return is(typ, what) })
37 }
38 return false
39 }
40
41 func isBoolean(typ Type) bool { return is(typ, IsBoolean) }
42 func isInteger(typ Type) bool { return is(typ, IsInteger) }
43 func isUnsigned(typ Type) bool { return is(typ, IsUnsigned) }
44 func isFloat(typ Type) bool { return is(typ, IsFloat) }
45 func isComplex(typ Type) bool { return is(typ, IsComplex) }
46 func isNumeric(typ Type) bool { return is(typ, IsNumeric) }
47 func isString(typ Type) bool { return is(typ, IsString) }
48
49
50
51
52
53 func isIntegerOrFloat(typ Type) bool { return is(typ, IsInteger|IsFloat) }
54
55
56 func isNumericOrString(typ Type) bool { return is(typ, IsNumeric|IsString) }
57
58
59
60
61 func isTyped(typ Type) bool {
62
63
64
65
66
67 t, _ := typ.(*Basic)
68 return t == nil || t.info&IsUntyped == 0
69 }
70
71
72 func isUntyped(typ Type) bool {
73 return !isTyped(typ)
74 }
75
76 func isOrdered(typ Type) bool { return is(typ, IsOrdered) }
77
78 func isConstType(typ Type) bool {
79
80 t, _ := under(typ).(*Basic)
81 return t != nil && t.info&IsConstType != 0
82 }
83
84
85 func IsInterface(typ Type) bool {
86 return asInterface(typ) != nil
87 }
88
89
90 func Comparable(T Type) bool {
91 return comparable(T, nil)
92 }
93
94 func comparable(T Type, seen map[Type]bool) bool {
95 if seen[T] {
96 return true
97 }
98 if seen == nil {
99 seen = make(map[Type]bool)
100 }
101 seen[T] = true
102
103
104
105
106
107
108
109
110
111 if t := asTypeParam(T); t != nil && optype(t) == theTop {
112 return t.Bound()._IsComparable()
113 }
114
115 switch t := optype(T).(type) {
116 case *Basic:
117
118
119 return t.kind != UntypedNil
120 case *Pointer, *Interface, *Chan:
121 return true
122 case *Struct:
123 for _, f := range t.fields {
124 if !comparable(f.typ, seen) {
125 return false
126 }
127 }
128 return true
129 case *Array:
130 return comparable(t.elem, seen)
131 case *_Sum:
132 pred := func(t Type) bool {
133 return comparable(t, seen)
134 }
135 return t.is(pred)
136 case *_TypeParam:
137 return t.Bound()._IsComparable()
138 }
139 return false
140 }
141
142
143 func hasNil(typ Type) bool {
144 switch t := optype(typ).(type) {
145 case *Basic:
146 return t.kind == UnsafePointer
147 case *Slice, *Pointer, *Signature, *Interface, *Map, *Chan:
148 return true
149 case *_Sum:
150 return t.is(hasNil)
151 }
152 return false
153 }
154
155
156
157 func (check *Checker) identical(x, y Type) bool {
158 return check.identical0(x, y, true, nil)
159 }
160
161
162
163 func (check *Checker) identicalIgnoreTags(x, y Type) bool {
164 return check.identical0(x, y, false, nil)
165 }
166
167
168 type ifacePair struct {
169 x, y *Interface
170 prev *ifacePair
171 }
172
173 func (p *ifacePair) identical(q *ifacePair) bool {
174 return p.x == q.x && p.y == q.y || p.x == q.y && p.y == q.x
175 }
176
177
178 func (check *Checker) identical0(x, y Type, cmpTags bool, p *ifacePair) bool {
179
180 x = expandf(x)
181 y = expandf(y)
182
183 if x == y {
184 return true
185 }
186
187 switch x := x.(type) {
188 case *Basic:
189
190
191
192 if y, ok := y.(*Basic); ok {
193 return x.kind == y.kind
194 }
195
196 case *Array:
197
198
199 if y, ok := y.(*Array); ok {
200
201
202 return (x.len < 0 || y.len < 0 || x.len == y.len) && check.identical0(x.elem, y.elem, cmpTags, p)
203 }
204
205 case *Slice:
206
207 if y, ok := y.(*Slice); ok {
208 return check.identical0(x.elem, y.elem, cmpTags, p)
209 }
210
211 case *Struct:
212
213
214
215
216 if y, ok := y.(*Struct); ok {
217 if x.NumFields() == y.NumFields() {
218 for i, f := range x.fields {
219 g := y.fields[i]
220 if f.embedded != g.embedded ||
221 cmpTags && x.Tag(i) != y.Tag(i) ||
222 !f.sameId(g.pkg, g.name) ||
223 !check.identical0(f.typ, g.typ, cmpTags, p) {
224 return false
225 }
226 }
227 return true
228 }
229 }
230
231 case *Pointer:
232
233 if y, ok := y.(*Pointer); ok {
234 return check.identical0(x.base, y.base, cmpTags, p)
235 }
236
237 case *Tuple:
238
239
240 if y, ok := y.(*Tuple); ok {
241 if x.Len() == y.Len() {
242 if x != nil {
243 for i, v := range x.vars {
244 w := y.vars[i]
245 if !check.identical0(v.typ, w.typ, cmpTags, p) {
246 return false
247 }
248 }
249 }
250 return true
251 }
252 }
253
254 case *Signature:
255
256
257
258
259
260
261 if y, ok := y.(*Signature); ok {
262 return x.variadic == y.variadic &&
263 check.identicalTParams(x.tparams, y.tparams, cmpTags, p) &&
264 check.identical0(x.params, y.params, cmpTags, p) &&
265 check.identical0(x.results, y.results, cmpTags, p)
266 }
267
268 case *_Sum:
269
270
271
272
273
274
275 if y, ok := y.(*_Sum); ok && len(x.types) == len(y.types) {
276
277
278
279 L:
280 for _, x := range x.types {
281 for _, y := range y.types {
282 if Identical(x, y) {
283 continue L
284 }
285 }
286 return false
287 }
288 return true
289 }
290
291 case *Interface:
292
293
294
295 if y, ok := y.(*Interface); ok {
296
297
298
299
300 if check != nil {
301 check.completeInterface(token.NoPos, x)
302 check.completeInterface(token.NoPos, y)
303 }
304 a := x.allMethods
305 b := y.allMethods
306 if len(a) == len(b) {
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329 q := &ifacePair{x, y, p}
330 for p != nil {
331 if p.identical(q) {
332 return true
333 }
334 p = p.prev
335 }
336 if debug {
337 assertSortedMethods(a)
338 assertSortedMethods(b)
339 }
340 for i, f := range a {
341 g := b[i]
342 if f.Id() != g.Id() || !check.identical0(f.typ, g.typ, cmpTags, q) {
343 return false
344 }
345 }
346 return true
347 }
348 }
349
350 case *Map:
351
352 if y, ok := y.(*Map); ok {
353 return check.identical0(x.key, y.key, cmpTags, p) && check.identical0(x.elem, y.elem, cmpTags, p)
354 }
355
356 case *Chan:
357
358
359 if y, ok := y.(*Chan); ok {
360 return x.dir == y.dir && check.identical0(x.elem, y.elem, cmpTags, p)
361 }
362
363 case *Named:
364
365
366 if y, ok := y.(*Named); ok {
367
368
369
370 return x.obj == y.obj
371 }
372
373 case *_TypeParam:
374
375
376
377
378
379 case *bottom, *top:
380
381
382
383
384 case nil:
385
386
387 default:
388 unreachable()
389 }
390
391 return false
392 }
393
394 func (check *Checker) identicalTParams(x, y []*TypeName, cmpTags bool, p *ifacePair) bool {
395 if len(x) != len(y) {
396 return false
397 }
398 for i, x := range x {
399 y := y[i]
400 if !check.identical0(x.typ.(*_TypeParam).bound, y.typ.(*_TypeParam).bound, cmpTags, p) {
401 return false
402 }
403 }
404 return true
405 }
406
407
408
409
410
411 func Default(typ Type) Type {
412 if t, ok := typ.(*Basic); ok {
413 switch t.kind {
414 case UntypedBool:
415 return Typ[Bool]
416 case UntypedInt:
417 return Typ[Int]
418 case UntypedRune:
419 return universeRune
420 case UntypedFloat:
421 return Typ[Float64]
422 case UntypedComplex:
423 return Typ[Complex128]
424 case UntypedString:
425 return Typ[String]
426 }
427 }
428 return typ
429 }
430
View as plain text