Source file
src/go/types/predicates.go
1
2
3
4
5
6
7 package types
8
9 import "go/token"
10
11
12
13
14
15 func isBoolean(t Type) bool { return isBasic(t, IsBoolean) }
16 func isInteger(t Type) bool { return isBasic(t, IsInteger) }
17 func isUnsigned(t Type) bool { return isBasic(t, IsUnsigned) }
18 func isFloat(t Type) bool { return isBasic(t, IsFloat) }
19 func isComplex(t Type) bool { return isBasic(t, IsComplex) }
20 func isNumeric(t Type) bool { return isBasic(t, IsNumeric) }
21 func isString(t Type) bool { return isBasic(t, IsString) }
22 func isIntegerOrFloat(t Type) bool { return isBasic(t, IsInteger|IsFloat) }
23 func isConstType(t Type) bool { return isBasic(t, IsConstType) }
24
25
26
27
28 func isBasic(t Type, info BasicInfo) bool {
29 u, _ := under(t).(*Basic)
30 return u != nil && u.info&info != 0
31 }
32
33
34
35
36
37
38
39 func allBoolean(typ Type) bool { return allBasic(typ, IsBoolean) }
40 func allInteger(typ Type) bool { return allBasic(typ, IsInteger) }
41 func allUnsigned(typ Type) bool { return allBasic(typ, IsUnsigned) }
42 func allNumeric(typ Type) bool { return allBasic(typ, IsNumeric) }
43 func allString(typ Type) bool { return allBasic(typ, IsString) }
44 func allOrdered(typ Type) bool { return allBasic(typ, IsOrdered) }
45 func allNumericOrString(typ Type) bool { return allBasic(typ, IsNumeric|IsString) }
46
47
48
49
50
51 func allBasic(t Type, info BasicInfo) bool {
52 if tpar, _ := t.(*TypeParam); tpar != nil {
53 return tpar.is(func(t *term) bool { return t != nil && isBasic(t.typ, info) })
54 }
55 return isBasic(t, info)
56 }
57
58
59
60
61 func hasName(t Type) bool {
62 switch t.(type) {
63 case *Basic, *Named, *TypeParam:
64 return true
65 }
66 return false
67 }
68
69
70
71
72 func isTyped(t Type) bool {
73
74
75 b, _ := t.(*Basic)
76 return b == nil || b.info&IsUntyped == 0
77 }
78
79
80 func isUntyped(t Type) bool {
81 return !isTyped(t)
82 }
83
84
85 func IsInterface(t Type) bool {
86 _, ok := under(t).(*Interface)
87 return ok
88 }
89
90
91 func isNonTypeParamInterface(t Type) bool {
92 return !isTypeParam(t) && IsInterface(t)
93 }
94
95
96 func isTypeParam(t Type) bool {
97 _, ok := t.(*TypeParam)
98 return ok
99 }
100
101
102
103
104 func isGeneric(t Type) bool {
105
106 named, _ := t.(*Named)
107 return named != nil && named.obj != nil && named.inst == nil && named.TypeParams().Len() > 0
108 }
109
110
111 func Comparable(T Type) bool {
112 return comparable(T, true, nil, nil)
113 }
114
115
116
117 func comparable(T Type, dynamic bool, seen map[Type]bool, reportf func(string, ...interface{})) bool {
118 if seen[T] {
119 return true
120 }
121 if seen == nil {
122 seen = make(map[Type]bool)
123 }
124 seen[T] = true
125
126 switch t := under(T).(type) {
127 case *Basic:
128
129
130 return t.kind != UntypedNil
131 case *Pointer, *Chan:
132 return true
133 case *Struct:
134 for _, f := range t.fields {
135 if !comparable(f.typ, dynamic, seen, nil) {
136 if reportf != nil {
137 reportf("struct containing %s cannot be compared", f.typ)
138 }
139 return false
140 }
141 }
142 return true
143 case *Array:
144 if !comparable(t.elem, dynamic, seen, nil) {
145 if reportf != nil {
146 reportf("%s cannot be compared", t)
147 }
148 return false
149 }
150 return true
151 case *Interface:
152 if dynamic && !isTypeParam(T) || t.typeSet().IsComparable(seen) {
153 return true
154 }
155 if reportf != nil {
156 if t.typeSet().IsEmpty() {
157 reportf("empty type set")
158 } else {
159 reportf("incomparable types in type set")
160 }
161 }
162
163 }
164 return false
165 }
166
167
168 func hasNil(t Type) bool {
169 switch u := under(t).(type) {
170 case *Basic:
171 return u.kind == UnsafePointer
172 case *Slice, *Pointer, *Signature, *Map, *Chan:
173 return true
174 case *Interface:
175 return !isTypeParam(t) || u.typeSet().underIs(func(u Type) bool {
176 return u != nil && hasNil(u)
177 })
178 }
179 return false
180 }
181
182
183 type ifacePair struct {
184 x, y *Interface
185 prev *ifacePair
186 }
187
188 func (p *ifacePair) identical(q *ifacePair) bool {
189 return p.x == q.x && p.y == q.y || p.x == q.y && p.y == q.x
190 }
191
192
193 func identical(x, y Type, cmpTags bool, p *ifacePair) bool {
194 if x == y {
195 return true
196 }
197
198 switch x := x.(type) {
199 case *Basic:
200
201
202
203 if y, ok := y.(*Basic); ok {
204 return x.kind == y.kind
205 }
206
207 case *Array:
208
209
210 if y, ok := y.(*Array); ok {
211
212
213 return (x.len < 0 || y.len < 0 || x.len == y.len) && identical(x.elem, y.elem, cmpTags, p)
214 }
215
216 case *Slice:
217
218 if y, ok := y.(*Slice); ok {
219 return identical(x.elem, y.elem, cmpTags, p)
220 }
221
222 case *Struct:
223
224
225
226
227 if y, ok := y.(*Struct); ok {
228 if x.NumFields() == y.NumFields() {
229 for i, f := range x.fields {
230 g := y.fields[i]
231 if f.embedded != g.embedded ||
232 cmpTags && x.Tag(i) != y.Tag(i) ||
233 !f.sameId(g.pkg, g.name) ||
234 !identical(f.typ, g.typ, cmpTags, p) {
235 return false
236 }
237 }
238 return true
239 }
240 }
241
242 case *Pointer:
243
244 if y, ok := y.(*Pointer); ok {
245 return identical(x.base, y.base, cmpTags, p)
246 }
247
248 case *Tuple:
249
250
251 if y, ok := y.(*Tuple); ok {
252 if x.Len() == y.Len() {
253 if x != nil {
254 for i, v := range x.vars {
255 w := y.vars[i]
256 if !identical(v.typ, w.typ, cmpTags, p) {
257 return false
258 }
259 }
260 }
261 return true
262 }
263 }
264
265 case *Signature:
266 y, _ := y.(*Signature)
267 if y == nil {
268 return false
269 }
270
271
272
273
274
275
276
277 if x.TypeParams().Len() != y.TypeParams().Len() {
278 return false
279 }
280
281
282
283 yparams := y.params
284 yresults := y.results
285
286 if x.TypeParams().Len() > 0 {
287
288
289 xtparams := x.TypeParams().list()
290 ytparams := y.TypeParams().list()
291
292 var targs []Type
293 for i := range xtparams {
294 targs = append(targs, x.TypeParams().At(i))
295 }
296 smap := makeSubstMap(ytparams, targs)
297
298 var check *Checker
299 ctxt := NewContext()
300
301
302 for i, xtparam := range xtparams {
303 ybound := check.subst(token.NoPos, ytparams[i].bound, smap, nil, ctxt)
304 if !identical(xtparam.bound, ybound, cmpTags, p) {
305 return false
306 }
307 }
308
309 yparams = check.subst(token.NoPos, y.params, smap, nil, ctxt).(*Tuple)
310 yresults = check.subst(token.NoPos, y.results, smap, nil, ctxt).(*Tuple)
311 }
312
313 return x.variadic == y.variadic &&
314 identical(x.params, yparams, cmpTags, p) &&
315 identical(x.results, yresults, cmpTags, p)
316
317 case *Union:
318 if y, _ := y.(*Union); y != nil {
319
320
321 unionSets := make(map[*Union]*_TypeSet)
322 xset := computeUnionTypeSet(nil, unionSets, token.NoPos, x)
323 yset := computeUnionTypeSet(nil, unionSets, token.NoPos, y)
324 return xset.terms.equal(yset.terms)
325 }
326
327 case *Interface:
328
329
330
331
332
333
334
335 if y, ok := y.(*Interface); ok {
336 xset := x.typeSet()
337 yset := y.typeSet()
338 if xset.comparable != yset.comparable {
339 return false
340 }
341 if !xset.terms.equal(yset.terms) {
342 return false
343 }
344 a := xset.methods
345 b := yset.methods
346 if len(a) == len(b) {
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369 q := &ifacePair{x, y, p}
370 for p != nil {
371 if p.identical(q) {
372 return true
373 }
374 p = p.prev
375 }
376 if debug {
377 assertSortedMethods(a)
378 assertSortedMethods(b)
379 }
380 for i, f := range a {
381 g := b[i]
382 if f.Id() != g.Id() || !identical(f.typ, g.typ, cmpTags, q) {
383 return false
384 }
385 }
386 return true
387 }
388 }
389
390 case *Map:
391
392 if y, ok := y.(*Map); ok {
393 return identical(x.key, y.key, cmpTags, p) && identical(x.elem, y.elem, cmpTags, p)
394 }
395
396 case *Chan:
397
398
399 if y, ok := y.(*Chan); ok {
400 return x.dir == y.dir && identical(x.elem, y.elem, cmpTags, p)
401 }
402
403 case *Named:
404
405
406 if y, ok := y.(*Named); ok {
407 xargs := x.TypeArgs().list()
408 yargs := y.TypeArgs().list()
409
410 if len(xargs) != len(yargs) {
411 return false
412 }
413
414 if len(xargs) > 0 {
415
416
417 if !Identical(x.Origin(), y.Origin()) {
418 return false
419 }
420 for i, xa := range xargs {
421 if !Identical(xa, yargs[i]) {
422 return false
423 }
424 }
425 return true
426 }
427
428
429
430
431 return x.obj == y.obj
432 }
433
434 case *TypeParam:
435
436
437 case nil:
438
439
440 default:
441 unreachable()
442 }
443
444 return false
445 }
446
447
448
449
450 func identicalInstance(xorig Type, xargs []Type, yorig Type, yargs []Type) bool {
451 if len(xargs) != len(yargs) {
452 return false
453 }
454
455 for i, xa := range xargs {
456 if !Identical(xa, yargs[i]) {
457 return false
458 }
459 }
460
461 return Identical(xorig, yorig)
462 }
463
464
465
466
467 func Default(t Type) Type {
468 if t, ok := t.(*Basic); ok {
469 switch t.kind {
470 case UntypedBool:
471 return Typ[Bool]
472 case UntypedInt:
473 return Typ[Int]
474 case UntypedRune:
475 return universeRune
476 case UntypedFloat:
477 return Typ[Float64]
478 case UntypedComplex:
479 return Typ[Complex128]
480 case UntypedString:
481 return Typ[String]
482 }
483 }
484 return t
485 }
486
View as plain text