Source file
src/go/types/builtins.go
1
2
3
4
5
6
7 package types
8
9 import (
10 "go/ast"
11 "go/constant"
12 "go/token"
13 )
14
15
16
17
18
19
20 func (check *Checker) builtin(x *operand, call *ast.CallExpr, id builtinId) (_ bool) {
21
22 bin := predeclaredFuncs[id]
23 if call.Ellipsis.IsValid() && id != _Append {
24 check.invalidOp(atPos(call.Ellipsis),
25 _InvalidDotDotDot,
26 "invalid use of ... with built-in %s", bin.name)
27 check.use(call.Args...)
28 return
29 }
30
31
32
33
34
35
36 if id == _Len || id == _Cap {
37 defer func(b bool) {
38 check.hasCallOrRecv = b
39 }(check.hasCallOrRecv)
40 check.hasCallOrRecv = false
41 }
42
43
44 var arg func(*operand, int)
45 nargs := len(call.Args)
46 switch id {
47 default:
48
49 xlist, _ := check.exprList(call.Args, false)
50 arg = func(x *operand, i int) { *x = *xlist[i] }
51 nargs = len(xlist)
52
53 if nargs > 0 {
54 arg(x, 0)
55 if x.mode == invalid {
56 return
57 }
58 }
59 case _Make, _New, _Offsetof, _Trace:
60
61 }
62
63
64 {
65 msg := ""
66 if nargs < bin.nargs {
67 msg = "not enough"
68 } else if !bin.variadic && nargs > bin.nargs {
69 msg = "too many"
70 }
71 if msg != "" {
72 check.invalidOp(inNode(call, call.Rparen), _WrongArgCount, "%s arguments for %s (expected %d, found %d)", msg, call, bin.nargs, nargs)
73 return
74 }
75 }
76
77 switch id {
78 case _Append:
79
80
81
82
83
84 S := x.typ
85 var T Type
86 if s, _ := coreType(S).(*Slice); s != nil {
87 T = s.elem
88 } else {
89 var cause string
90 switch {
91 case x.isNil():
92 cause = "have untyped nil"
93 case isTypeParam(S):
94 if u := coreType(S); u != nil {
95 cause = check.sprintf("%s has core type %s", x, u)
96 } else {
97 cause = check.sprintf("%s has no core type", x)
98 }
99 default:
100 cause = check.sprintf("have %s", x)
101 }
102
103 check.errorf(x, _InvalidAppend, "first argument to append must be a slice; %s", cause)
104 return
105 }
106
107
108 alist := []operand{*x}
109
110
111
112
113 if nargs == 2 && call.Ellipsis.IsValid() {
114 if ok, _ := x.assignableTo(check, NewSlice(universeByte), nil); ok {
115 arg(x, 1)
116 if x.mode == invalid {
117 return
118 }
119 if t := coreString(x.typ); t != nil && isString(t) {
120 if check.Types != nil {
121 sig := makeSig(S, S, x.typ)
122 sig.variadic = true
123 check.recordBuiltinType(call.Fun, sig)
124 }
125 x.mode = value
126 x.typ = S
127 break
128 }
129 alist = append(alist, *x)
130
131 }
132 }
133
134
135 sig := makeSig(S, S, NewSlice(T))
136 sig.variadic = true
137 var xlist []*operand
138
139 for i := range alist {
140 xlist = append(xlist, &alist[i])
141 }
142 for i := len(alist); i < nargs; i++ {
143 var x operand
144 arg(&x, i)
145 xlist = append(xlist, &x)
146 }
147 check.arguments(call, sig, nil, xlist, nil)
148
149
150 x.mode = value
151 x.typ = S
152 if check.Types != nil {
153 check.recordBuiltinType(call.Fun, sig)
154 }
155
156 case _Cap, _Len:
157
158
159 mode := invalid
160 var val constant.Value
161 switch t := arrayPtrDeref(under(x.typ)).(type) {
162 case *Basic:
163 if isString(t) && id == _Len {
164 if x.mode == constant_ {
165 mode = constant_
166 val = constant.MakeInt64(int64(len(constant.StringVal(x.val))))
167 } else {
168 mode = value
169 }
170 }
171
172 case *Array:
173 mode = value
174
175
176
177
178 if !check.hasCallOrRecv {
179 mode = constant_
180 if t.len >= 0 {
181 val = constant.MakeInt64(t.len)
182 } else {
183 val = constant.MakeUnknown()
184 }
185 }
186
187 case *Slice, *Chan:
188 mode = value
189
190 case *Map:
191 if id == _Len {
192 mode = value
193 }
194
195 case *Interface:
196 if !isTypeParam(x.typ) {
197 break
198 }
199 if t.typeSet().underIs(func(t Type) bool {
200 switch t := arrayPtrDeref(t).(type) {
201 case *Basic:
202 if isString(t) && id == _Len {
203 return true
204 }
205 case *Array, *Slice, *Chan:
206 return true
207 case *Map:
208 if id == _Len {
209 return true
210 }
211 }
212 return false
213 }) {
214 mode = value
215 }
216 }
217
218 if mode == invalid && under(x.typ) != Typ[Invalid] {
219 code := _InvalidCap
220 if id == _Len {
221 code = _InvalidLen
222 }
223 check.invalidArg(x, code, "%s for %s", x, bin.name)
224 return
225 }
226
227
228 if check.Types != nil && mode != constant_ {
229 check.recordBuiltinType(call.Fun, makeSig(Typ[Int], x.typ))
230 }
231
232 x.mode = mode
233 x.typ = Typ[Int]
234 x.val = val
235
236 case _Close:
237
238 if !underIs(x.typ, func(u Type) bool {
239 uch, _ := u.(*Chan)
240 if uch == nil {
241 check.invalidOp(x, _InvalidClose, "cannot close non-channel %s", x)
242 return false
243 }
244 if uch.dir == RecvOnly {
245 check.invalidOp(x, _InvalidClose, "cannot close receive-only channel %s", x)
246 return false
247 }
248 return true
249 }) {
250 return
251 }
252 x.mode = novalue
253 if check.Types != nil {
254 check.recordBuiltinType(call.Fun, makeSig(nil, x.typ))
255 }
256
257 case _Complex:
258
259 var y operand
260 arg(&y, 1)
261 if y.mode == invalid {
262 return
263 }
264
265
266 d := 0
267 if isUntyped(x.typ) {
268 d |= 1
269 }
270 if isUntyped(y.typ) {
271 d |= 2
272 }
273 switch d {
274 case 0:
275
276 case 1:
277
278 check.convertUntyped(x, y.typ)
279 case 2:
280
281 check.convertUntyped(&y, x.typ)
282 case 3:
283
284
285
286
287
288
289
290
291 if x.mode == constant_ && y.mode == constant_ {
292 toFloat := func(x *operand) {
293 if isNumeric(x.typ) && constant.Sign(constant.Imag(x.val)) == 0 {
294 x.typ = Typ[UntypedFloat]
295 }
296 }
297 toFloat(x)
298 toFloat(&y)
299 } else {
300 check.convertUntyped(x, Typ[Float64])
301 check.convertUntyped(&y, Typ[Float64])
302
303
304 }
305 }
306 if x.mode == invalid || y.mode == invalid {
307 return
308 }
309
310
311 if !Identical(x.typ, y.typ) {
312 check.invalidArg(x, _InvalidComplex, "mismatched types %s and %s", x.typ, y.typ)
313 return
314 }
315
316
317
318 f := func(typ Type) Type {
319 assert(!isTypeParam(typ))
320 if t, _ := under(typ).(*Basic); t != nil {
321 switch t.kind {
322 case Float32:
323 return Typ[Complex64]
324 case Float64:
325 return Typ[Complex128]
326 case UntypedFloat:
327 return Typ[UntypedComplex]
328 }
329 }
330 return nil
331 }
332 resTyp := check.applyTypeFunc(f, x, id)
333 if resTyp == nil {
334 check.invalidArg(x, _InvalidComplex, "arguments have type %s, expected floating-point", x.typ)
335 return
336 }
337
338
339 if x.mode == constant_ && y.mode == constant_ {
340 x.val = constant.BinaryOp(constant.ToFloat(x.val), token.ADD, constant.MakeImag(constant.ToFloat(y.val)))
341 } else {
342 x.mode = value
343 }
344
345 if check.Types != nil && x.mode != constant_ {
346 check.recordBuiltinType(call.Fun, makeSig(resTyp, x.typ, x.typ))
347 }
348
349 x.typ = resTyp
350
351 case _Copy:
352
353 dst, _ := coreType(x.typ).(*Slice)
354
355 var y operand
356 arg(&y, 1)
357 if y.mode == invalid {
358 return
359 }
360 src0 := coreString(y.typ)
361 if src0 != nil && isString(src0) {
362 src0 = NewSlice(universeByte)
363 }
364 src, _ := src0.(*Slice)
365
366 if dst == nil || src == nil {
367 check.invalidArg(x, _InvalidCopy, "copy expects slice arguments; found %s and %s", x, &y)
368 return
369 }
370
371 if !Identical(dst.elem, src.elem) {
372 check.errorf(x, _InvalidCopy, "arguments to copy %s and %s have different element types %s and %s", x, &y, dst.elem, src.elem)
373 return
374 }
375
376 if check.Types != nil {
377 check.recordBuiltinType(call.Fun, makeSig(Typ[Int], x.typ, y.typ))
378 }
379 x.mode = value
380 x.typ = Typ[Int]
381
382 case _Delete:
383
384
385
386 map_ := x.typ
387 var key Type
388 if !underIs(map_, func(u Type) bool {
389 map_, _ := u.(*Map)
390 if map_ == nil {
391 check.invalidArg(x, _InvalidDelete, "%s is not a map", x)
392 return false
393 }
394 if key != nil && !Identical(map_.key, key) {
395 check.invalidArg(x, _InvalidDelete, "maps of %s must have identical key types", x)
396 return false
397 }
398 key = map_.key
399 return true
400 }) {
401 return
402 }
403
404 arg(x, 1)
405 if x.mode == invalid {
406 return
407 }
408
409 check.assignment(x, key, "argument to delete")
410 if x.mode == invalid {
411 return
412 }
413
414 x.mode = novalue
415 if check.Types != nil {
416 check.recordBuiltinType(call.Fun, makeSig(nil, map_, key))
417 }
418
419 case _Imag, _Real:
420
421
422
423
424 if isUntyped(x.typ) {
425 if x.mode == constant_ {
426
427
428 if isNumeric(x.typ) {
429 x.typ = Typ[UntypedComplex]
430 }
431 } else {
432
433
434
435
436 check.convertUntyped(x, Typ[Complex128])
437
438 if x.mode == invalid {
439 return
440 }
441 }
442 }
443
444
445
446 f := func(typ Type) Type {
447 assert(!isTypeParam(typ))
448 if t, _ := under(typ).(*Basic); t != nil {
449 switch t.kind {
450 case Complex64:
451 return Typ[Float32]
452 case Complex128:
453 return Typ[Float64]
454 case UntypedComplex:
455 return Typ[UntypedFloat]
456 }
457 }
458 return nil
459 }
460 resTyp := check.applyTypeFunc(f, x, id)
461 if resTyp == nil {
462 code := _InvalidImag
463 if id == _Real {
464 code = _InvalidReal
465 }
466 check.invalidArg(x, code, "argument has type %s, expected complex type", x.typ)
467 return
468 }
469
470
471 if x.mode == constant_ {
472 if id == _Real {
473 x.val = constant.Real(x.val)
474 } else {
475 x.val = constant.Imag(x.val)
476 }
477 } else {
478 x.mode = value
479 }
480
481 if check.Types != nil && x.mode != constant_ {
482 check.recordBuiltinType(call.Fun, makeSig(resTyp, x.typ))
483 }
484
485 x.typ = resTyp
486
487 case _Make:
488
489
490
491 arg0 := call.Args[0]
492 T := check.varType(arg0)
493 if T == Typ[Invalid] {
494 return
495 }
496
497 var min int
498 switch coreType(T).(type) {
499 case *Slice:
500 min = 2
501 case *Map, *Chan:
502 min = 1
503 case nil:
504 check.errorf(arg0, _InvalidMake, "cannot make %s: no core type", arg0)
505 return
506 default:
507 check.invalidArg(arg0, _InvalidMake, "cannot make %s; type must be slice, map, or channel", arg0)
508 return
509 }
510 if nargs < min || min+1 < nargs {
511 check.invalidOp(call, _WrongArgCount, "%v expects %d or %d arguments; found %d", call, min, min+1, nargs)
512 return
513 }
514
515 types := []Type{T}
516 var sizes []int64
517 for _, arg := range call.Args[1:] {
518 typ, size := check.index(arg, -1)
519 types = append(types, typ)
520 if size >= 0 {
521 sizes = append(sizes, size)
522 }
523 }
524 if len(sizes) == 2 && sizes[0] > sizes[1] {
525 check.invalidArg(call.Args[1], _SwappedMakeArgs, "length and capacity swapped")
526
527 }
528 x.mode = value
529 x.typ = T
530 if check.Types != nil {
531 check.recordBuiltinType(call.Fun, makeSig(x.typ, types...))
532 }
533
534 case _New:
535
536
537 T := check.varType(call.Args[0])
538 if T == Typ[Invalid] {
539 return
540 }
541
542 x.mode = value
543 x.typ = &Pointer{base: T}
544 if check.Types != nil {
545 check.recordBuiltinType(call.Fun, makeSig(x.typ, T))
546 }
547
548 case _Panic:
549
550
551
552 if check.sig != nil && check.sig.results.Len() > 0 {
553
554 p := check.isPanic
555 if p == nil {
556
557 p = make(map[*ast.CallExpr]bool)
558 check.isPanic = p
559 }
560 p[call] = true
561 }
562
563 check.assignment(x, &emptyInterface, "argument to panic")
564 if x.mode == invalid {
565 return
566 }
567
568 x.mode = novalue
569 if check.Types != nil {
570 check.recordBuiltinType(call.Fun, makeSig(nil, &emptyInterface))
571 }
572
573 case _Print, _Println:
574
575
576 var params []Type
577 if nargs > 0 {
578 params = make([]Type, nargs)
579 for i := 0; i < nargs; i++ {
580 if i > 0 {
581 arg(x, i)
582 }
583 check.assignment(x, nil, "argument to "+predeclaredFuncs[id].name)
584 if x.mode == invalid {
585
586 return
587 }
588 params[i] = x.typ
589 }
590 }
591
592 x.mode = novalue
593 if check.Types != nil {
594 check.recordBuiltinType(call.Fun, makeSig(nil, params...))
595 }
596
597 case _Recover:
598
599 x.mode = value
600 x.typ = &emptyInterface
601 if check.Types != nil {
602 check.recordBuiltinType(call.Fun, makeSig(x.typ))
603 }
604
605 case _Add:
606
607 if !check.allowVersion(check.pkg, 1, 17) {
608 check.errorf(call.Fun, _InvalidUnsafeAdd, "unsafe.Add requires go1.17 or later")
609 return
610 }
611
612 check.assignment(x, Typ[UnsafePointer], "argument to unsafe.Add")
613 if x.mode == invalid {
614 return
615 }
616
617 var y operand
618 arg(&y, 1)
619 if !check.isValidIndex(&y, _InvalidUnsafeAdd, "length", true) {
620 return
621 }
622
623 x.mode = value
624 x.typ = Typ[UnsafePointer]
625 if check.Types != nil {
626 check.recordBuiltinType(call.Fun, makeSig(x.typ, x.typ, y.typ))
627 }
628
629 case _Alignof:
630
631 check.assignment(x, nil, "argument to unsafe.Alignof")
632 if x.mode == invalid {
633 return
634 }
635
636 if hasVarSize(x.typ) {
637 x.mode = value
638 if check.Types != nil {
639 check.recordBuiltinType(call.Fun, makeSig(Typ[Uintptr], x.typ))
640 }
641 } else {
642 x.mode = constant_
643 x.val = constant.MakeInt64(check.conf.alignof(x.typ))
644
645 }
646 x.typ = Typ[Uintptr]
647
648 case _Offsetof:
649
650
651 arg0 := call.Args[0]
652 selx, _ := unparen(arg0).(*ast.SelectorExpr)
653 if selx == nil {
654 check.invalidArg(arg0, _BadOffsetofSyntax, "%s is not a selector expression", arg0)
655 check.use(arg0)
656 return
657 }
658
659 check.expr(x, selx.X)
660 if x.mode == invalid {
661 return
662 }
663
664 base := derefStructPtr(x.typ)
665 sel := selx.Sel.Name
666 obj, index, indirect := LookupFieldOrMethod(base, false, check.pkg, sel)
667 switch obj.(type) {
668 case nil:
669 check.invalidArg(x, _MissingFieldOrMethod, "%s has no single field %s", base, sel)
670 return
671 case *Func:
672
673
674
675
676 check.invalidArg(arg0, _InvalidOffsetof, "%s is a method value", arg0)
677 return
678 }
679 if indirect {
680 check.invalidArg(x, _InvalidOffsetof, "field %s is embedded via a pointer in %s", sel, base)
681 return
682 }
683
684
685 check.recordSelection(selx, FieldVal, base, obj, index, false)
686
687
688 {
689 mode := value
690 if x.mode == variable || indirect {
691 mode = variable
692 }
693 check.record(&operand{mode, selx, obj.Type(), nil, 0})
694 }
695
696
697
698
699
700 if hasVarSize(base) {
701 x.mode = value
702 if check.Types != nil {
703 check.recordBuiltinType(call.Fun, makeSig(Typ[Uintptr], obj.Type()))
704 }
705 } else {
706 x.mode = constant_
707 x.val = constant.MakeInt64(check.conf.offsetof(base, index))
708
709 }
710 x.typ = Typ[Uintptr]
711
712 case _Sizeof:
713
714 check.assignment(x, nil, "argument to unsafe.Sizeof")
715 if x.mode == invalid {
716 return
717 }
718
719 if hasVarSize(x.typ) {
720 x.mode = value
721 if check.Types != nil {
722 check.recordBuiltinType(call.Fun, makeSig(Typ[Uintptr], x.typ))
723 }
724 } else {
725 x.mode = constant_
726 x.val = constant.MakeInt64(check.conf.sizeof(x.typ))
727
728 }
729 x.typ = Typ[Uintptr]
730
731 case _Slice:
732
733 if !check.allowVersion(check.pkg, 1, 17) {
734 check.errorf(call.Fun, _InvalidUnsafeSlice, "unsafe.Slice requires go1.17 or later")
735 return
736 }
737
738 typ, _ := under(x.typ).(*Pointer)
739 if typ == nil {
740 check.invalidArg(x, _InvalidUnsafeSlice, "%s is not a pointer", x)
741 return
742 }
743
744 var y operand
745 arg(&y, 1)
746 if !check.isValidIndex(&y, _InvalidUnsafeSlice, "length", false) {
747 return
748 }
749
750 x.mode = value
751 x.typ = NewSlice(typ.base)
752 if check.Types != nil {
753 check.recordBuiltinType(call.Fun, makeSig(x.typ, typ, y.typ))
754 }
755
756 case _Assert:
757
758
759
760 if x.mode != constant_ || !isBoolean(x.typ) {
761 check.invalidArg(x, _Test, "%s is not a boolean constant", x)
762 return
763 }
764 if x.val.Kind() != constant.Bool {
765 check.errorf(x, _Test, "internal error: value of %s should be a boolean constant", x)
766 return
767 }
768 if !constant.BoolVal(x.val) {
769 check.errorf(call, _Test, "%v failed", call)
770
771 }
772
773
774 case _Trace:
775
776
777
778
779
780 if nargs == 0 {
781 check.dump("%v: trace() without arguments", call.Pos())
782 x.mode = novalue
783 break
784 }
785 var t operand
786 x1 := x
787 for _, arg := range call.Args {
788 check.rawExpr(x1, arg, nil, false)
789 check.dump("%v: %s", x1.Pos(), x1)
790 x1 = &t
791 }
792
793
794 default:
795 unreachable()
796 }
797
798 return true
799 }
800
801
802 func hasVarSize(t Type) bool {
803 switch u := under(t).(type) {
804 case *Array:
805 return hasVarSize(u.elem)
806 case *Struct:
807 for _, f := range u.fields {
808 if hasVarSize(f.typ) {
809 return true
810 }
811 }
812 case *Interface:
813 return isTypeParam(t)
814 case *Named, *Union:
815 unreachable()
816 }
817 return false
818 }
819
820
821
822
823
824
825
826
827 func (check *Checker) applyTypeFunc(f func(Type) Type, x *operand, id builtinId) Type {
828 if tp, _ := x.typ.(*TypeParam); tp != nil {
829
830
831 var terms []*Term
832 if !tp.is(func(t *term) bool {
833 if t == nil {
834 return false
835 }
836 if r := f(t.typ); r != nil {
837 terms = append(terms, NewTerm(t.tilde, r))
838 return true
839 }
840 return false
841 }) {
842 return nil
843 }
844
845
846
847
848
849 var code errorCode
850 switch id {
851 case _Real:
852 code = _InvalidReal
853 case _Imag:
854 code = _InvalidImag
855 case _Complex:
856 code = _InvalidComplex
857 default:
858 unreachable()
859 }
860 check.softErrorf(x, code, "%s not supported as argument to %s for go1.18 (see issue #50937)", x, predeclaredFuncs[id].name)
861
862
863
864
865 tpar := NewTypeName(token.NoPos, check.pkg, tp.obj.name, nil)
866 ptyp := check.newTypeParam(tpar, NewInterfaceType(nil, []Type{NewUnion(terms)}))
867 ptyp.index = tp.index
868
869 return ptyp
870 }
871
872 return f(x.typ)
873 }
874
875
876
877 func makeSig(res Type, args ...Type) *Signature {
878 list := make([]*Var, len(args))
879 for i, param := range args {
880 list[i] = NewVar(token.NoPos, nil, "", Default(param))
881 }
882 params := NewTuple(list...)
883 var result *Tuple
884 if res != nil {
885 assert(!isUntyped(res))
886 result = NewTuple(NewVar(token.NoPos, nil, "", res))
887 }
888 return &Signature{params: params, results: result}
889 }
890
891
892
893 func arrayPtrDeref(typ Type) Type {
894 if p, ok := typ.(*Pointer); ok {
895 if a, _ := under(p.base).(*Array); a != nil {
896 return a
897 }
898 }
899 return typ
900 }
901
902
903 func unparen(e ast.Expr) ast.Expr {
904 for {
905 p, ok := e.(*ast.ParenExpr)
906 if !ok {
907 return e
908 }
909 e = p.X
910 }
911 }
912
View as plain text