Home | History | Annotate | Download | only in types
      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.
      4 
      5 // This file implements typechecking of call and selector expressions.
      6 
      7 package types
      8 
      9 import (
     10 	"go/ast"
     11 	"go/token"
     12 )
     13 
     14 func (check *Checker) call(x *operand, e *ast.CallExpr) exprKind {
     15 	check.exprOrType(x, e.Fun)
     16 
     17 	switch x.mode {
     18 	case invalid:
     19 		check.use(e.Args...)
     20 		x.mode = invalid
     21 		x.expr = e
     22 		return statement
     23 
     24 	case typexpr:
     25 		// conversion
     26 		T := x.typ
     27 		x.mode = invalid
     28 		switch n := len(e.Args); n {
     29 		case 0:
     30 			check.errorf(e.Rparen, "missing argument in conversion to %s", T)
     31 		case 1:
     32 			check.expr(x, e.Args[0])
     33 			if x.mode != invalid {
     34 				check.conversion(x, T)
     35 			}
     36 		default:
     37 			check.errorf(e.Args[n-1].Pos(), "too many arguments in conversion to %s", T)
     38 		}
     39 		x.expr = e
     40 		return conversion
     41 
     42 	case builtin:
     43 		id := x.id
     44 		if !check.builtin(x, e, id) {
     45 			x.mode = invalid
     46 		}
     47 		x.expr = e
     48 		// a non-constant result implies a function call
     49 		if x.mode != invalid && x.mode != constant_ {
     50 			check.hasCallOrRecv = true
     51 		}
     52 		return predeclaredFuncs[id].kind
     53 
     54 	default:
     55 		// function/method call
     56 		sig, _ := x.typ.Underlying().(*Signature)
     57 		if sig == nil {
     58 			check.invalidOp(x.pos(), "cannot call non-function %s", x)
     59 			x.mode = invalid
     60 			x.expr = e
     61 			return statement
     62 		}
     63 
     64 		arg, n, _ := unpack(func(x *operand, i int) { check.multiExpr(x, e.Args[i]) }, len(e.Args), false)
     65 		if arg != nil {
     66 			check.arguments(x, e, sig, arg, n)
     67 		} else {
     68 			x.mode = invalid
     69 		}
     70 
     71 		// determine result
     72 		switch sig.results.Len() {
     73 		case 0:
     74 			x.mode = novalue
     75 		case 1:
     76 			x.mode = value
     77 			x.typ = sig.results.vars[0].typ // unpack tuple
     78 		default:
     79 			x.mode = value
     80 			x.typ = sig.results
     81 		}
     82 
     83 		x.expr = e
     84 		check.hasCallOrRecv = true
     85 
     86 		return statement
     87 	}
     88 }
     89 
     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) {
     95 	var x operand
     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).
     99 		if e != nil {
    100 			check.rawExpr(&x, e, nil)
    101 		}
    102 	}
    103 }
    104 
    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) {
    110 	var x operand
    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.
    115 		var v *Var
    116 		var v_used bool
    117 		if ident, _ := unparen(e).(*ast.Ident); ident != nil {
    118 			// never type-check the blank name on the lhs
    119 			if ident.Name == "_" {
    120 				continue
    121 			}
    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 {
    127 					v = w
    128 					v_used = v.used
    129 				}
    130 			}
    131 		}
    132 		check.rawExpr(&x, e, nil)
    133 		if v != nil {
    134 			v.used = v_used // restore v.used
    135 		}
    136 	}
    137 }
    138 
    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) {
    144 	var x operand
    145 	for i := 0; i < n; i++ {
    146 		get(&x, i)
    147 	}
    148 }
    149 
    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-
    153 // specific.
    154 type getter func(x *operand, i int)
    155 
    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.
    164 //
    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.
    168 //
    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.
    172 //
    173 func unpack(get getter, n int, allowCommaOk bool) (getter, int, bool) {
    174 	if n != 1 {
    175 		// zero or multiple values
    176 		return get, n, false
    177 	}
    178 	// possibly result of an n-valued function call or comma,ok value
    179 	var x0 operand
    180 	get(&x0, 0)
    181 	if x0.mode == invalid {
    182 		return nil, 0, false
    183 	}
    184 
    185 	if t, ok := x0.typ.(*Tuple); ok {
    186 		// result of an n-valued function call
    187 		return func(x *operand, i int) {
    188 			x.mode = value
    189 			x.expr = x0.expr
    190 			x.typ = t.At(i).typ
    191 		}, t.Len(), false
    192 	}
    193 
    194 	if x0.mode == mapindex || x0.mode == commaok {
    195 		// comma-ok value
    196 		if allowCommaOk {
    197 			a := [2]Type{x0.typ, Typ[UntypedBool]}
    198 			return func(x *operand, i int) {
    199 				x.mode = value
    200 				x.expr = x0.expr
    201 				x.typ = a[i]
    202 			}, 2, true
    203 		}
    204 		x0.mode = value
    205 	}
    206 
    207 	// single value
    208 	return func(x *operand, i int) {
    209 		if i != 0 {
    210 			unreachable()
    211 		}
    212 		*x = x0
    213 	}, 1, false
    214 }
    215 
    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...
    221 		if !sig.variadic {
    222 			check.errorf(call.Ellipsis, "cannot use ... in call to non-variadic %s", call.Fun)
    223 			check.useGetter(arg, n)
    224 			return
    225 		}
    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)
    230 			return
    231 		}
    232 	}
    233 
    234 	// evaluate arguments
    235 	for i := 0; i < n; i++ {
    236 		arg(x, i)
    237 		if x.mode != invalid {
    238 			var ellipsis token.Pos
    239 			if i == n-1 && call.Ellipsis.IsValid() {
    240 				ellipsis = call.Ellipsis
    241 			}
    242 			check.argument(call.Fun, sig, i, x, ellipsis)
    243 		}
    244 	}
    245 
    246 	// check argument count
    247 	if sig.variadic {
    248 		// a variadic function accepts an "empty"
    249 		// last argument: count one extra
    250 		n++
    251 	}
    252 	if n < sig.params.Len() {
    253 		check.errorf(call.Rparen, "too few arguments in call to %s", call.Fun)
    254 		// ok to continue
    255 	}
    256 }
    257 
    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) {
    261 	check.singleValue(x)
    262 	if x.mode == invalid {
    263 		return
    264 	}
    265 
    266 	n := sig.params.Len()
    267 
    268 	// determine parameter type
    269 	var typ Type
    270 	switch {
    271 	case i < n:
    272 		typ = sig.params.vars[i].typ
    273 	case sig.variadic:
    274 		typ = sig.params.vars[n-1].typ
    275 		if debug {
    276 			if _, ok := typ.(*Slice); !ok {
    277 				check.dump("%s: expected unnamed slice type, got %s", sig.params.vars[n-1].Pos(), typ)
    278 			}
    279 		}
    280 	default:
    281 		check.errorf(x.pos(), "too many arguments")
    282 		return
    283 	}
    284 
    285 	if ellipsis.IsValid() {
    286 		// argument is of the form x... and x is single-valued
    287 		if i != n-1 {
    288 			check.errorf(ellipsis, "can only use ... with matching parameter")
    289 			return
    290 		}
    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)
    293 			return
    294 		}
    295 	} else if sig.variadic && i >= n-1 {
    296 		// use the variadic parameter slice's element type
    297 		typ = typ.(*Slice).elem
    298 	}
    299 
    300 	check.assignment(x, typ, check.sprintf("argument to %s", fun))
    301 }
    302 
    303 func (check *Checker) selector(x *operand, e *ast.SelectorExpr) {
    304 	// these must be declared before the "goto Error" statements
    305 	var (
    306 		obj      Object
    307 		index    []int
    308 		indirect bool
    309 	)
    310 
    311 	sel := e.Sel.Name
    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)
    321 			pname.used = true
    322 			pkg := pname.imported
    323 			exp := pkg.scope.Lookup(sel)
    324 			if exp == nil {
    325 				if !pkg.fake {
    326 					check.errorf(e.Pos(), "%s not declared by package %s", sel, pkg.name)
    327 				}
    328 				goto Error
    329 			}
    330 			if !exp.Exported() {
    331 				check.errorf(e.Pos(), "%s not exported by package %s", sel, pkg.name)
    332 				// ok to continue
    333 			}
    334 			check.recordUse(e.Sel, exp)
    335 
    336 			// Simplified version of the code for *ast.Idents:
    337 			// - imported objects are always fully initialized
    338 			switch exp := exp.(type) {
    339 			case *Const:
    340 				assert(exp.Val() != nil)
    341 				x.mode = constant_
    342 				x.typ = exp.typ
    343 				x.val = exp.val
    344 			case *TypeName:
    345 				x.mode = typexpr
    346 				x.typ = exp.typ
    347 			case *Var:
    348 				x.mode = variable
    349 				x.typ = exp.typ
    350 			case *Func:
    351 				x.mode = value
    352 				x.typ = exp.typ
    353 			case *Builtin:
    354 				x.mode = builtin
    355 				x.typ = exp.typ
    356 				x.id = exp.id
    357 			default:
    358 				check.dump("unexpected object %v", exp)
    359 				unreachable()
    360 			}
    361 			x.expr = e
    362 			return
    363 		}
    364 	}
    365 
    366 	check.exprOrType(x, e.X)
    367 	if x.mode == invalid {
    368 		goto Error
    369 	}
    370 
    371 	obj, index, indirect = LookupFieldOrMethod(x.typ, x.mode == variable, check.pkg, sel)
    372 	if obj == nil {
    373 		switch {
    374 		case index != nil:
    375 			// TODO(gri) should provide actual type where the conflict happens
    376 			check.invalidOp(e.Pos(), "ambiguous selector %s", sel)
    377 		case indirect:
    378 			check.invalidOp(e.Pos(), "%s is not in method set of %s", sel, x.typ)
    379 		default:
    380 			check.invalidOp(e.Pos(), "%s has no field or method %s", x, sel)
    381 		}
    382 		goto Error
    383 	}
    384 
    385 	if x.mode == typexpr {
    386 		// method expression
    387 		m, _ := obj.(*Func)
    388 		if m == nil {
    389 			check.invalidOp(e.Pos(), "%s has no method %s", x, sel)
    390 			goto Error
    391 		}
    392 
    393 		check.recordSelection(e, MethodExpr, x.typ, m, index, indirect)
    394 
    395 		// the receiver type becomes the type of the first function
    396 		// argument of the method expression's function type
    397 		var params []*Var
    398 		sig := m.typ.(*Signature)
    399 		if sig.params != nil {
    400 			params = sig.params.vars
    401 		}
    402 		x.mode = value
    403 		x.typ = &Signature{
    404 			params:   NewTuple(append([]*Var{NewVar(token.NoPos, check.pkg, "", x.typ)}, params...)...),
    405 			results:  sig.results,
    406 			variadic: sig.variadic,
    407 		}
    408 
    409 		check.addDeclDep(m)
    410 
    411 	} else {
    412 		// regular selector
    413 		switch obj := obj.(type) {
    414 		case *Var:
    415 			check.recordSelection(e, FieldVal, x.typ, obj, index, indirect)
    416 			if x.mode == variable || indirect {
    417 				x.mode = variable
    418 			} else {
    419 				x.mode = value
    420 			}
    421 			x.typ = obj.typ
    422 
    423 		case *Func:
    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)
    427 
    428 			if debug {
    429 				// Verify that LookupFieldOrMethod and MethodSet.Lookup agree.
    430 				typ := x.typ
    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
    436 					// address.
    437 					if _, ok := typ.(*Pointer); !ok && !IsInterface(typ) {
    438 						typ = &Pointer{base: typ}
    439 					}
    440 				}
    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
    448 				// lookup.
    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")
    454 				}
    455 			}
    456 
    457 			x.mode = value
    458 
    459 			// remove receiver
    460 			sig := *obj.typ.(*Signature)
    461 			sig.recv = nil
    462 			x.typ = &sig
    463 
    464 			check.addDeclDep(obj)
    465 
    466 		default:
    467 			unreachable()
    468 		}
    469 	}
    470 
    471 	// everything went well
    472 	x.expr = e
    473 	return
    474 
    475 Error:
    476 	x.mode = invalid
    477 	x.expr = e
    478 }
    479