1
2
3
4
5
6
7 package types2
8
9 import (
10 "cmd/compile/internal/syntax"
11 "go/constant"
12 "go/token"
13 . "internal/types/errors"
14 )
15
16
17
18
19
20 func (check *Checker) builtin(x *operand, call *syntax.CallExpr, id builtinId) (_ bool) {
21 argList := call.ArgList
22
23
24 bin := predeclaredFuncs[id]
25 if hasDots(call) && id != _Append {
26 check.errorf(dddErrPos(call),
27 InvalidDotDotDot,
28 invalidOp+"invalid use of ... with built-in %s", bin.name)
29 check.use(argList...)
30 return
31 }
32
33
34
35
36
37
38 if id == _Len || id == _Cap {
39 defer func(b bool) {
40 check.hasCallOrRecv = b
41 }(check.hasCallOrRecv)
42 check.hasCallOrRecv = false
43 }
44
45
46
47
48 var args []*operand
49 var nargs int
50 switch id {
51 default:
52
53 args = check.exprList(argList)
54 nargs = len(args)
55 for _, a := range args {
56 if a.mode == invalid {
57 return
58 }
59 }
60
61 if nargs > 0 {
62 *x = *args[0]
63 }
64 case _Make, _New, _Offsetof, _Trace:
65
66 nargs = len(argList)
67 }
68
69
70 {
71 msg := ""
72 if nargs < bin.nargs {
73 msg = "not enough"
74 } else if !bin.variadic && nargs > bin.nargs {
75 msg = "too many"
76 }
77 if msg != "" {
78 check.errorf(argErrPos(call), WrongArgCount, invalidOp+"%s arguments for %v (expected %d, found %d)", msg, call, bin.nargs, nargs)
79 return
80 }
81 }
82
83 switch id {
84 case _Append:
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99 E, err := sliceElem(x)
100 if err != nil {
101 check.errorf(x, InvalidAppend, "invalid append: %s", err.format(check))
102 return
103 }
104
105
106
107 var sig *Signature
108 if nargs == 2 && hasDots(call) {
109 if ok, _ := x.assignableTo(check, NewSlice(universeByte), nil); ok {
110 y := args[1]
111 hasString := false
112 for _, u := range typeset(y.typ) {
113 if s, _ := u.(*Slice); s != nil && Identical(s.elem, universeByte) {
114
115 } else if isString(u) {
116
117 hasString = true
118 } else {
119 y = nil
120 break
121 }
122 }
123 if y != nil && hasString {
124
125 sig = makeSig(x.typ, x.typ, y.typ)
126 sig.variadic = true
127 }
128 }
129 }
130
131
132 if sig == nil {
133
134 sig = makeSig(x.typ, x.typ, NewSlice(E))
135 sig.variadic = true
136 check.arguments(call, sig, nil, nil, args, nil)
137
138 }
139
140 if check.recordTypes() {
141 check.recordBuiltinType(call.Fun, sig)
142 }
143 x.mode = value
144
145
146 case _Cap, _Len:
147
148
149 mode := invalid
150 var val constant.Value
151 switch t := arrayPtrDeref(x.typ.Underlying()).(type) {
152 case *Basic:
153 if isString(t) && id == _Len {
154 if x.mode == constant_ {
155 mode = constant_
156 val = constant.MakeInt64(int64(len(constant.StringVal(x.val))))
157 } else {
158 mode = value
159 }
160 }
161
162 case *Array:
163 mode = value
164
165
166
167
168 if !check.hasCallOrRecv {
169 mode = constant_
170 if t.len >= 0 {
171 val = constant.MakeInt64(t.len)
172 } else {
173 val = constant.MakeUnknown()
174 }
175 }
176
177 case *Slice, *Chan:
178 mode = value
179
180 case *Map:
181 if id == _Len {
182 mode = value
183 }
184
185 case *Interface:
186 if !isTypeParam(x.typ) {
187 break
188 }
189 if underIs(x.typ, func(u Type) bool {
190 switch t := arrayPtrDeref(u).(type) {
191 case *Basic:
192 if isString(t) && id == _Len {
193 return true
194 }
195 case *Array, *Slice, *Chan:
196 return true
197 case *Map:
198 if id == _Len {
199 return true
200 }
201 }
202 return false
203 }) {
204 mode = value
205 }
206 }
207
208 if mode == invalid {
209
210 if isValid(x.typ.Underlying()) {
211 code := InvalidCap
212 if id == _Len {
213 code = InvalidLen
214 }
215 check.errorf(x, code, invalidArg+"%s for built-in %s", x, bin.name)
216 }
217 return
218 }
219
220
221 if check.recordTypes() && mode != constant_ {
222 check.recordBuiltinType(call.Fun, makeSig(Typ[Int], x.typ))
223 }
224
225 x.mode = mode
226 x.typ = Typ[Int]
227 x.val = val
228
229 case _Clear:
230
231 check.verifyVersionf(call.Fun, go1_21, "clear")
232
233 if !underIs(x.typ, func(u Type) bool {
234 switch u.(type) {
235 case *Map, *Slice:
236 return true
237 }
238 check.errorf(x, InvalidClear, invalidArg+"cannot clear %s: argument must be (or constrained by) map or slice", x)
239 return false
240 }) {
241 return
242 }
243
244 x.mode = novalue
245 if check.recordTypes() {
246 check.recordBuiltinType(call.Fun, makeSig(nil, x.typ))
247 }
248
249 case _Close:
250
251 if !underIs(x.typ, func(u Type) bool {
252 uch, _ := u.(*Chan)
253 if uch == nil {
254 check.errorf(x, InvalidClose, invalidOp+"cannot close non-channel %s", x)
255 return false
256 }
257 if uch.dir == RecvOnly {
258 check.errorf(x, InvalidClose, invalidOp+"cannot close receive-only channel %s", x)
259 return false
260 }
261 return true
262 }) {
263 return
264 }
265 x.mode = novalue
266 if check.recordTypes() {
267 check.recordBuiltinType(call.Fun, makeSig(nil, x.typ))
268 }
269
270 case _Complex:
271
272 y := args[1]
273
274
275 d := 0
276 if isUntyped(x.typ) {
277 d |= 1
278 }
279 if isUntyped(y.typ) {
280 d |= 2
281 }
282 switch d {
283 case 0:
284
285 case 1:
286
287 check.convertUntyped(x, y.typ)
288 case 2:
289
290 check.convertUntyped(y, x.typ)
291 case 3:
292
293
294
295
296
297
298
299
300 if x.mode == constant_ && y.mode == constant_ {
301 toFloat := func(x *operand) {
302 if isNumeric(x.typ) && constant.Sign(constant.Imag(x.val)) == 0 {
303 x.typ = Typ[UntypedFloat]
304 }
305 }
306 toFloat(x)
307 toFloat(y)
308 } else {
309 check.convertUntyped(x, Typ[Float64])
310 check.convertUntyped(y, Typ[Float64])
311
312
313 }
314 }
315 if x.mode == invalid || y.mode == invalid {
316 return
317 }
318
319
320 if !Identical(x.typ, y.typ) {
321 check.errorf(x, InvalidComplex, invalidOp+"%v (mismatched types %s and %s)", call, x.typ, y.typ)
322 return
323 }
324
325
326
327 f := func(typ Type) Type {
328 assert(!isTypeParam(typ))
329 if t, _ := typ.Underlying().(*Basic); t != nil {
330 switch t.kind {
331 case Float32:
332 return Typ[Complex64]
333 case Float64:
334 return Typ[Complex128]
335 case UntypedFloat:
336 return Typ[UntypedComplex]
337 }
338 }
339 return nil
340 }
341 resTyp := check.applyTypeFunc(f, x, id)
342 if resTyp == nil {
343 check.errorf(x, InvalidComplex, invalidArg+"arguments have type %s, expected floating-point", x.typ)
344 return
345 }
346
347
348 if x.mode == constant_ && y.mode == constant_ {
349 x.val = constant.BinaryOp(constant.ToFloat(x.val), token.ADD, constant.MakeImag(constant.ToFloat(y.val)))
350 } else {
351 x.mode = value
352 }
353
354 if check.recordTypes() && x.mode != constant_ {
355 check.recordBuiltinType(call.Fun, makeSig(resTyp, x.typ, x.typ))
356 }
357
358 x.typ = resTyp
359
360 case _Copy:
361
362
363
364
365
366
367
368
369
370
371 y := args[1]
372 var special bool
373 if ok, _ := x.assignableTo(check, NewSlice(universeByte), nil); ok {
374 special = true
375 for _, u := range typeset(y.typ) {
376 if s, _ := u.(*Slice); s != nil && Identical(s.elem, universeByte) {
377
378 } else if isString(u) {
379
380 } else {
381 special = false
382 break
383 }
384 }
385 }
386
387
388 if !special {
389
390
391 dstE, err := sliceElem(x)
392 if err != nil {
393 check.errorf(x, InvalidCopy, "invalid copy: %s", err.format(check))
394 return
395 }
396 srcE, err := sliceElem(y)
397 if err != nil {
398
399 if !allString(y.typ) {
400 check.errorf(y, InvalidCopy, "invalid copy: %s", err.format(check))
401 return
402 }
403 srcE = universeByte
404 }
405 if !Identical(dstE, srcE) {
406 check.errorf(x, InvalidCopy, "invalid copy: arguments %s and %s have different element types %s and %s", x, y, dstE, srcE)
407 return
408 }
409 }
410
411 if check.recordTypes() {
412 check.recordBuiltinType(call.Fun, makeSig(Typ[Int], x.typ, y.typ))
413 }
414 x.mode = value
415 x.typ = Typ[Int]
416
417 case _Delete:
418
419
420
421 map_ := x.typ
422 var key Type
423 if !underIs(map_, func(u Type) bool {
424 map_, _ := u.(*Map)
425 if map_ == nil {
426 check.errorf(x, InvalidDelete, invalidArg+"%s is not a map", x)
427 return false
428 }
429 if key != nil && !Identical(map_.key, key) {
430 check.errorf(x, InvalidDelete, invalidArg+"maps of %s must have identical key types", x)
431 return false
432 }
433 key = map_.key
434 return true
435 }) {
436 return
437 }
438
439 *x = *args[1]
440 check.assignment(x, key, "argument to delete")
441 if x.mode == invalid {
442 return
443 }
444
445 x.mode = novalue
446 if check.recordTypes() {
447 check.recordBuiltinType(call.Fun, makeSig(nil, map_, key))
448 }
449
450 case _Imag, _Real:
451
452
453
454
455 if isUntyped(x.typ) {
456 if x.mode == constant_ {
457
458
459 if isNumeric(x.typ) {
460 x.typ = Typ[UntypedComplex]
461 }
462 } else {
463
464
465
466
467 check.convertUntyped(x, Typ[Complex128])
468
469 if x.mode == invalid {
470 return
471 }
472 }
473 }
474
475
476
477 f := func(typ Type) Type {
478 assert(!isTypeParam(typ))
479 if t, _ := typ.Underlying().(*Basic); t != nil {
480 switch t.kind {
481 case Complex64:
482 return Typ[Float32]
483 case Complex128:
484 return Typ[Float64]
485 case UntypedComplex:
486 return Typ[UntypedFloat]
487 }
488 }
489 return nil
490 }
491 resTyp := check.applyTypeFunc(f, x, id)
492 if resTyp == nil {
493 code := InvalidImag
494 if id == _Real {
495 code = InvalidReal
496 }
497 check.errorf(x, code, invalidArg+"argument has type %s, expected complex type", x.typ)
498 return
499 }
500
501
502 if x.mode == constant_ {
503 if id == _Real {
504 x.val = constant.Real(x.val)
505 } else {
506 x.val = constant.Imag(x.val)
507 }
508 } else {
509 x.mode = value
510 }
511
512 if check.recordTypes() && x.mode != constant_ {
513 check.recordBuiltinType(call.Fun, makeSig(resTyp, x.typ))
514 }
515
516 x.typ = resTyp
517
518 case _Make:
519
520
521
522 arg0 := argList[0]
523 T := check.varType(arg0)
524 if !isValid(T) {
525 return
526 }
527
528 u, err := commonUnder(T, func(_, u Type) *typeError {
529 switch u.(type) {
530 case *Slice, *Map, *Chan:
531 return nil
532 case nil:
533 return typeErrorf("no specific type")
534 default:
535 return typeErrorf("type must be slice, map, or channel")
536 }
537 })
538 if err != nil {
539 check.errorf(arg0, InvalidMake, invalidArg+"cannot make %s: %s", arg0, err.format(check))
540 return
541 }
542
543 var min int
544 switch u.(type) {
545 case *Slice:
546 min = 2
547 case *Map, *Chan:
548 min = 1
549 default:
550
551 panic("unreachable")
552 }
553 if nargs < min || min+1 < nargs {
554 check.errorf(call, WrongArgCount, invalidOp+"%v expects %d or %d arguments; found %d", call, min, min+1, nargs)
555 return
556 }
557
558 types := []Type{T}
559 var sizes []int64
560 for _, arg := range argList[1:] {
561 typ, size := check.index(arg, -1)
562 types = append(types, typ)
563 if size >= 0 {
564 sizes = append(sizes, size)
565 }
566 }
567 if len(sizes) == 2 && sizes[0] > sizes[1] {
568 check.error(argList[1], SwappedMakeArgs, invalidArg+"length and capacity swapped")
569
570 }
571 x.mode = value
572 x.typ = T
573 if check.recordTypes() {
574 check.recordBuiltinType(call.Fun, makeSig(x.typ, types...))
575 }
576
577 case _Max, _Min:
578
579
580 check.verifyVersionf(call.Fun, go1_21, "built-in %s", bin.name)
581
582 op := token.LSS
583 if id == _Max {
584 op = token.GTR
585 }
586
587 for i, a := range args {
588 if a.mode == invalid {
589 return
590 }
591
592 if !allOrdered(a.typ) {
593 check.errorf(a, InvalidMinMaxOperand, invalidArg+"%s cannot be ordered", a)
594 return
595 }
596
597
598 if i > 0 {
599 check.matchTypes(x, a)
600 if x.mode == invalid {
601 return
602 }
603
604 if !Identical(x.typ, a.typ) {
605 check.errorf(a, MismatchedTypes, invalidArg+"mismatched types %s (previous argument) and %s (type of %s)", x.typ, a.typ, a.expr)
606 return
607 }
608
609 if x.mode == constant_ && a.mode == constant_ {
610 if constant.Compare(a.val, op, x.val) {
611 *x = *a
612 }
613 } else {
614 x.mode = value
615 }
616 }
617 }
618
619
620 if x.mode != constant_ {
621 x.mode = value
622
623 check.assignment(x, &emptyInterface, "argument to built-in "+bin.name)
624 if x.mode == invalid {
625 return
626 }
627 }
628
629
630 for _, a := range args {
631 check.updateExprType(a.expr, x.typ, true)
632 }
633
634 if check.recordTypes() && x.mode != constant_ {
635 types := make([]Type, nargs)
636 for i := range types {
637 types[i] = x.typ
638 }
639 check.recordBuiltinType(call.Fun, makeSig(x.typ, types...))
640 }
641
642 case _New:
643
644
645 arg := argList[0]
646 check.exprOrType(x, arg, false)
647 check.exclude(x, 1<<novalue|1<<builtin)
648 switch x.mode {
649 case invalid:
650 return
651 case typexpr:
652
653 check.validVarType(arg, x.typ)
654 default:
655
656 if isUntyped(x.typ) {
657
658 check.assignment(x, nil, "argument to new")
659 if x.mode == invalid {
660 return
661 }
662 assert(isTyped(x.typ))
663 }
664
665 check.verifyVersionf(call.Fun, go1_26, "new(%s)", arg)
666 }
667
668 T := x.typ
669 x.mode = value
670 x.typ = NewPointer(T)
671 if check.recordTypes() {
672 check.recordBuiltinType(call.Fun, makeSig(x.typ, T))
673 }
674
675 case _Panic:
676
677
678
679 if check.sig != nil && check.sig.results.Len() > 0 {
680
681 p := check.isPanic
682 if p == nil {
683
684 p = make(map[*syntax.CallExpr]bool)
685 check.isPanic = p
686 }
687 p[call] = true
688 }
689
690 check.assignment(x, &emptyInterface, "argument to panic")
691 if x.mode == invalid {
692 return
693 }
694
695 x.mode = novalue
696 if check.recordTypes() {
697 check.recordBuiltinType(call.Fun, makeSig(nil, &emptyInterface))
698 }
699
700 case _Print, _Println:
701
702
703 var params []Type
704 if nargs > 0 {
705 params = make([]Type, nargs)
706 for i, a := range args {
707 check.assignment(a, nil, "argument to built-in "+predeclaredFuncs[id].name)
708 if a.mode == invalid {
709 return
710 }
711 params[i] = a.typ
712 }
713 }
714
715 x.mode = novalue
716 if check.recordTypes() {
717 check.recordBuiltinType(call.Fun, makeSig(nil, params...))
718 }
719
720 case _Recover:
721
722 x.mode = value
723 x.typ = &emptyInterface
724 if check.recordTypes() {
725 check.recordBuiltinType(call.Fun, makeSig(x.typ))
726 }
727
728 case _Add:
729
730 check.verifyVersionf(call.Fun, go1_17, "unsafe.Add")
731
732 check.assignment(x, Typ[UnsafePointer], "argument to unsafe.Add")
733 if x.mode == invalid {
734 return
735 }
736
737 y := args[1]
738 if !check.isValidIndex(y, InvalidUnsafeAdd, "length", true) {
739 return
740 }
741
742 x.mode = value
743 x.typ = Typ[UnsafePointer]
744 if check.recordTypes() {
745 check.recordBuiltinType(call.Fun, makeSig(x.typ, x.typ, y.typ))
746 }
747
748 case _Alignof:
749
750 check.assignment(x, nil, "argument to unsafe.Alignof")
751 if x.mode == invalid {
752 return
753 }
754
755 if hasVarSize(x.typ, nil) {
756 x.mode = value
757 if check.recordTypes() {
758 check.recordBuiltinType(call.Fun, makeSig(Typ[Uintptr], x.typ))
759 }
760 } else {
761 x.mode = constant_
762 x.val = constant.MakeInt64(check.conf.alignof(x.typ))
763
764 }
765 x.typ = Typ[Uintptr]
766
767 case _Offsetof:
768
769
770 arg0 := argList[0]
771 selx, _ := syntax.Unparen(arg0).(*syntax.SelectorExpr)
772 if selx == nil {
773 check.errorf(arg0, BadOffsetofSyntax, invalidArg+"%s is not a selector expression", arg0)
774 check.use(arg0)
775 return
776 }
777
778 check.expr(nil, x, selx.X)
779 if x.mode == invalid {
780 return
781 }
782
783 base := derefStructPtr(x.typ)
784 sel := selx.Sel.Value
785 obj, index, indirect := lookupFieldOrMethod(base, false, check.pkg, sel, false)
786 switch obj.(type) {
787 case nil:
788 check.errorf(x, MissingFieldOrMethod, invalidArg+"%s has no single field %s", base, sel)
789 return
790 case *Func:
791
792
793
794
795 check.errorf(arg0, InvalidOffsetof, invalidArg+"%s is a method value", arg0)
796 return
797 }
798 if indirect {
799 check.errorf(x, InvalidOffsetof, invalidArg+"field %s is embedded via a pointer in %s", sel, base)
800 return
801 }
802
803
804 check.recordSelection(selx, FieldVal, base, obj, index, false)
805
806
807 {
808 mode := value
809 if x.mode == variable || indirect {
810 mode = variable
811 }
812 check.record(&operand{mode, selx, obj.Type(), nil, 0})
813 }
814
815
816
817
818
819 if hasVarSize(base, nil) {
820 x.mode = value
821 if check.recordTypes() {
822 check.recordBuiltinType(call.Fun, makeSig(Typ[Uintptr], obj.Type()))
823 }
824 } else {
825 offs := check.conf.offsetof(base, index)
826 if offs < 0 {
827 check.errorf(x, TypeTooLarge, "%s is too large", x)
828 return
829 }
830 x.mode = constant_
831 x.val = constant.MakeInt64(offs)
832
833 }
834 x.typ = Typ[Uintptr]
835
836 case _Sizeof:
837
838 check.assignment(x, nil, "argument to unsafe.Sizeof")
839 if x.mode == invalid {
840 return
841 }
842
843 if hasVarSize(x.typ, nil) {
844 x.mode = value
845 if check.recordTypes() {
846 check.recordBuiltinType(call.Fun, makeSig(Typ[Uintptr], x.typ))
847 }
848 } else {
849 size := check.conf.sizeof(x.typ)
850 if size < 0 {
851 check.errorf(x, TypeTooLarge, "%s is too large", x)
852 return
853 }
854 x.mode = constant_
855 x.val = constant.MakeInt64(size)
856
857 }
858 x.typ = Typ[Uintptr]
859
860 case _Slice:
861
862 check.verifyVersionf(call.Fun, go1_17, "unsafe.Slice")
863
864 u, _ := commonUnder(x.typ, nil)
865 ptr, _ := u.(*Pointer)
866 if ptr == nil {
867 check.errorf(x, InvalidUnsafeSlice, invalidArg+"%s is not a pointer", x)
868 return
869 }
870
871 y := args[1]
872 if !check.isValidIndex(y, InvalidUnsafeSlice, "length", false) {
873 return
874 }
875
876 x.mode = value
877 x.typ = NewSlice(ptr.base)
878 if check.recordTypes() {
879 check.recordBuiltinType(call.Fun, makeSig(x.typ, ptr, y.typ))
880 }
881
882 case _SliceData:
883
884 check.verifyVersionf(call.Fun, go1_20, "unsafe.SliceData")
885
886 u, _ := commonUnder(x.typ, nil)
887 slice, _ := u.(*Slice)
888 if slice == nil {
889 check.errorf(x, InvalidUnsafeSliceData, invalidArg+"%s is not a slice", x)
890 return
891 }
892
893 x.mode = value
894 x.typ = NewPointer(slice.elem)
895 if check.recordTypes() {
896 check.recordBuiltinType(call.Fun, makeSig(x.typ, slice))
897 }
898
899 case _String:
900
901 check.verifyVersionf(call.Fun, go1_20, "unsafe.String")
902
903 check.assignment(x, NewPointer(universeByte), "argument to unsafe.String")
904 if x.mode == invalid {
905 return
906 }
907
908 y := args[1]
909 if !check.isValidIndex(y, InvalidUnsafeString, "length", false) {
910 return
911 }
912
913 x.mode = value
914 x.typ = Typ[String]
915 if check.recordTypes() {
916 check.recordBuiltinType(call.Fun, makeSig(x.typ, NewPointer(universeByte), y.typ))
917 }
918
919 case _StringData:
920
921 check.verifyVersionf(call.Fun, go1_20, "unsafe.StringData")
922
923 check.assignment(x, Typ[String], "argument to unsafe.StringData")
924 if x.mode == invalid {
925 return
926 }
927
928 x.mode = value
929 x.typ = NewPointer(universeByte)
930 if check.recordTypes() {
931 check.recordBuiltinType(call.Fun, makeSig(x.typ, Typ[String]))
932 }
933
934 case _Assert:
935
936
937
938 if x.mode != constant_ || !isBoolean(x.typ) {
939 check.errorf(x, Test, invalidArg+"%s is not a boolean constant", x)
940 return
941 }
942 if x.val.Kind() != constant.Bool {
943 check.errorf(x, Test, "internal error: value of %s should be a boolean constant", x)
944 return
945 }
946 if !constant.BoolVal(x.val) {
947 check.errorf(call, Test, "%v failed", call)
948
949 }
950
951
952 case _Trace:
953
954
955
956
957
958 if nargs == 0 {
959 check.dump("%v: trace() without arguments", atPos(call))
960 x.mode = novalue
961 break
962 }
963 var t operand
964 x1 := x
965 for _, arg := range argList {
966 check.rawExpr(nil, x1, arg, nil, false)
967 check.dump("%v: %s", atPos(x1), x1)
968 x1 = &t
969 }
970 if x.mode == invalid {
971 return
972 }
973
974
975 default:
976 panic("unreachable")
977 }
978
979 assert(x.mode != invalid)
980 return true
981 }
982
983
984
985 func sliceElem(x *operand) (Type, *typeError) {
986 var E Type
987 for _, u := range typeset(x.typ) {
988 s, _ := u.(*Slice)
989 if s == nil {
990 if x.isNil() {
991
992
993 return nil, typeErrorf("argument must be a slice; have untyped nil")
994 } else {
995 return nil, typeErrorf("argument must be a slice; have %s", x)
996 }
997 }
998 if E == nil {
999 E = s.elem
1000 } else if !Identical(E, s.elem) {
1001 return nil, typeErrorf("mismatched slice element types %s and %s in %s", E, s.elem, x)
1002 }
1003 }
1004 return E, nil
1005 }
1006
1007
1008
1009
1010 func hasVarSize(t Type, seen map[*Named]bool) (varSized bool) {
1011
1012
1013
1014 if named := asNamed(t); named != nil {
1015 if v, ok := seen[named]; ok {
1016 return v
1017 }
1018 if seen == nil {
1019 seen = make(map[*Named]bool)
1020 }
1021 seen[named] = true
1022 defer func() {
1023 seen[named] = varSized
1024 }()
1025 }
1026
1027 switch u := t.Underlying().(type) {
1028 case *Array:
1029 return hasVarSize(u.elem, seen)
1030 case *Struct:
1031 for _, f := range u.fields {
1032 if hasVarSize(f.typ, seen) {
1033 return true
1034 }
1035 }
1036 case *Interface:
1037 return isTypeParam(t)
1038 case *Named, *Union:
1039 panic("unreachable")
1040 }
1041 return false
1042 }
1043
1044
1045
1046
1047
1048
1049
1050
1051 func (check *Checker) applyTypeFunc(f func(Type) Type, x *operand, id builtinId) Type {
1052 if tp, _ := Unalias(x.typ).(*TypeParam); tp != nil {
1053
1054
1055 var terms []*Term
1056 if !tp.is(func(t *term) bool {
1057 if t == nil {
1058 return false
1059 }
1060 if r := f(t.typ); r != nil {
1061 terms = append(terms, NewTerm(t.tilde, r))
1062 return true
1063 }
1064 return false
1065 }) {
1066 return nil
1067 }
1068
1069
1070
1071
1072
1073 var code Code
1074 switch id {
1075 case _Real:
1076 code = InvalidReal
1077 case _Imag:
1078 code = InvalidImag
1079 case _Complex:
1080 code = InvalidComplex
1081 default:
1082 panic("unreachable")
1083 }
1084 check.softErrorf(x, code, "%s not supported as argument to built-in %s for go1.18 (see go.dev/issue/50937)", x, predeclaredFuncs[id].name)
1085
1086
1087
1088
1089 tpar := NewTypeName(nopos, check.pkg, tp.obj.name, nil)
1090 ptyp := check.newTypeParam(tpar, NewInterfaceType(nil, []Type{NewUnion(terms)}))
1091 ptyp.index = tp.index
1092
1093 return ptyp
1094 }
1095
1096 return f(x.typ)
1097 }
1098
1099
1100
1101 func makeSig(res Type, args ...Type) *Signature {
1102 list := make([]*Var, len(args))
1103 for i, param := range args {
1104 list[i] = NewParam(nopos, nil, "", Default(param))
1105 }
1106 params := NewTuple(list...)
1107 var result *Tuple
1108 if res != nil {
1109 assert(!isUntyped(res))
1110 result = NewTuple(newVar(ResultVar, nopos, nil, "", res))
1111 }
1112 return &Signature{params: params, results: result}
1113 }
1114
1115
1116
1117 func arrayPtrDeref(typ Type) Type {
1118 if p, ok := Unalias(typ).(*Pointer); ok {
1119 if a, _ := p.base.Underlying().(*Array); a != nil {
1120 return a
1121 }
1122 }
1123 return typ
1124 }
1125
View as plain text