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