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