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