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 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 func allBasic(t Type, info BasicInfo) bool {
55 if tpar, _ := Unalias(t).(*TypeParam); tpar != nil {
56 return tpar.is(func(t *term) bool { return t != nil && isBasic(t.typ, info) })
57 }
58 return isBasic(t, info)
59 }
60
61
62
63
64 func hasName(t Type) bool {
65 switch Unalias(t).(type) {
66 case *Basic, *Named, *TypeParam:
67 return true
68 }
69 return false
70 }
71
72
73
74
75 func isTypeLit(t Type) bool {
76 switch Unalias(t).(type) {
77 case *Named, *TypeParam:
78 return false
79 }
80 return true
81 }
82
83
84
85
86 func isTyped(t Type) bool {
87
88
89 b, _ := t.(*Basic)
90 return b == nil || b.info&IsUntyped == 0
91 }
92
93
94
95 func isUntyped(t Type) bool {
96 return !isTyped(t)
97 }
98
99
100
101 func isUntypedNumeric(t Type) bool {
102
103
104 b, _ := t.(*Basic)
105 return b != nil && b.info&IsUntyped != 0 && b.info&IsNumeric != 0
106 }
107
108
109 func IsInterface(t Type) bool {
110 _, ok := under(t).(*Interface)
111 return ok
112 }
113
114
115 func isNonTypeParamInterface(t Type) bool {
116 return !isTypeParam(t) && IsInterface(t)
117 }
118
119
120 func isTypeParam(t Type) bool {
121 _, ok := Unalias(t).(*TypeParam)
122 return ok
123 }
124
125
126
127
128
129 func hasEmptyTypeset(t Type) bool {
130 if tpar, _ := Unalias(t).(*TypeParam); tpar != nil && tpar.bound != nil {
131 iface, _ := safeUnderlying(tpar.bound).(*Interface)
132 return iface != nil && iface.tset != nil && iface.tset.IsEmpty()
133 }
134 return false
135 }
136
137
138
139
140 func isGeneric(t Type) bool {
141
142 if alias, _ := t.(*Alias); alias != nil && alias.tparams != nil && alias.targs == nil {
143 return true
144 }
145 named := asNamed(t)
146 return named != nil && named.obj != nil && named.inst == nil && named.TypeParams().Len() > 0
147 }
148
149
150 func Comparable(T Type) bool {
151 return comparableType(T, true, nil) == nil
152 }
153
154
155
156
157 func comparableType(T Type, dynamic bool, seen map[Type]bool) *typeError {
158 if seen[T] {
159 return nil
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 if t.kind == UntypedNil {
170 return typeErrorf("")
171 }
172
173 case *Pointer, *Chan:
174
175
176 case *Struct:
177 for _, f := range t.fields {
178 if comparableType(f.typ, dynamic, seen) != nil {
179 return typeErrorf("struct containing %s cannot be compared", f.typ)
180 }
181 }
182
183 case *Array:
184 if comparableType(t.elem, dynamic, seen) != nil {
185 return typeErrorf("%s cannot be compared", T)
186 }
187
188 case *Interface:
189 if dynamic && !isTypeParam(T) || t.typeSet().IsComparable(seen) {
190 return nil
191 }
192 var cause string
193 if t.typeSet().IsEmpty() {
194 cause = "empty type set"
195 } else {
196 cause = "incomparable types in type set"
197 }
198 return typeErrorf(cause)
199
200 default:
201 return typeErrorf("")
202 }
203
204 return nil
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) || underIs(t, 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 !slices.EqualFunc(xargs, yargs, Identical) {
511 return false
512 }
513
514 return Identical(xorig, yorig)
515 }
516
517
518
519
520 func Default(t Type) Type {
521
522
523 if t, _ := t.(*Basic); t != nil {
524 switch t.kind {
525 case UntypedBool:
526 return Typ[Bool]
527 case UntypedInt:
528 return Typ[Int]
529 case UntypedRune:
530 return universeRune
531 case UntypedFloat:
532 return Typ[Float64]
533 case UntypedComplex:
534 return Typ[Complex128]
535 case UntypedString:
536 return Typ[String]
537 }
538 }
539 return t
540 }
541
542
543
544
545
546 func maxType(x, y Type) Type {
547
548
549 if x == y {
550 return x
551 }
552 if isUntypedNumeric(x) && isUntypedNumeric(y) {
553
554 if x.(*Basic).kind > y.(*Basic).kind {
555 return x
556 }
557 return y
558 }
559 return nil
560 }
561
562
563 func clone[P *T, T any](p P) P {
564 c := *p
565 return &c
566 }
567
568
569 func isValidName(s string) bool {
570 for i, ch := range s {
571 if !(unicode.IsLetter(ch) || ch == '_' || i > 0 && unicode.IsDigit(ch)) {
572 return false
573 }
574 }
575 return true
576 }
577
View as plain text