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