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 // returns true if 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(call
.Ellipsis
, "invalid use of ... with built-in %s", bin
.name
)
25 check
.use(call
.Args
...)
29 // For len(x) and cap(x) we need to know if x contains any function calls or
30 // receive operations. Save/restore current setting and set hasCallOrRecv to
31 // false for the evaluation of x so that we can check it afterwards.
32 // Note: We must do this _before_ calling unpack because unpack evaluates the
33 // first argument before we even call arg(x, 0)!
34 if id
== _Len || id
== _Cap
{
36 check
.hasCallOrRecv
= b
37 }(check
.hasCallOrRecv
)
38 check
.hasCallOrRecv
= false
41 // determine actual arguments
43 nargs
:= len(call
.Args
)
46 // make argument getter
47 arg
, nargs
, _
= unpack(func(x
*operand
, i
int) { check
.multiExpr(x
, call
.Args
[i
]) }, nargs
, false)
51 // evaluate first argument, if present
54 if x
.mode
== invalid
{
58 case _Make
, _New
, _Offsetof
, _Trace
:
59 // arguments require special handling
62 // check argument count
65 if nargs
< bin
.nargs
{
67 } else if !bin
.variadic
&& nargs
> bin
.nargs
{
71 check
.invalidOp(call
.Rparen
, "%s arguments for %s (expected %d, found %d)", msg
, call
, bin
.nargs
, nargs
)
78 // append(s S, x ...T) S, where T is the element type of S
79 // spec: "The variadic function append appends zero or more values x to s of type
80 // S, which must be a slice type, and returns the resulting slice, also of type S.
81 // The values x are passed to a parameter of type ...T where T is the element type
82 // of S and the respective parameter passing rules apply."
85 if s
, _
:= S
.Underlying().(*Slice
); s
!= nil {
88 check
.invalidArg(x
.pos(), "%s is not a slice", x
)
92 // remember arguments that have been evaluated already
93 alist
:= []operand
{*x
}
95 // spec: "As a special case, append also accepts a first argument assignable
96 // to type []byte with a second argument of string type followed by ... .
97 // This form appends the bytes of the string.
98 if nargs
== 2 && call
.Ellipsis
.IsValid() && x
.assignableTo(check
.conf
, NewSlice(universeByte
), nil) {
100 if x
.mode
== invalid
{
104 if check
.Types
!= nil {
105 sig
:= makeSig(S
, S
, x
.typ
)
107 check
.recordBuiltinType(call
.Fun
, sig
)
113 alist
= append(alist
, *x
)
117 // check general case by creating custom signature
118 sig
:= makeSig(S
, S
, NewSlice(T
)) // []T required for variadic signature
120 check
.arguments(x
, call
, sig
, func(x
*operand
, i
int) {
121 // only evaluate arguments that have not been evaluated before
128 // ok to continue even if check.arguments reported errors
132 if check
.Types
!= nil {
133 check
.recordBuiltinType(call
.Fun
, sig
)
141 var val constant
.Value
142 switch typ
= implicitArrayDeref(x
.typ
.Underlying()); t
:= typ
.(type) {
144 if isString(t
) && id
== _Len
{
145 if x
.mode
== constant_
{
147 val
= constant
.MakeInt64(int64(len(constant
.StringVal(x
.val
))))
155 // spec: "The expressions len(s) and cap(s) are constants
156 // if the type of s is an array or pointer to an array and
157 // the expression s does not contain channel receives or
158 // function calls; in this case s is not evaluated."
159 if !check
.hasCallOrRecv
{
162 val
= constant
.MakeInt64(t
.len)
164 val
= constant
.MakeUnknown()
177 if mode
== invalid
&& typ
!= Typ
[Invalid
] {
178 check
.invalidArg(x
.pos(), "%s for %s", x
, bin
.name
)
185 if check
.Types
!= nil && mode
!= constant_
{
186 check
.recordBuiltinType(call
.Fun
, makeSig(x
.typ
, typ
))
191 c
, _
:= x
.typ
.Underlying().(*Chan
)
193 check
.invalidArg(x
.pos(), "%s is not a channel", x
)
196 if c
.dir
== RecvOnly
{
197 check
.invalidArg(x
.pos(), "%s must not be a receive-only channel", x
)
202 if check
.Types
!= nil {
203 check
.recordBuiltinType(call
.Fun
, makeSig(nil, c
))
207 // complex(x, y floatT) complexT
210 if y
.mode
== invalid
{
214 // convert or check untyped arguments
216 if isUntyped(x
.typ
) {
219 if isUntyped(y
.typ
) {
224 // x and y are typed => nothing to do
226 // only x is untyped => convert to type of y
227 check
.convertUntyped(x
, y
.typ
)
229 // only y is untyped => convert to type of x
230 check
.convertUntyped(&y
, x
.typ
)
232 // x and y are untyped =>
233 // 1) if both are constants, convert them to untyped
234 // floating-point numbers if possible,
235 // 2) if one of them is not constant (possible because
236 // it contains a shift that is yet untyped), convert
237 // both of them to float64 since they must have the
238 // same type to succeed (this will result in an error
239 // because shifts of floats are not permitted)
240 if x
.mode
== constant_
&& y
.mode
== constant_
{
241 toFloat
:= func(x
*operand
) {
242 if isNumeric(x
.typ
) && constant
.Sign(constant
.Imag(x
.val
)) == 0 {
243 x
.typ
= Typ
[UntypedFloat
]
249 check
.convertUntyped(x
, Typ
[Float64
])
250 check
.convertUntyped(&y
, Typ
[Float64
])
251 // x and y should be invalid now, but be conservative
255 if x
.mode
== invalid || y
.mode
== invalid
{
259 // both argument types must be identical
260 if !Identical(x
.typ
, y
.typ
) {
261 check
.invalidArg(x
.pos(), "mismatched types %s and %s", x
.typ
, y
.typ
)
265 // the argument types must be of floating-point type
267 check
.invalidArg(x
.pos(), "arguments have type %s, expected floating-point", x
.typ
)
271 // if both arguments are constants, the result is a constant
272 if x
.mode
== constant_
&& y
.mode
== constant_
{
273 x
.val
= constant
.BinaryOp(constant
.ToFloat(x
.val
), token
.ADD
, constant
.MakeImag(constant
.ToFloat(y
.val
)))
278 // determine result type
280 switch x
.typ
.Underlying().(*Basic
).kind
{
292 if check
.Types
!= nil && x
.mode
!= constant_
{
293 check
.recordBuiltinType(call
.Fun
, makeSig(resTyp
, x
.typ
, x
.typ
))
299 // copy(x, y []T) int
301 if t
, _
:= x
.typ
.Underlying().(*Slice
); t
!= nil {
307 if y
.mode
== invalid
{
311 switch t
:= y
.typ
.Underlying().(type) {
320 if dst
== nil || src
== nil {
321 check
.invalidArg(x
.pos(), "copy expects slice arguments; found %s and %s", x
, &y
)
325 if !Identical(dst
, src
) {
326 check
.invalidArg(x
.pos(), "arguments to copy %s and %s have different element types %s and %s", x
, &y
, dst
, src
)
330 if check
.Types
!= nil {
331 check
.recordBuiltinType(call
.Fun
, makeSig(Typ
[Int
], x
.typ
, y
.typ
))
338 m
, _
:= x
.typ
.Underlying().(*Map
)
340 check
.invalidArg(x
.pos(), "%s is not a map", x
)
344 if x
.mode
== invalid
{
348 if !x
.assignableTo(check
.conf
, m
.key
, nil) {
349 check
.invalidArg(x
.pos(), "%s is not assignable to %s", x
, m
.key
)
354 if check
.Types
!= nil {
355 check
.recordBuiltinType(call
.Fun
, makeSig(nil, m
, m
.key
))
359 // imag(complexT) floatT
360 // real(complexT) floatT
362 // convert or check untyped argument
363 if isUntyped(x
.typ
) {
364 if x
.mode
== constant_
{
365 // an untyped constant number can alway be considered
366 // as a complex constant
367 if isNumeric(x
.typ
) {
368 x
.typ
= Typ
[UntypedComplex
]
371 // an untyped non-constant argument may appear if
372 // it contains a (yet untyped non-constant) shift
373 // expression: convert it to complex128 which will
374 // result in an error (shift of complex value)
375 check
.convertUntyped(x
, Typ
[Complex128
])
376 // x should be invalid now, but be conservative and check
377 if x
.mode
== invalid
{
383 // the argument must be of complex type
384 if !isComplex(x
.typ
) {
385 check
.invalidArg(x
.pos(), "argument has type %s, expected complex type", x
.typ
)
389 // if the argument is a constant, the result is a constant
390 if x
.mode
== constant_
{
392 x
.val
= constant
.Real(x
.val
)
394 x
.val
= constant
.Imag(x
.val
)
400 // determine result type
402 switch x
.typ
.Underlying().(*Basic
).kind
{
414 if check
.Types
!= nil && x
.mode
!= constant_
{
415 check
.recordBuiltinType(call
.Fun
, makeSig(resTyp
, x
.typ
))
423 // (no argument evaluated yet)
426 if T
== Typ
[Invalid
] {
430 var min
int // minimum number of arguments
431 switch T
.Underlying().(type) {
437 check
.invalidArg(arg0
.Pos(), "cannot make %s; type must be slice, map, or channel", arg0
)
440 if nargs
< min || min
+1 < nargs
{
441 check
.errorf(call
.Pos(), "%v expects %d or %d arguments; found %d", call
, min
, min
+1, nargs
)
444 var sizes
[]int64 // constant integer arguments, if any
445 for _
, arg
:= range call
.Args
[1:] {
446 if s
, ok
:= check
.index(arg
, -1); ok
&& s
>= 0 {
447 sizes
= append(sizes
, s
)
450 if len(sizes
) == 2 && sizes
[0] > sizes
[1] {
451 check
.invalidArg(call
.Args
[1].Pos(), "length and capacity swapped")
456 if check
.Types
!= nil {
457 params
:= [...]Type
{T
, Typ
[Int
], Typ
[Int
]}
458 check
.recordBuiltinType(call
.Fun
, makeSig(x
.typ
, params
[:1+len(sizes
)]...))
463 // (no argument evaluated yet)
464 T
:= check
.typ(call
.Args
[0])
465 if T
== Typ
[Invalid
] {
470 x
.typ
= &Pointer
{base
: T
}
471 if check
.Types
!= nil {
472 check
.recordBuiltinType(call
.Fun
, makeSig(x
.typ
, T
))
477 // record panic call if inside a function with result parameters
478 // (for use in Checker.isTerminating)
479 if check
.sig
.results
.Len() > 0 {
480 // function has result parameters
484 p
= make(map[*ast
.CallExpr
]bool)
490 check
.assignment(x
, &emptyInterface
, "argument to panic")
491 if x
.mode
== invalid
{
496 if check
.Types
!= nil {
497 check
.recordBuiltinType(call
.Fun
, makeSig(nil, &emptyInterface
))
500 case _Print
, _Println
:
502 // println(x, y, ...)
505 params
= make([]Type
, nargs
)
506 for i
:= 0; i
< nargs
; i
++ {
508 arg(x
, i
) // first argument already evaluated
510 check
.assignment(x
, nil, "argument to "+predeclaredFuncs
[id
].name
)
511 if x
.mode
== invalid
{
512 // TODO(gri) "use" all arguments?
520 if check
.Types
!= nil {
521 check
.recordBuiltinType(call
.Fun
, makeSig(nil, params
...))
525 // recover() interface{}
527 x
.typ
= &emptyInterface
528 if check
.Types
!= nil {
529 check
.recordBuiltinType(call
.Fun
, makeSig(x
.typ
))
533 // unsafe.Alignof(x T) uintptr
534 check
.assignment(x
, nil, "argument to unsafe.Alignof")
535 if x
.mode
== invalid
{
540 x
.val
= constant
.MakeInt64(check
.conf
.alignof(x
.typ
))
542 // result is constant - no need to record signature
545 // unsafe.Offsetof(x T) uintptr, where x must be a selector
546 // (no argument evaluated yet)
548 selx
, _
:= unparen(arg0
).(*ast
.SelectorExpr
)
550 check
.invalidArg(arg0
.Pos(), "%s is not a selector expression", arg0
)
555 check
.expr(x
, selx
.X
)
556 if x
.mode
== invalid
{
560 base
:= derefStructPtr(x
.typ
)
562 obj
, index
, indirect
:= LookupFieldOrMethod(base
, false, check
.pkg
, sel
)
565 check
.invalidArg(x
.pos(), "%s has no single field %s", base
, sel
)
568 // TODO(gri) Using derefStructPtr may result in methods being found
569 // that don't actually exist. An error either way, but the error
570 // message is confusing. See: https://play.golang.org/p/al75v23kUy ,
571 // but go/types reports: "invalid argument: x.m is a method value".
572 check
.invalidArg(arg0
.Pos(), "%s is a method value", arg0
)
576 check
.invalidArg(x
.pos(), "field %s is embedded via a pointer in %s", sel
, base
)
580 // TODO(gri) Should we pass x.typ instead of base (and indirect report if derefStructPtr indirected)?
581 check
.recordSelection(selx
, FieldVal
, base
, obj
, index
, false)
583 offs
:= check
.conf
.offsetof(base
, index
)
585 x
.val
= constant
.MakeInt64(offs
)
587 // result is constant - no need to record signature
590 // unsafe.Sizeof(x T) uintptr
591 check
.assignment(x
, nil, "argument to unsafe.Sizeof")
592 if x
.mode
== invalid
{
597 x
.val
= constant
.MakeInt64(check
.conf
.sizeof(x
.typ
))
599 // result is constant - no need to record signature
602 // assert(pred) causes a typechecker error if pred is false.
603 // The result of assert is the value of pred if there is no error.
604 // Note: assert is only available in self-test mode.
605 if x
.mode
!= constant_ ||
!isBoolean(x
.typ
) {
606 check
.invalidArg(x
.pos(), "%s is not a boolean constant", x
)
609 if x
.val
.Kind() != constant
.Bool
{
610 check
.errorf(x
.pos(), "internal error: value of %s should be a boolean constant", x
)
613 if !constant
.BoolVal(x
.val
) {
614 check
.errorf(call
.Pos(), "%v failed", call
)
615 // compile-time assertion failure - safe to continue
617 // result is constant - no need to record signature
620 // trace(x, y, z, ...) dumps the positions, expressions, and
621 // values of its arguments. The result of trace is the value
622 // of the first argument.
623 // Note: trace is only available in self-test mode.
624 // (no argument evaluated yet)
626 check
.dump("%v: trace() without arguments", call
.Pos())
632 for _
, arg
:= range call
.Args
{
633 check
.rawExpr(x1
, arg
, nil) // permit trace for types, e.g.: new(trace(T))
634 check
.dump("%v: %s", x1
.pos(), x1
)
635 x1
= &t
// use incoming x only for first argument
637 // trace is only available in test mode - no need to record signature
646 // makeSig makes a signature for the given argument and result types.
647 // Default types are used for untyped arguments, and res may be nil.
648 func makeSig(res Type
, args
...Type
) *Signature
{
649 list
:= make([]*Var
, len(args
))
650 for i
, param
:= range args
{
651 list
[i
] = NewVar(token
.NoPos
, nil, "", Default(param
))
653 params
:= NewTuple(list
...)
656 assert(!isUntyped(res
))
657 result
= NewTuple(NewVar(token
.NoPos
, nil, "", res
))
659 return &Signature
{params
: params
, results
: result
}
662 // implicitArrayDeref returns A if typ is of the form *A and A is an array;
663 // otherwise it returns typ.
665 func implicitArrayDeref(typ Type
) Type
{
666 if p
, ok
:= typ
.(*Pointer
); ok
{
667 if a
, ok
:= p
.base
.Underlying().(*Array
); ok
{
674 // unparen returns e with any enclosing parentheses stripped.
675 func unparen(e ast
.Expr
) ast
.Expr
{
677 p
, ok
:= e
.(*ast
.ParenExpr
)