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