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