github.com/dannin/go@v0.0.0-20161031215817-d35dfd405eaa/src/go/types/call.go (about) 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 func (check *Checker) use(arg ...ast.Expr) { 94 var x operand 95 for _, e := range arg { 96 check.rawExpr(&x, e, nil) 97 } 98 } 99 100 // useGetter is like use, but takes a getter instead of a list of expressions. 101 // It should be called instead of use if a getter is present to avoid repeated 102 // evaluation of the first argument (since the getter was likely obtained via 103 // unpack, which may have evaluated the first argument already). 104 func (check *Checker) useGetter(get getter, n int) { 105 var x operand 106 for i := 0; i < n; i++ { 107 get(&x, i) 108 } 109 } 110 111 // A getter sets x as the i'th operand, where 0 <= i < n and n is the total 112 // number of operands (context-specific, and maintained elsewhere). A getter 113 // type-checks the i'th operand; the details of the actual check are getter- 114 // specific. 115 type getter func(x *operand, i int) 116 117 // unpack takes a getter get and a number of operands n. If n == 1, unpack 118 // calls the incoming getter for the first operand. If that operand is 119 // invalid, unpack returns (nil, 0, false). Otherwise, if that operand is a 120 // function call, or a comma-ok expression and allowCommaOk is set, the result 121 // is a new getter and operand count providing access to the function results, 122 // or comma-ok values, respectively. The third result value reports if it 123 // is indeed the comma-ok case. In all other cases, the incoming getter and 124 // operand count are returned unchanged, and the third result value is false. 125 // 126 // In other words, if there's exactly one operand that - after type-checking 127 // by calling get - stands for multiple operands, the resulting getter provides 128 // access to those operands instead. 129 // 130 // If the returned getter is called at most once for a given operand index i 131 // (including i == 0), that operand is guaranteed to cause only one call of 132 // the incoming getter with that i. 133 // 134 func unpack(get getter, n int, allowCommaOk bool) (getter, int, bool) { 135 if n == 1 { 136 // possibly result of an n-valued function call or comma,ok value 137 var x0 operand 138 get(&x0, 0) 139 if x0.mode == invalid { 140 return nil, 0, false 141 } 142 143 if t, ok := x0.typ.(*Tuple); ok { 144 // result of an n-valued function call 145 return func(x *operand, i int) { 146 x.mode = value 147 x.expr = x0.expr 148 x.typ = t.At(i).typ 149 }, t.Len(), false 150 } 151 152 if x0.mode == mapindex || x0.mode == commaok { 153 // comma-ok value 154 if allowCommaOk { 155 a := [2]Type{x0.typ, Typ[UntypedBool]} 156 return func(x *operand, i int) { 157 x.mode = value 158 x.expr = x0.expr 159 x.typ = a[i] 160 }, 2, true 161 } 162 x0.mode = value 163 } 164 165 // single value 166 return func(x *operand, i int) { 167 if i != 0 { 168 unreachable() 169 } 170 *x = x0 171 }, 1, false 172 } 173 174 // zero or multiple values 175 return get, n, false 176 } 177 178 // arguments checks argument passing for the call with the given signature. 179 // The arg function provides the operand for the i'th argument. 180 func (check *Checker) arguments(x *operand, call *ast.CallExpr, sig *Signature, arg getter, n int) { 181 if call.Ellipsis.IsValid() { 182 // last argument is of the form x... 183 if !sig.variadic { 184 check.errorf(call.Ellipsis, "cannot use ... in call to non-variadic %s", call.Fun) 185 check.useGetter(arg, n) 186 return 187 } 188 if len(call.Args) == 1 && n > 1 { 189 // f()... is not permitted if f() is multi-valued 190 check.errorf(call.Ellipsis, "cannot use ... with %d-valued %s", n, call.Args[0]) 191 check.useGetter(arg, n) 192 return 193 } 194 } 195 196 // evaluate arguments 197 for i := 0; i < n; i++ { 198 arg(x, i) 199 if x.mode != invalid { 200 var ellipsis token.Pos 201 if i == n-1 && call.Ellipsis.IsValid() { 202 ellipsis = call.Ellipsis 203 } 204 check.argument(call.Fun, sig, i, x, ellipsis) 205 } 206 } 207 208 // check argument count 209 if sig.variadic { 210 // a variadic function accepts an "empty" 211 // last argument: count one extra 212 n++ 213 } 214 if n < sig.params.Len() { 215 check.errorf(call.Rparen, "too few arguments in call to %s", call.Fun) 216 // ok to continue 217 } 218 } 219 220 // argument checks passing of argument x to the i'th parameter of the given signature. 221 // If ellipsis is valid, the argument is followed by ... at that position in the call. 222 func (check *Checker) argument(fun ast.Expr, sig *Signature, i int, x *operand, ellipsis token.Pos) { 223 check.singleValue(x) 224 if x.mode == invalid { 225 return 226 } 227 228 n := sig.params.Len() 229 230 // determine parameter type 231 var typ Type 232 switch { 233 case i < n: 234 typ = sig.params.vars[i].typ 235 case sig.variadic: 236 typ = sig.params.vars[n-1].typ 237 if debug { 238 if _, ok := typ.(*Slice); !ok { 239 check.dump("%s: expected unnamed slice type, got %s", sig.params.vars[n-1].Pos(), typ) 240 } 241 } 242 default: 243 check.errorf(x.pos(), "too many arguments") 244 return 245 } 246 247 if ellipsis.IsValid() { 248 // argument is of the form x... and x is single-valued 249 if i != n-1 { 250 check.errorf(ellipsis, "can only use ... with matching parameter") 251 return 252 } 253 if _, ok := x.typ.Underlying().(*Slice); !ok { 254 check.errorf(x.pos(), "cannot use %s as parameter of type %s", x, typ) 255 return 256 } 257 } else if sig.variadic && i >= n-1 { 258 // use the variadic parameter slice's element type 259 typ = typ.(*Slice).elem 260 } 261 262 check.assignment(x, typ, check.sprintf("argument to %s", fun)) 263 } 264 265 func (check *Checker) selector(x *operand, e *ast.SelectorExpr) { 266 // these must be declared before the "goto Error" statements 267 var ( 268 obj Object 269 index []int 270 indirect bool 271 ) 272 273 sel := e.Sel.Name 274 // If the identifier refers to a package, handle everything here 275 // so we don't need a "package" mode for operands: package names 276 // can only appear in qualified identifiers which are mapped to 277 // selector expressions. 278 // (see also decl.go: checker.aliasDecl) 279 // TODO(gri) factor this code out and share with checker.aliasDecl 280 if ident, ok := e.X.(*ast.Ident); ok { 281 _, obj := check.scope.LookupParent(ident.Name, check.pos) 282 if pname, _ := obj.(*PkgName); pname != nil { 283 assert(pname.pkg == check.pkg) 284 check.recordUse(ident, pname) 285 pname.used = true 286 pkg := pname.imported 287 exp := pkg.scope.Lookup(sel) 288 if exp == nil { 289 if !pkg.fake { 290 check.errorf(e.Pos(), "%s not declared by package %s", sel, pkg.name) 291 } 292 goto Error 293 } 294 if !exp.Exported() { 295 check.errorf(e.Pos(), "%s not exported by package %s", sel, pkg.name) 296 // ok to continue 297 } 298 check.recordUse(e.Sel, exp) 299 // Simplified version of the code for *ast.Idents: 300 // - imported objects are always fully initialized 301 switch exp := exp.(type) { 302 case *Const: 303 assert(exp.Val() != nil) 304 x.mode = constant_ 305 x.typ = exp.typ 306 x.val = exp.val 307 case *TypeName: 308 x.mode = typexpr 309 x.typ = exp.typ 310 case *Var: 311 x.mode = variable 312 x.typ = exp.typ 313 case *Func: 314 x.mode = value 315 x.typ = exp.typ 316 case *Builtin: 317 x.mode = builtin 318 x.typ = exp.typ 319 x.id = exp.id 320 default: 321 unreachable() 322 } 323 x.expr = e 324 return 325 } 326 } 327 328 check.exprOrType(x, e.X) 329 if x.mode == invalid { 330 goto Error 331 } 332 333 obj, index, indirect = LookupFieldOrMethod(x.typ, x.mode == variable, check.pkg, sel) 334 if obj == nil { 335 switch { 336 case index != nil: 337 // TODO(gri) should provide actual type where the conflict happens 338 check.invalidOp(e.Pos(), "ambiguous selector %s", sel) 339 case indirect: 340 check.invalidOp(e.Pos(), "%s is not in method set of %s", sel, x.typ) 341 default: 342 check.invalidOp(e.Pos(), "%s has no field or method %s", x, sel) 343 } 344 goto Error 345 } 346 347 if x.mode == typexpr { 348 // method expression 349 m, _ := obj.(*Func) 350 if m == nil { 351 check.invalidOp(e.Pos(), "%s has no method %s", x, sel) 352 goto Error 353 } 354 355 check.recordSelection(e, MethodExpr, x.typ, m, index, indirect) 356 357 // the receiver type becomes the type of the first function 358 // argument of the method expression's function type 359 var params []*Var 360 sig := m.typ.(*Signature) 361 if sig.params != nil { 362 params = sig.params.vars 363 } 364 x.mode = value 365 x.typ = &Signature{ 366 params: NewTuple(append([]*Var{NewVar(token.NoPos, check.pkg, "", x.typ)}, params...)...), 367 results: sig.results, 368 variadic: sig.variadic, 369 } 370 371 check.addDeclDep(m) 372 373 } else { 374 // regular selector 375 switch obj := obj.(type) { 376 case *Var: 377 check.recordSelection(e, FieldVal, x.typ, obj, index, indirect) 378 if x.mode == variable || indirect { 379 x.mode = variable 380 } else { 381 x.mode = value 382 } 383 x.typ = obj.typ 384 385 case *Func: 386 // TODO(gri) If we needed to take into account the receiver's 387 // addressability, should we report the type &(x.typ) instead? 388 check.recordSelection(e, MethodVal, x.typ, obj, index, indirect) 389 390 if debug { 391 // Verify that LookupFieldOrMethod and MethodSet.Lookup agree. 392 typ := x.typ 393 if x.mode == variable { 394 // If typ is not an (unnamed) pointer or an interface, 395 // use *typ instead, because the method set of *typ 396 // includes the methods of typ. 397 // Variables are addressable, so we can always take their 398 // address. 399 if _, ok := typ.(*Pointer); !ok && !IsInterface(typ) { 400 typ = &Pointer{base: typ} 401 } 402 } 403 // If we created a synthetic pointer type above, we will throw 404 // away the method set computed here after use. 405 // TODO(gri) Method set computation should probably always compute 406 // both, the value and the pointer receiver method set and represent 407 // them in a single structure. 408 // TODO(gri) Consider also using a method set cache for the lifetime 409 // of checker once we rely on MethodSet lookup instead of individual 410 // lookup. 411 mset := NewMethodSet(typ) 412 if m := mset.Lookup(check.pkg, sel); m == nil || m.obj != obj { 413 check.dump("%s: (%s).%v -> %s", e.Pos(), typ, obj.name, m) 414 check.dump("%s\n", mset) 415 panic("method sets and lookup don't agree") 416 } 417 } 418 419 x.mode = value 420 421 // remove receiver 422 sig := *obj.typ.(*Signature) 423 sig.recv = nil 424 x.typ = &sig 425 426 check.addDeclDep(obj) 427 428 default: 429 unreachable() 430 } 431 } 432 433 // everything went well 434 x.expr = e 435 return 436 437 Error: 438 x.mode = invalid 439 x.expr = e 440 }