1 // Copyright 2013 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 call and selector expressions.
14 func (check
*Checker
) call(x
*operand
, e
*ast
.CallExpr
) exprKind
{
15 check
.exprOrType(x
, e
.Fun
)
28 switch n
:= len(e
.Args
); n
{
30 check
.errorf(e
.Rparen
, "missing argument in conversion to %s", T
)
32 check
.expr(x
, e
.Args
[0])
33 if x
.mode
!= invalid
{
34 check
.conversion(x
, T
)
37 check
.errorf(e
.Args
[n
-1].Pos(), "too many arguments in conversion to %s", T
)
44 if !check
.builtin(x
, e
, id
) {
48 // a non-constant result implies a function call
49 if x
.mode
!= invalid
&& x
.mode
!= constant_
{
50 check
.hasCallOrRecv
= true
52 return predeclaredFuncs
[id
].kind
55 // function/method call
56 sig
, _
:= x
.typ
.Underlying().(*Signature
)
58 check
.invalidOp(x
.pos(), "cannot call non-function %s", x
)
64 arg
, n
, _
:= unpack(func(x
*operand
, i
int) { check
.multiExpr(x
, e
.Args
[i
]) }, len(e
.Args
), false)
66 check
.arguments(x
, e
, sig
, arg
, n
)
72 switch sig
.results
.Len() {
77 x
.typ
= sig
.results
.vars
[0].typ
// unpack tuple
84 check
.hasCallOrRecv
= true
90 // use type-checks each argument.
91 // Useful to make sure expressions are evaluated
92 // (and variables are "used") in the presence of other errors.
93 // The arguments may be nil.
94 func (check
*Checker
) use(arg
...ast
.Expr
) {
96 for _
, e
:= range arg
{
97 // The nil check below is necessary since certain AST fields
98 // may legally be nil (e.g., the ast.SliceExpr.High field).
100 check
.rawExpr(&x
, e
, nil)
105 // useLHS is like use, but doesn't "use" top-level identifiers.
106 // It should be called instead of use if the arguments are
107 // expressions on the lhs of an assignment.
108 // The arguments must not be nil.
109 func (check
*Checker
) useLHS(arg
...ast
.Expr
) {
111 for _
, e
:= range arg
{
112 // If the lhs is an identifier denoting a variable v, this assignment
113 // is not a 'use' of v. Remember current value of v.used and restore
114 // after evaluating the lhs via check.rawExpr.
117 if ident
, _
:= unparen(e
).(*ast
.Ident
); ident
!= nil {
118 // never type-check the blank name on the lhs
119 if ident
.Name
== "_" {
122 if _
, obj
:= check
.scope
.LookupParent(ident
.Name
, token
.NoPos
); obj
!= nil {
123 // It's ok to mark non-local variables, but ignore variables
124 // from other packages to avoid potential race conditions with
125 // dot-imported variables.
126 if w
, _
:= obj
.(*Var
); w
!= nil && w
.pkg
== check
.pkg
{
132 check
.rawExpr(&x
, e
, nil)
134 v
.used
= v_used
// restore v.used
139 // useGetter is like use, but takes a getter instead of a list of expressions.
140 // It should be called instead of use if a getter is present to avoid repeated
141 // evaluation of the first argument (since the getter was likely obtained via
142 // unpack, which may have evaluated the first argument already).
143 func (check
*Checker
) useGetter(get getter
, n
int) {
145 for i
:= 0; i
< n
; i
++ {
150 // A getter sets x as the i'th operand, where 0 <= i < n and n is the total
151 // number of operands (context-specific, and maintained elsewhere). A getter
152 // type-checks the i'th operand; the details of the actual check are getter-
154 type getter
func(x
*operand
, i
int)
156 // unpack takes a getter get and a number of operands n. If n == 1, unpack
157 // calls the incoming getter for the first operand. If that operand is
158 // invalid, unpack returns (nil, 0, false). Otherwise, if that operand is a
159 // function call, or a comma-ok expression and allowCommaOk is set, the result
160 // is a new getter and operand count providing access to the function results,
161 // or comma-ok values, respectively. The third result value reports if it
162 // is indeed the comma-ok case. In all other cases, the incoming getter and
163 // operand count are returned unchanged, and the third result value is false.
165 // In other words, if there's exactly one operand that - after type-checking
166 // by calling get - stands for multiple operands, the resulting getter provides
167 // access to those operands instead.
169 // If the returned getter is called at most once for a given operand index i
170 // (including i == 0), that operand is guaranteed to cause only one call of
171 // the incoming getter with that i.
173 func unpack(get getter
, n
int, allowCommaOk
bool) (getter
, int, bool) {
175 // zero or multiple values
178 // possibly result of an n-valued function call or comma,ok value
181 if x0
.mode
== invalid
{
185 if t
, ok
:= x0
.typ
.(*Tuple
); ok
{
186 // result of an n-valued function call
187 return func(x
*operand
, i
int) {
194 if x0
.mode
== mapindex || x0
.mode
== commaok
{
197 a
:= [2]Type
{x0
.typ
, Typ
[UntypedBool
]}
198 return func(x
*operand
, i
int) {
208 return func(x
*operand
, i
int) {
216 // arguments checks argument passing for the call with the given signature.
217 // The arg function provides the operand for the i'th argument.
218 func (check
*Checker
) arguments(x
*operand
, call
*ast
.CallExpr
, sig
*Signature
, arg getter
, n
int) {
219 if call
.Ellipsis
.IsValid() {
220 // last argument is of the form x...
222 check
.errorf(call
.Ellipsis
, "cannot use ... in call to non-variadic %s", call
.Fun
)
223 check
.useGetter(arg
, n
)
226 if len(call
.Args
) == 1 && n
> 1 {
227 // f()... is not permitted if f() is multi-valued
228 check
.errorf(call
.Ellipsis
, "cannot use ... with %d-valued %s", n
, call
.Args
[0])
229 check
.useGetter(arg
, n
)
234 // evaluate arguments
235 for i
:= 0; i
< n
; i
++ {
237 if x
.mode
!= invalid
{
238 var ellipsis token
.Pos
239 if i
== n
-1 && call
.Ellipsis
.IsValid() {
240 ellipsis
= call
.Ellipsis
242 check
.argument(call
.Fun
, sig
, i
, x
, ellipsis
)
246 // check argument count
248 // a variadic function accepts an "empty"
249 // last argument: count one extra
252 if n
< sig
.params
.Len() {
253 check
.errorf(call
.Rparen
, "too few arguments in call to %s", call
.Fun
)
258 // argument checks passing of argument x to the i'th parameter of the given signature.
259 // If ellipsis is valid, the argument is followed by ... at that position in the call.
260 func (check
*Checker
) argument(fun ast
.Expr
, sig
*Signature
, i
int, x
*operand
, ellipsis token
.Pos
) {
262 if x
.mode
== invalid
{
266 n
:= sig
.params
.Len()
268 // determine parameter type
272 typ
= sig
.params
.vars
[i
].typ
274 typ
= sig
.params
.vars
[n
-1].typ
276 if _
, ok
:= typ
.(*Slice
); !ok
{
277 check
.dump("%s: expected unnamed slice type, got %s", sig
.params
.vars
[n
-1].Pos(), typ
)
281 check
.errorf(x
.pos(), "too many arguments")
285 if ellipsis
.IsValid() {
286 // argument is of the form x... and x is single-valued
288 check
.errorf(ellipsis
, "can only use ... with matching parameter")
291 if _
, ok
:= x
.typ
.Underlying().(*Slice
); !ok
&& x
.typ
!= Typ
[UntypedNil
] { // see issue #18268
292 check
.errorf(x
.pos(), "cannot use %s as parameter of type %s", x
, typ
)
295 } else if sig
.variadic
&& i
>= n
-1 {
296 // use the variadic parameter slice's element type
297 typ
= typ
.(*Slice
).elem
300 check
.assignment(x
, typ
, check
.sprintf("argument to %s", fun
))
303 func (check
*Checker
) selector(x
*operand
, e
*ast
.SelectorExpr
) {
304 // these must be declared before the "goto Error" statements
312 // If the identifier refers to a package, handle everything here
313 // so we don't need a "package" mode for operands: package names
314 // can only appear in qualified identifiers which are mapped to
315 // selector expressions.
316 if ident
, ok
:= e
.X
.(*ast
.Ident
); ok
{
317 _
, obj
:= check
.scope
.LookupParent(ident
.Name
, check
.pos
)
318 if pname
, _
:= obj
.(*PkgName
); pname
!= nil {
319 assert(pname
.pkg
== check
.pkg
)
320 check
.recordUse(ident
, pname
)
322 pkg
:= pname
.imported
323 exp
:= pkg
.scope
.Lookup(sel
)
326 check
.errorf(e
.Pos(), "%s not declared by package %s", sel
, pkg
.name
)
331 check
.errorf(e
.Pos(), "%s not exported by package %s", sel
, pkg
.name
)
334 check
.recordUse(e
.Sel
, exp
)
336 // Simplified version of the code for *ast.Idents:
337 // - imported objects are always fully initialized
338 switch exp
:= exp
.(type) {
340 assert(exp
.Val() != nil)
358 check
.dump("unexpected object %v", exp
)
366 check
.exprOrType(x
, e
.X
)
367 if x
.mode
== invalid
{
371 obj
, index
, indirect
= LookupFieldOrMethod(x
.typ
, x
.mode
== variable
, check
.pkg
, sel
)
375 // TODO(gri) should provide actual type where the conflict happens
376 check
.invalidOp(e
.Pos(), "ambiguous selector %s", sel
)
378 check
.invalidOp(e
.Pos(), "%s is not in method set of %s", sel
, x
.typ
)
380 check
.invalidOp(e
.Pos(), "%s has no field or method %s", x
, sel
)
385 if x
.mode
== typexpr
{
389 check
.invalidOp(e
.Pos(), "%s has no method %s", x
, sel
)
393 check
.recordSelection(e
, MethodExpr
, x
.typ
, m
, index
, indirect
)
395 // the receiver type becomes the type of the first function
396 // argument of the method expression's function type
398 sig
:= m
.typ
.(*Signature
)
399 if sig
.params
!= nil {
400 params
= sig
.params
.vars
404 params
: NewTuple(append([]*Var
{NewVar(token
.NoPos
, check
.pkg
, "", x
.typ
)}, params
...)...),
405 results
: sig
.results
,
406 variadic
: sig
.variadic
,
413 switch obj
:= obj
.(type) {
415 check
.recordSelection(e
, FieldVal
, x
.typ
, obj
, index
, indirect
)
416 if x
.mode
== variable || indirect
{
424 // TODO(gri) If we needed to take into account the receiver's
425 // addressability, should we report the type &(x.typ) instead?
426 check
.recordSelection(e
, MethodVal
, x
.typ
, obj
, index
, indirect
)
429 // Verify that LookupFieldOrMethod and MethodSet.Lookup agree.
431 if x
.mode
== variable
{
432 // If typ is not an (unnamed) pointer or an interface,
433 // use *typ instead, because the method set of *typ
434 // includes the methods of typ.
435 // Variables are addressable, so we can always take their
437 if _
, ok
:= typ
.(*Pointer
); !ok
&& !IsInterface(typ
) {
438 typ
= &Pointer
{base
: typ
}
441 // If we created a synthetic pointer type above, we will throw
442 // away the method set computed here after use.
443 // TODO(gri) Method set computation should probably always compute
444 // both, the value and the pointer receiver method set and represent
445 // them in a single structure.
446 // TODO(gri) Consider also using a method set cache for the lifetime
447 // of checker once we rely on MethodSet lookup instead of individual
449 mset
:= NewMethodSet(typ
)
450 if m
:= mset
.Lookup(check
.pkg
, sel
); m
== nil || m
.obj
!= obj
{
451 check
.dump("%s: (%s).%v -> %s", e
.Pos(), typ
, obj
.name
, m
)
452 check
.dump("%s\n", mset
)
453 panic("method sets and lookup don't agree")
460 sig
:= *obj
.typ
.(*Signature
)
464 check
.addDeclDep(obj
)
471 // everything went well