1
2
3
4
5 package typecheck
6
7 import (
8 "fmt"
9 "slices"
10 "strings"
11
12 "cmd/compile/internal/base"
13 "cmd/compile/internal/ir"
14 "cmd/compile/internal/types"
15 "cmd/internal/obj"
16 "cmd/internal/src"
17 )
18
19 func AssignConv(n ir.Node, t *types.Type, context string) ir.Node {
20 return assignconvfn(n, t, func() string { return context })
21 }
22
23
24 func LookupNum(prefix string, n int) *types.Sym {
25 return types.LocalPkg.LookupNum(prefix, n)
26 }
27
28
29 func NewFuncParams(origs []*types.Field) []*types.Field {
30 res := make([]*types.Field, len(origs))
31 for i, orig := range origs {
32 p := types.NewField(orig.Pos, orig.Sym, orig.Type)
33 p.SetIsDDD(orig.IsDDD())
34 res[i] = p
35 }
36 return res
37 }
38
39
40 func NodAddr(n ir.Node) *ir.AddrExpr {
41 return NodAddrAt(base.Pos, n)
42 }
43
44
45 func NodAddrAt(pos src.XPos, n ir.Node) *ir.AddrExpr {
46 return ir.NewAddrExpr(pos, Expr(n))
47 }
48
49
50
51 func LinksymAddr(pos src.XPos, lsym *obj.LSym, typ *types.Type) *ir.AddrExpr {
52 n := ir.NewLinksymExpr(pos, lsym, typ)
53 return Expr(NodAddrAt(pos, n)).(*ir.AddrExpr)
54 }
55
56 func NodNil() ir.Node {
57 return ir.NewNilExpr(base.Pos, types.Types[types.TNIL])
58 }
59
60
61
62
63 func AddImplicitDots(n *ir.SelectorExpr) *ir.SelectorExpr {
64 n.X = typecheck(n.X, ctxType|ctxExpr)
65 t := n.X.Type()
66 if t == nil {
67 return n
68 }
69
70 if n.X.Op() == ir.OTYPE {
71 return n
72 }
73
74 s := n.Sel
75 if s == nil {
76 return n
77 }
78
79 switch path, ambig := dotpath(s, t, nil, false); {
80 case path != nil:
81
82 for c := len(path) - 1; c >= 0; c-- {
83 dot := ir.NewSelectorExpr(n.Pos(), ir.ODOT, n.X, path[c].field.Sym)
84 dot.SetImplicit(true)
85 dot.SetType(path[c].field.Type)
86 n.X = dot
87 }
88 case ambig:
89 base.Errorf("ambiguous selector %v", n)
90 n.X = nil
91 }
92
93 return n
94 }
95
96
97
98 func CalcMethods(t *types.Type) {
99 if t == nil || len(t.AllMethods()) != 0 {
100 return
101 }
102
103
104
105 for _, f := range t.Methods() {
106 f.Sym.SetUniq(true)
107 }
108
109
110 slist = slist[:0]
111 expand1(t, true)
112
113
114 var ms []*types.Field
115 for i, sl := range slist {
116 slist[i].field = nil
117 sl.field.Sym.SetUniq(false)
118
119 var f *types.Field
120 path, _ := dotpath(sl.field.Sym, t, &f, false)
121 if path == nil {
122 continue
123 }
124
125
126 if !f.IsMethod() {
127 continue
128 }
129
130
131 f = f.Copy()
132 f.Embedded = 1
133 for _, d := range path {
134 if d.field.Type.IsPtr() {
135 f.Embedded = 2
136 break
137 }
138 }
139 ms = append(ms, f)
140 }
141
142 for _, f := range t.Methods() {
143 f.Sym.SetUniq(false)
144 }
145
146 ms = append(ms, t.Methods()...)
147 slices.SortFunc(ms, types.MethodsByNameCmp)
148 t.SetAllMethods(ms)
149 }
150
151
152
153
154
155
156
157 func adddot1(s *types.Sym, t *types.Type, d int, save **types.Field, ignorecase bool) (c int, more bool) {
158 if t.Recur() {
159 return
160 }
161 t.SetRecur(true)
162 defer t.SetRecur(false)
163
164 var u *types.Type
165 d--
166 if d < 0 {
167
168
169
170 c = lookdot0(s, t, save, ignorecase)
171 if c != 0 {
172 return c, false
173 }
174 }
175
176 u = t
177 if u.IsPtr() {
178 u = u.Elem()
179 }
180 if !u.IsStruct() && !u.IsInterface() {
181 return c, false
182 }
183
184 var fields []*types.Field
185 if u.IsStruct() {
186 fields = u.Fields()
187 } else {
188 fields = u.AllMethods()
189 }
190 for _, f := range fields {
191 if f.Embedded == 0 || f.Sym == nil {
192 continue
193 }
194 if d < 0 {
195
196 return c, true
197 }
198 a, more1 := adddot1(s, f.Type, d, save, ignorecase)
199 if a != 0 && c == 0 {
200 dotlist[d].field = f
201 }
202 c += a
203 if more1 {
204 more = true
205 }
206 }
207
208 return c, more
209 }
210
211
212
213
214 var dotlist = make([]dlist, 10)
215
216
217 func assignconvfn(n ir.Node, t *types.Type, context func() string) ir.Node {
218 if n == nil || n.Type() == nil {
219 return n
220 }
221
222 if t.Kind() == types.TBLANK && n.Type().Kind() == types.TNIL {
223 base.Errorf("use of untyped nil")
224 }
225
226 n = convlit1(n, t, false, context)
227 if n.Type() == nil {
228 base.Fatalf("cannot assign %v to %v", n, t)
229 }
230 if n.Type().IsUntyped() {
231 base.Fatalf("%L has untyped type", n)
232 }
233 if t.Kind() == types.TBLANK {
234 return n
235 }
236 if types.Identical(n.Type(), t) {
237 return n
238 }
239
240 op, why := assignOp(n.Type(), t)
241 if op == ir.OXXX {
242 base.Errorf("cannot use %L as type %v in %s%s", n, t, context(), why)
243 op = ir.OCONV
244 }
245
246 r := ir.NewConvExpr(base.Pos, op, t, n)
247 r.SetTypecheck(1)
248 r.SetImplicit(true)
249 return r
250 }
251
252
253
254
255
256 func assignOp(src, dst *types.Type) (ir.Op, string) {
257 if src == dst {
258 return ir.OCONVNOP, ""
259 }
260 if src == nil || dst == nil || src.Kind() == types.TFORW || dst.Kind() == types.TFORW || src.Underlying() == nil || dst.Underlying() == nil {
261 return ir.OXXX, ""
262 }
263
264
265 if types.Identical(src, dst) {
266 return ir.OCONVNOP, ""
267 }
268
269
270
271
272
273
274
275
276
277 if types.Identical(src.Underlying(), dst.Underlying()) {
278 if src.IsEmptyInterface() {
279
280
281 return ir.OCONVNOP, ""
282 }
283 if (src.Sym() == nil || dst.Sym() == nil) && !src.IsInterface() {
284
285
286
287 return ir.OCONVNOP, ""
288 }
289 if src.IsShape() || dst.IsShape() {
290
291
292 return ir.OCONVNOP, ""
293 }
294 }
295
296
297 if dst.IsInterface() && src.Kind() != types.TNIL {
298 if src.IsShape() {
299
300
301
302 return ir.OCONVIFACE, ""
303 }
304 if src.HasShape() {
305
306
307 return ir.OCONVIFACE, ""
308 }
309
310 why := ImplementsExplain(src, dst)
311 if why == "" {
312 return ir.OCONVIFACE, ""
313 }
314 return ir.OXXX, ":\n\t" + why
315 }
316
317 if isptrto(dst, types.TINTER) {
318 why := fmt.Sprintf(":\n\t%v is pointer to interface, not interface", dst)
319 return ir.OXXX, why
320 }
321
322 if src.IsInterface() && dst.Kind() != types.TBLANK {
323 var why string
324 if Implements(dst, src) {
325 why = ": need type assertion"
326 }
327 return ir.OXXX, why
328 }
329
330
331
332
333 if src.IsChan() && src.ChanDir() == types.Cboth && dst.IsChan() {
334 if types.Identical(src.Elem(), dst.Elem()) && (src.Sym() == nil || dst.Sym() == nil) {
335 return ir.OCONVNOP, ""
336 }
337 }
338
339
340 if src.Kind() == types.TNIL {
341 switch dst.Kind() {
342 case types.TPTR,
343 types.TFUNC,
344 types.TMAP,
345 types.TCHAN,
346 types.TINTER,
347 types.TSLICE:
348 return ir.OCONVNOP, ""
349 }
350 }
351
352
353
354
355 if dst.Kind() == types.TBLANK {
356 return ir.OCONVNOP, ""
357 }
358
359 return ir.OXXX, ""
360 }
361
362
363
364
365
366
367 func convertOp(srcConstant bool, src, dst *types.Type) (ir.Op, string) {
368 if src == dst {
369 return ir.OCONVNOP, ""
370 }
371 if src == nil || dst == nil {
372 return ir.OXXX, ""
373 }
374
375
376
377
378
379 if src.IsPtr() && dst.IsPtr() && dst.Elem().NotInHeap() && !src.Elem().NotInHeap() {
380 why := fmt.Sprintf(":\n\t%v is incomplete (or unallocatable), but %v is not", dst.Elem(), src.Elem())
381 return ir.OXXX, why
382 }
383
384 if src.IsString() && dst.IsSlice() && dst.Elem().NotInHeap() && (dst.Elem().Kind() == types.ByteType.Kind() || dst.Elem().Kind() == types.RuneType.Kind()) {
385 why := fmt.Sprintf(":\n\t%v is incomplete (or unallocatable)", dst.Elem())
386 return ir.OXXX, why
387 }
388
389
390 op, why := assignOp(src, dst)
391 if op != ir.OXXX {
392 return op, why
393 }
394
395
396
397
398
399 if src.IsInterface() || dst.IsInterface() {
400 return ir.OXXX, why
401 }
402
403
404 if types.IdenticalIgnoreTags(src.Underlying(), dst.Underlying()) {
405 return ir.OCONVNOP, ""
406 }
407
408
409
410 if src.IsPtr() && dst.IsPtr() && src.Sym() == nil && dst.Sym() == nil {
411 if types.IdenticalIgnoreTags(src.Elem().Underlying(), dst.Elem().Underlying()) {
412 return ir.OCONVNOP, ""
413 }
414 }
415
416
417 if (src.IsInteger() || src.IsFloat()) && (dst.IsInteger() || dst.IsFloat()) {
418 if types.SimType[src.Kind()] == types.SimType[dst.Kind()] {
419 return ir.OCONVNOP, ""
420 }
421 return ir.OCONV, ""
422 }
423
424
425 if src.IsComplex() && dst.IsComplex() {
426 if types.SimType[src.Kind()] == types.SimType[dst.Kind()] {
427 return ir.OCONVNOP, ""
428 }
429 return ir.OCONV, ""
430 }
431
432
433
434
435 if srcConstant && (src.IsInteger() || src.IsFloat() || src.IsComplex()) && (dst.IsInteger() || dst.IsFloat() || dst.IsComplex()) {
436 return ir.OCONV, ""
437 }
438
439
440
441 if src.IsInteger() && dst.IsString() {
442 return ir.ORUNESTR, ""
443 }
444
445 if src.IsSlice() && dst.IsString() {
446 if src.Elem().Kind() == types.ByteType.Kind() {
447 return ir.OBYTES2STR, ""
448 }
449 if src.Elem().Kind() == types.RuneType.Kind() {
450 return ir.ORUNES2STR, ""
451 }
452 }
453
454
455
456 if src.IsString() && dst.IsSlice() {
457 if dst.Elem().Kind() == types.ByteType.Kind() {
458 return ir.OSTR2BYTES, ""
459 }
460 if dst.Elem().Kind() == types.RuneType.Kind() {
461 return ir.OSTR2RUNES, ""
462 }
463 }
464
465
466 if (src.IsPtr() || src.IsUintptr()) && dst.IsUnsafePtr() {
467 return ir.OCONVNOP, ""
468 }
469
470
471 if src.IsUnsafePtr() && (dst.IsPtr() || dst.IsUintptr()) {
472 return ir.OCONVNOP, ""
473 }
474
475
476
477 if src.IsSlice() {
478 if dst.IsArray() && types.Identical(src.Elem(), dst.Elem()) {
479 return ir.OSLICE2ARR, ""
480 }
481 if dst.IsPtr() && dst.Elem().IsArray() &&
482 types.Identical(src.Elem(), dst.Elem().Elem()) {
483 return ir.OSLICE2ARRPTR, ""
484 }
485 }
486
487 return ir.OXXX, ""
488 }
489
490
491
492
493
494 type dlist struct {
495 field *types.Field
496 }
497
498
499
500
501
502 func dotpath(s *types.Sym, t *types.Type, save **types.Field, ignorecase bool) (path []dlist, ambig bool) {
503
504
505
506
507
508
509 for d := 0; ; d++ {
510 if d > len(dotlist) {
511 dotlist = append(dotlist, dlist{})
512 }
513 if c, more := adddot1(s, t, d, save, ignorecase); c == 1 {
514 return dotlist[:d], false
515 } else if c > 1 {
516 return nil, true
517 } else if !more {
518 return nil, false
519 }
520 }
521 }
522
523 func expand0(t *types.Type) {
524 u := t
525 if u.IsPtr() {
526 u = u.Elem()
527 }
528
529 if u.IsInterface() {
530 for _, f := range u.AllMethods() {
531 if f.Sym.Uniq() {
532 continue
533 }
534 f.Sym.SetUniq(true)
535 slist = append(slist, symlink{field: f})
536 }
537
538 return
539 }
540
541 u = types.ReceiverBaseType(t)
542 if u != nil {
543 for _, f := range u.Methods() {
544 if f.Sym.Uniq() {
545 continue
546 }
547 f.Sym.SetUniq(true)
548 slist = append(slist, symlink{field: f})
549 }
550 }
551 }
552
553 func expand1(t *types.Type, top bool) {
554 if t.Recur() {
555 return
556 }
557 t.SetRecur(true)
558
559 if !top {
560 expand0(t)
561 }
562
563 u := t
564 if u.IsPtr() {
565 u = u.Elem()
566 }
567
568 if u.IsStruct() || u.IsInterface() {
569 var fields []*types.Field
570 if u.IsStruct() {
571 fields = u.Fields()
572 } else {
573 fields = u.AllMethods()
574 }
575 for _, f := range fields {
576 if f.Embedded == 0 {
577 continue
578 }
579 if f.Sym == nil {
580 continue
581 }
582 expand1(f.Type, false)
583 }
584 }
585
586 t.SetRecur(false)
587 }
588
589 func ifacelookdot(s *types.Sym, t *types.Type, ignorecase bool) *types.Field {
590 if t == nil {
591 return nil
592 }
593
594 var m *types.Field
595 path, _ := dotpath(s, t, &m, ignorecase)
596 if path == nil {
597 return nil
598 }
599
600 if !m.IsMethod() {
601 return nil
602 }
603
604 return m
605 }
606
607
608
609 func Implements(t, iface *types.Type) bool {
610 var missing, have *types.Field
611 var ptr int
612 return implements(t, iface, &missing, &have, &ptr)
613 }
614
615
616
617
618 func ImplementsExplain(t, iface *types.Type) string {
619 var missing, have *types.Field
620 var ptr int
621 if implements(t, iface, &missing, &have, &ptr) {
622 return ""
623 }
624
625 if isptrto(t, types.TINTER) {
626 return fmt.Sprintf("%v is pointer to interface, not interface", t)
627 } else if have != nil && have.Sym == missing.Sym && have.Nointerface() {
628 return fmt.Sprintf("%v does not implement %v (%v method is marked 'nointerface')", t, iface, missing.Sym)
629 } else if have != nil && have.Sym == missing.Sym {
630 return fmt.Sprintf("%v does not implement %v (wrong type for %v method)\n"+
631 "\t\thave %v%S\n\t\twant %v%S", t, iface, missing.Sym, have.Sym, have.Type, missing.Sym, missing.Type)
632 } else if ptr != 0 {
633 return fmt.Sprintf("%v does not implement %v (%v method has pointer receiver)", t, iface, missing.Sym)
634 } else if have != nil {
635 return fmt.Sprintf("%v does not implement %v (missing %v method)\n"+
636 "\t\thave %v%S\n\t\twant %v%S", t, iface, missing.Sym, have.Sym, have.Type, missing.Sym, missing.Type)
637 }
638 return fmt.Sprintf("%v does not implement %v (missing %v method)", t, iface, missing.Sym)
639 }
640
641
642
643
644
645
646 func implements(t, iface *types.Type, m, samename **types.Field, ptr *int) bool {
647 t0 := t
648 if t == nil {
649 return false
650 }
651
652 if t.IsInterface() {
653 i := 0
654 tms := t.AllMethods()
655 for _, im := range iface.AllMethods() {
656 for i < len(tms) && tms[i].Sym != im.Sym {
657 i++
658 }
659 if i == len(tms) {
660 *m = im
661 *samename = nil
662 *ptr = 0
663 return false
664 }
665 tm := tms[i]
666 if !types.Identical(tm.Type, im.Type) {
667 *m = im
668 *samename = tm
669 *ptr = 0
670 return false
671 }
672 }
673
674 return true
675 }
676
677 t = types.ReceiverBaseType(t)
678 var tms []*types.Field
679 if t != nil {
680 CalcMethods(t)
681 tms = t.AllMethods()
682 }
683 i := 0
684 for _, im := range iface.AllMethods() {
685 for i < len(tms) && tms[i].Sym != im.Sym {
686 i++
687 }
688 if i == len(tms) {
689 *m = im
690 *samename = ifacelookdot(im.Sym, t, true)
691 *ptr = 0
692 return false
693 }
694 tm := tms[i]
695 if tm.Nointerface() || !types.Identical(tm.Type, im.Type) {
696 *m = im
697 *samename = tm
698 *ptr = 0
699 return false
700 }
701
702
703
704 if !types.IsMethodApplicable(t0, tm) {
705 if false && base.Flag.LowerR != 0 {
706 base.Errorf("interface pointer mismatch")
707 }
708
709 *m = im
710 *samename = nil
711 *ptr = 1
712 return false
713 }
714 }
715
716 return true
717 }
718
719 func isptrto(t *types.Type, et types.Kind) bool {
720 if t == nil {
721 return false
722 }
723 if !t.IsPtr() {
724 return false
725 }
726 t = t.Elem()
727 if t == nil {
728 return false
729 }
730 if t.Kind() != et {
731 return false
732 }
733 return true
734 }
735
736
737
738
739 func lookdot0(s *types.Sym, t *types.Type, save **types.Field, ignorecase bool) int {
740 u := t
741 if u.IsPtr() {
742 u = u.Elem()
743 }
744
745 c := 0
746 if u.IsStruct() || u.IsInterface() {
747 var fields []*types.Field
748 if u.IsStruct() {
749 fields = u.Fields()
750 } else {
751 fields = u.AllMethods()
752 }
753 for _, f := range fields {
754 if f.Sym == s || (ignorecase && f.IsMethod() && strings.EqualFold(f.Sym.Name, s.Name)) {
755 if save != nil {
756 *save = f
757 }
758 c++
759 }
760 }
761 }
762
763 u = t
764 if t.Sym() != nil && t.IsPtr() && !t.Elem().IsPtr() {
765
766 u = t.Elem()
767 }
768 u = types.ReceiverBaseType(u)
769 if u != nil {
770 for _, f := range u.Methods() {
771 if f.Embedded == 0 && (f.Sym == s || (ignorecase && strings.EqualFold(f.Sym.Name, s.Name))) {
772 if save != nil {
773 *save = f
774 }
775 c++
776 }
777 }
778 }
779
780 return c
781 }
782
783 var slist []symlink
784
785
786
787
788
789
790 type symlink struct {
791 field *types.Field
792 }
793
View as plain text