1 // Copyright 2012 The Go Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style
3 // license that can be found in the LICENSE file.
5 // This file implements typechecking of builtin function calls.
15 // builtin type-checks a call to the built-in specified by id and
16 // reports whether the call is valid, with *x holding the result;
17 // but x.expr is not set. If the call is invalid, the result is
18 // false, and *x is undefined.
20 func (check
*Checker
) builtin(x
*operand
, call
*ast
.CallExpr
, id builtinId
) (_
bool) {
21 // append is the only built-in that permits the use of ... for the last argument
22 bin
:= predeclaredFuncs
[id
]
23 if call
.Ellipsis
.IsValid() && id
!= _Append
{
24 check
.invalidOp(atPos(call
.Ellipsis
),
26 "invalid use of ... with built-in %s", bin
.name
)
27 check
.use(call
.Args
...)
31 // For len(x) and cap(x) we need to know if x contains any function calls or
32 // receive operations. Save/restore current setting and set hasCallOrRecv to
33 // false for the evaluation of x so that we can check it afterwards.
34 // Note: We must do this _before_ calling exprList because exprList evaluates
36 if id
== _Len || id
== _Cap
{
38 check
.hasCallOrRecv
= b
39 }(check
.hasCallOrRecv
)
40 check
.hasCallOrRecv
= false
43 // determine actual arguments
44 var arg
func(*operand
, int) // TODO(gri) remove use of arg getter in favor of using xlist directly
45 nargs
:= len(call
.Args
)
48 // make argument getter
49 xlist
, _
:= check
.exprList(call
.Args
, false)
50 arg
= func(x
*operand
, i
int) { *x
= *xlist
[i
] }
52 // evaluate first argument, if present
55 if x
.mode
== invalid
{
59 case _Make
, _New
, _Offsetof
, _Trace
:
60 // arguments require special handling
63 // check argument count
66 if nargs
< bin
.nargs
{
68 } else if !bin
.variadic
&& nargs
> bin
.nargs
{
72 check
.invalidOp(inNode(call
, call
.Rparen
), _WrongArgCount
, "%s arguments for %s (expected %d, found %d)", msg
, call
, bin
.nargs
, nargs
)
79 // append(s S, x ...T) S, where T is the element type of S
80 // spec: "The variadic function append appends zero or more values x to s of type
81 // S, which must be a slice type, and returns the resulting slice, also of type S.
82 // The values x are passed to a parameter of type ...T where T is the element type
83 // of S and the respective parameter passing rules apply."
86 if s
, _
:= coreType(S
).(*Slice
); s
!= nil {
92 cause
= "have untyped nil"
94 if u
:= coreType(S
); u
!= nil {
95 cause
= check
.sprintf("%s has core type %s", x
, u
)
97 cause
= check
.sprintf("%s has no core type", x
)
100 cause
= check
.sprintf("have %s", x
)
102 // don't use Checker.invalidArg here as it would repeat "argument" in the error message
103 check
.errorf(x
, _InvalidAppend
, "first argument to append must be a slice; %s", cause
)
107 // remember arguments that have been evaluated already
108 alist
:= []operand
{*x
}
110 // spec: "As a special case, append also accepts a first argument assignable
111 // to type []byte with a second argument of string type followed by ... .
112 // This form appends the bytes of the string.
113 if nargs
== 2 && call
.Ellipsis
.IsValid() {
114 if ok
, _
:= x
.assignableTo(check
, NewSlice(universeByte
), nil); ok
{
116 if x
.mode
== invalid
{
119 if t
:= coreString(x
.typ
); t
!= nil && isString(t
) {
120 if check
.Types
!= nil {
121 sig
:= makeSig(S
, S
, x
.typ
)
123 check
.recordBuiltinType(call
.Fun
, sig
)
129 alist
= append(alist
, *x
)
134 // check general case by creating custom signature
135 sig
:= makeSig(S
, S
, NewSlice(T
)) // []T required for variadic signature
138 // convert []operand to []*operand
139 for i
:= range alist
{
140 xlist
= append(xlist
, &alist
[i
])
142 for i
:= len(alist
); i
< nargs
; i
++ {
145 xlist
= append(xlist
, &x
)
147 check
.arguments(call
, sig
, nil, xlist
, nil) // discard result (we know the result type)
148 // ok to continue even if check.arguments reported errors
152 if check
.Types
!= nil {
153 check
.recordBuiltinType(call
.Fun
, sig
)
160 var val constant
.Value
161 switch t
:= arrayPtrDeref(under(x
.typ
)).(type) {
163 if isString(t
) && id
== _Len
{
164 if x
.mode
== constant_
{
166 val
= constant
.MakeInt64(int64(len(constant
.StringVal(x
.val
))))
174 // spec: "The expressions len(s) and cap(s) are constants
175 // if the type of s is an array or pointer to an array and
176 // the expression s does not contain channel receives or
177 // function calls; in this case s is not evaluated."
178 if !check
.hasCallOrRecv
{
181 val
= constant
.MakeInt64(t
.len)
183 val
= constant
.MakeUnknown()
196 if !isTypeParam(x
.typ
) {
199 if t
.typeSet().underIs(func(t Type
) bool {
200 switch t
:= arrayPtrDeref(t
).(type) {
202 if isString(t
) && id
== _Len
{
205 case *Array
, *Slice
, *Chan
:
218 if mode
== invalid
&& under(x
.typ
) != Typ
[Invalid
] {
223 check
.invalidArg(x
, code
, "%s for %s", x
, bin
.name
)
227 // record the signature before changing x.typ
228 if check
.Types
!= nil && mode
!= constant_
{
229 check
.recordBuiltinType(call
.Fun
, makeSig(Typ
[Int
], x
.typ
))
238 if !underIs(x
.typ
, func(u Type
) bool {
241 check
.invalidOp(x
, _InvalidClose
, "cannot close non-channel %s", x
)
244 if uch
.dir
== RecvOnly
{
245 check
.invalidOp(x
, _InvalidClose
, "cannot close receive-only channel %s", x
)
253 if check
.Types
!= nil {
254 check
.recordBuiltinType(call
.Fun
, makeSig(nil, x
.typ
))
258 // complex(x, y floatT) complexT
261 if y
.mode
== invalid
{
265 // convert or check untyped arguments
267 if isUntyped(x
.typ
) {
270 if isUntyped(y
.typ
) {
275 // x and y are typed => nothing to do
277 // only x is untyped => convert to type of y
278 check
.convertUntyped(x
, y
.typ
)
280 // only y is untyped => convert to type of x
281 check
.convertUntyped(&y
, x
.typ
)
283 // x and y are untyped =>
284 // 1) if both are constants, convert them to untyped
285 // floating-point numbers if possible,
286 // 2) if one of them is not constant (possible because
287 // it contains a shift that is yet untyped), convert
288 // both of them to float64 since they must have the
289 // same type to succeed (this will result in an error
290 // because shifts of floats are not permitted)
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
]
300 check
.convertUntyped(x
, Typ
[Float64
])
301 check
.convertUntyped(&y
, Typ
[Float64
])
302 // x and y should be invalid now, but be conservative
306 if x
.mode
== invalid || y
.mode
== invalid
{
310 // both argument types must be identical
311 if !Identical(x
.typ
, y
.typ
) {
312 check
.invalidArg(x
, _InvalidComplex
, "mismatched types %s and %s", x
.typ
, y
.typ
)
316 // the argument types must be of floating-point type
317 // (applyTypeFunc never calls f with a type parameter)
318 f
:= func(typ Type
) Type
{
319 assert(!isTypeParam(typ
))
320 if t
, _
:= under(typ
).(*Basic
); t
!= nil {
323 return Typ
[Complex64
]
325 return Typ
[Complex128
]
327 return Typ
[UntypedComplex
]
332 resTyp
:= check
.applyTypeFunc(f
, x
, id
)
334 check
.invalidArg(x
, _InvalidComplex
, "arguments have type %s, expected floating-point", x
.typ
)
338 // if both arguments are constants, the result is a constant
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
)))
345 if check
.Types
!= nil && x
.mode
!= constant_
{
346 check
.recordBuiltinType(call
.Fun
, makeSig(resTyp
, x
.typ
, x
.typ
))
352 // copy(x, y []T) int
353 dst
, _
:= coreType(x
.typ
).(*Slice
)
357 if y
.mode
== invalid
{
360 src0
:= coreString(y
.typ
)
361 if src0
!= nil && isString(src0
) {
362 src0
= NewSlice(universeByte
)
364 src
, _
:= src0
.(*Slice
)
366 if dst
== nil || src
== nil {
367 check
.invalidArg(x
, _InvalidCopy
, "copy expects slice arguments; found %s and %s", x
, &y
)
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
)
376 if check
.Types
!= nil {
377 check
.recordBuiltinType(call
.Fun
, makeSig(Typ
[Int
], x
.typ
, y
.typ
))
384 // map_ must be a map type or a type parameter describing map types.
385 // The key cannot be a type parameter for now.
388 if !underIs(map_
, func(u Type
) bool {
391 check
.invalidArg(x
, _InvalidDelete
, "%s is not a map", x
)
394 if key
!= nil && !Identical(map_
.key
, key
) {
395 check
.invalidArg(x
, _InvalidDelete
, "maps of %s must have identical key types", x
)
405 if x
.mode
== invalid
{
409 check
.assignment(x
, key
, "argument to delete")
410 if x
.mode
== invalid
{
415 if check
.Types
!= nil {
416 check
.recordBuiltinType(call
.Fun
, makeSig(nil, map_
, key
))
420 // imag(complexT) floatT
421 // real(complexT) floatT
423 // convert or check untyped argument
424 if isUntyped(x
.typ
) {
425 if x
.mode
== constant_
{
426 // an untyped constant number can always be considered
427 // as a complex constant
428 if isNumeric(x
.typ
) {
429 x
.typ
= Typ
[UntypedComplex
]
432 // an untyped non-constant argument may appear if
433 // it contains a (yet untyped non-constant) shift
434 // expression: convert it to complex128 which will
435 // result in an error (shift of complex value)
436 check
.convertUntyped(x
, Typ
[Complex128
])
437 // x should be invalid now, but be conservative and check
438 if x
.mode
== invalid
{
444 // the argument must be of complex type
445 // (applyTypeFunc never calls f with a type parameter)
446 f
:= func(typ Type
) Type
{
447 assert(!isTypeParam(typ
))
448 if t
, _
:= under(typ
).(*Basic
); t
!= nil {
455 return Typ
[UntypedFloat
]
460 resTyp
:= check
.applyTypeFunc(f
, x
, id
)
466 check
.invalidArg(x
, code
, "argument has type %s, expected complex type", x
.typ
)
470 // if the argument is a constant, the result is a constant
471 if x
.mode
== constant_
{
473 x
.val
= constant
.Real(x
.val
)
475 x
.val
= constant
.Imag(x
.val
)
481 if check
.Types
!= nil && x
.mode
!= constant_
{
482 check
.recordBuiltinType(call
.Fun
, makeSig(resTyp
, x
.typ
))
490 // (no argument evaluated yet)
492 T
:= check
.varType(arg0
)
493 if T
== Typ
[Invalid
] {
497 var min
int // minimum number of arguments
498 switch coreType(T
).(type) {
504 check
.errorf(arg0
, _InvalidMake
, "cannot make %s: no core type", arg0
)
507 check
.invalidArg(arg0
, _InvalidMake
, "cannot make %s; type must be slice, map, or channel", arg0
)
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
)
516 var sizes
[]int64 // constant integer arguments, if any
517 for _
, arg
:= range call
.Args
[1:] {
518 typ
, size
:= check
.index(arg
, -1) // ok to continue with typ == Typ[Invalid]
519 types
= append(types
, typ
)
521 sizes
= append(sizes
, size
)
524 if len(sizes
) == 2 && sizes
[0] > sizes
[1] {
525 check
.invalidArg(call
.Args
[1], _SwappedMakeArgs
, "length and capacity swapped")
530 if check
.Types
!= nil {
531 check
.recordBuiltinType(call
.Fun
, makeSig(x
.typ
, types
...))
536 // (no argument evaluated yet)
537 T
:= check
.varType(call
.Args
[0])
538 if T
== Typ
[Invalid
] {
543 x
.typ
= &Pointer
{base
: T
}
544 if check
.Types
!= nil {
545 check
.recordBuiltinType(call
.Fun
, makeSig(x
.typ
, T
))
550 // record panic call if inside a function with result parameters
551 // (for use in Checker.isTerminating)
552 if check
.sig
!= nil && check
.sig
.results
.Len() > 0 {
553 // function has result parameters
557 p
= make(map[*ast
.CallExpr
]bool)
563 check
.assignment(x
, &emptyInterface
, "argument to panic")
564 if x
.mode
== invalid
{
569 if check
.Types
!= nil {
570 check
.recordBuiltinType(call
.Fun
, makeSig(nil, &emptyInterface
))
573 case _Print
, _Println
:
575 // println(x, y, ...)
578 params
= make([]Type
, nargs
)
579 for i
:= 0; i
< nargs
; i
++ {
581 arg(x
, i
) // first argument already evaluated
583 check
.assignment(x
, nil, "argument to "+predeclaredFuncs
[id
].name
)
584 if x
.mode
== invalid
{
585 // TODO(gri) "use" all arguments?
593 if check
.Types
!= nil {
594 check
.recordBuiltinType(call
.Fun
, makeSig(nil, params
...))
598 // recover() interface{}
600 x
.typ
= &emptyInterface
601 if check
.Types
!= nil {
602 check
.recordBuiltinType(call
.Fun
, makeSig(x
.typ
))
606 // unsafe.Add(ptr unsafe.Pointer, len IntegerType) unsafe.Pointer
607 if !check
.allowVersion(check
.pkg
, 1, 17) {
608 check
.errorf(call
.Fun
, _InvalidUnsafeAdd
, "unsafe.Add requires go1.17 or later")
612 check
.assignment(x
, Typ
[UnsafePointer
], "argument to unsafe.Add")
613 if x
.mode
== invalid
{
619 if !check
.isValidIndex(&y
, _InvalidUnsafeAdd
, "length", true) {
624 x
.typ
= Typ
[UnsafePointer
]
625 if check
.Types
!= nil {
626 check
.recordBuiltinType(call
.Fun
, makeSig(x
.typ
, x
.typ
, y
.typ
))
630 // unsafe.Alignof(x T) uintptr
631 check
.assignment(x
, nil, "argument to unsafe.Alignof")
632 if x
.mode
== invalid
{
636 if hasVarSize(x
.typ
) {
638 if check
.Types
!= nil {
639 check
.recordBuiltinType(call
.Fun
, makeSig(Typ
[Uintptr
], x
.typ
))
643 x
.val
= constant
.MakeInt64(check
.conf
.alignof(x
.typ
))
644 // result is constant - no need to record signature
649 // unsafe.Offsetof(x T) uintptr, where x must be a selector
650 // (no argument evaluated yet)
652 selx
, _
:= unparen(arg0
).(*ast
.SelectorExpr
)
654 check
.invalidArg(arg0
, _BadOffsetofSyntax
, "%s is not a selector expression", arg0
)
659 check
.expr(x
, selx
.X
)
660 if x
.mode
== invalid
{
664 base
:= derefStructPtr(x
.typ
)
666 obj
, index
, indirect
:= LookupFieldOrMethod(base
, false, check
.pkg
, sel
)
669 check
.invalidArg(x
, _MissingFieldOrMethod
, "%s has no single field %s", base
, sel
)
672 // TODO(gri) Using derefStructPtr may result in methods being found
673 // that don't actually exist. An error either way, but the error
674 // message is confusing. See: https://play.golang.org/p/al75v23kUy ,
675 // but go/types reports: "invalid argument: x.m is a method value".
676 check
.invalidArg(arg0
, _InvalidOffsetof
, "%s is a method value", arg0
)
680 check
.invalidArg(x
, _InvalidOffsetof
, "field %s is embedded via a pointer in %s", sel
, base
)
684 // TODO(gri) Should we pass x.typ instead of base (and have indirect report if derefStructPtr indirected)?
685 check
.recordSelection(selx
, FieldVal
, base
, obj
, index
, false)
687 // record the selector expression (was bug - issue #47895)
690 if x
.mode
== variable || indirect
{
693 check
.record(&operand
{mode
, selx
, obj
.Type(), nil, 0})
696 // The field offset is considered a variable even if the field is declared before
697 // the part of the struct which is variable-sized. This makes both the rules
698 // simpler and also permits (or at least doesn't prevent) a compiler from re-
699 // arranging struct fields if it wanted to.
700 if hasVarSize(base
) {
702 if check
.Types
!= nil {
703 check
.recordBuiltinType(call
.Fun
, makeSig(Typ
[Uintptr
], obj
.Type()))
707 x
.val
= constant
.MakeInt64(check
.conf
.offsetof(base
, index
))
708 // result is constant - no need to record signature
713 // unsafe.Sizeof(x T) uintptr
714 check
.assignment(x
, nil, "argument to unsafe.Sizeof")
715 if x
.mode
== invalid
{
719 if hasVarSize(x
.typ
) {
721 if check
.Types
!= nil {
722 check
.recordBuiltinType(call
.Fun
, makeSig(Typ
[Uintptr
], x
.typ
))
726 x
.val
= constant
.MakeInt64(check
.conf
.sizeof(x
.typ
))
727 // result is constant - no need to record signature
732 // unsafe.Slice(ptr *T, len IntegerType) []T
733 if !check
.allowVersion(check
.pkg
, 1, 17) {
734 check
.errorf(call
.Fun
, _InvalidUnsafeSlice
, "unsafe.Slice requires go1.17 or later")
738 typ
, _
:= under(x
.typ
).(*Pointer
)
740 check
.invalidArg(x
, _InvalidUnsafeSlice
, "%s is not a pointer", x
)
746 if !check
.isValidIndex(&y
, _InvalidUnsafeSlice
, "length", false) {
751 x
.typ
= NewSlice(typ
.base
)
752 if check
.Types
!= nil {
753 check
.recordBuiltinType(call
.Fun
, makeSig(x
.typ
, typ
, y
.typ
))
757 // assert(pred) causes a typechecker error if pred is false.
758 // The result of assert is the value of pred if there is no error.
759 // Note: assert is only available in self-test mode.
760 if x
.mode
!= constant_ ||
!isBoolean(x
.typ
) {
761 check
.invalidArg(x
, _Test
, "%s is not a boolean constant", x
)
764 if x
.val
.Kind() != constant
.Bool
{
765 check
.errorf(x
, _Test
, "internal error: value of %s should be a boolean constant", x
)
768 if !constant
.BoolVal(x
.val
) {
769 check
.errorf(call
, _Test
, "%v failed", call
)
770 // compile-time assertion failure - safe to continue
772 // result is constant - no need to record signature
775 // trace(x, y, z, ...) dumps the positions, expressions, and
776 // values of its arguments. The result of trace is the value
777 // of the first argument.
778 // Note: trace is only available in self-test mode.
779 // (no argument evaluated yet)
781 check
.dump("%v: trace() without arguments", call
.Pos())
787 for _
, arg
:= range call
.Args
{
788 check
.rawExpr(x1
, arg
, nil, false) // permit trace for types, e.g.: new(trace(T))
789 check
.dump("%v: %s", x1
.Pos(), x1
)
790 x1
= &t
// use incoming x only for first argument
792 // trace is only available in test mode - no need to record signature
801 // hasVarSize reports if the size of type t is variable due to type parameters.
802 func hasVarSize(t Type
) bool {
803 switch u
:= under(t
).(type) {
805 return hasVarSize(u
.elem
)
807 for _
, f
:= range u
.fields
{
808 if hasVarSize(f
.typ
) {
813 return isTypeParam(t
)
820 // applyTypeFunc applies f to x. If x is a type parameter,
821 // the result is a type parameter constrained by an new
822 // interface bound. The type bounds for that interface
823 // are computed by applying f to each of the type bounds
824 // of x. If any of these applications of f return nil,
825 // applyTypeFunc returns nil.
826 // If x is not a type parameter, the result is f(x).
827 func (check
*Checker
) applyTypeFunc(f
func(Type
) Type
, x
*operand
, id builtinId
) Type
{
828 if tp
, _
:= x
.typ
.(*TypeParam
); tp
!= nil {
829 // Test if t satisfies the requirements for the argument
830 // type and collect possible result types at the same time.
832 if !tp
.is(func(t
*term
) bool {
836 if r
:= f(t
.typ
); r
!= nil {
837 terms
= append(terms
, NewTerm(t
.tilde
, r
))
845 // We can type-check this fine but we're introducing a synthetic
846 // type parameter for the result. It's not clear what the API
847 // implications are here. Report an error for 1.18 (see #50912),
848 // but continue type-checking.
856 code
= _InvalidComplex
860 check
.softErrorf(x
, code
, "%s not supported as argument to %s for go1.18 (see issue #50937)", x
, predeclaredFuncs
[id
].name
)
862 // Construct a suitable new type parameter for the result type.
863 // The type parameter is placed in the current package so export/import
864 // works as expected.
865 tpar
:= NewTypeName(token
.NoPos
, check
.pkg
, tp
.obj
.name
, nil)
866 ptyp
:= check
.newTypeParam(tpar
, NewInterfaceType(nil, []Type
{NewUnion(terms
)})) // assigns type to tpar as a side-effect
867 ptyp
.index
= tp
.index
875 // makeSig makes a signature for the given argument and result types.
876 // Default types are used for untyped arguments, and res may be nil.
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
))
882 params
:= NewTuple(list
...)
885 assert(!isUntyped(res
))
886 result
= NewTuple(NewVar(token
.NoPos
, nil, "", res
))
888 return &Signature
{params
: params
, results
: result
}
891 // arrayPtrDeref returns A if typ is of the form *A and A is an array;
892 // otherwise it returns typ.
893 func arrayPtrDeref(typ Type
) Type
{
894 if p
, ok
:= typ
.(*Pointer
); ok
{
895 if a
, _
:= under(p
.base
).(*Array
); a
!= nil {
902 // unparen returns e with any enclosing parentheses stripped.
903 func unparen(e ast
.Expr
) ast
.Expr
{
905 p
, ok
:= e
.(*ast
.ParenExpr
)