github.com/gmemcc/yaegi@v0.12.1-0.20221128122509-aa99124c5d16/internal/cmd/extract/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 "strings" 13 "unicode" 14 ) 15 16 func (check *Checker) call(x *operand, e *ast.CallExpr) exprKind { 17 check.exprOrType(x, e.Fun) 18 19 switch x.mode { 20 case invalid: 21 check.use(e.Args...) 22 x.mode = invalid 23 x.expr = e 24 return statement 25 26 case typexpr: 27 // conversion 28 T := x.typ 29 x.mode = invalid 30 switch n := len(e.Args); n { 31 case 0: 32 check.errorf(inNode(e, e.Rparen), _WrongArgCount, "missing argument in conversion to %s", T) 33 case 1: 34 check.expr(x, e.Args[0]) 35 if x.mode != invalid { 36 if e.Ellipsis.IsValid() { 37 check.errorf(e.Args[0], _BadDotDotDotSyntax, "invalid use of ... in conversion to %s", T) 38 break 39 } 40 check.conversion(x, T) 41 } 42 default: 43 check.use(e.Args...) 44 check.errorf(e.Args[n-1], _WrongArgCount, "too many arguments in conversion to %s", T) 45 } 46 x.expr = e 47 return conversion 48 49 case builtin: 50 id := x.id 51 if !check.builtin(x, e, id) { 52 x.mode = invalid 53 } 54 x.expr = e 55 // a non-constant result implies a function call 56 if x.mode != invalid && x.mode != constant_ { 57 check.hasCallOrRecv = true 58 } 59 return predeclaredFuncs[id].kind 60 61 default: 62 // function/method call 63 cgocall := x.mode == cgofunc 64 65 sig, _ := x.typ.Underlying().(*Signature) 66 if sig == nil { 67 check.invalidOp(x, _InvalidCall, "cannot call non-function %s", x) 68 x.mode = invalid 69 x.expr = e 70 return statement 71 } 72 73 arg, n, _ := unpack(func(x *operand, i int) { check.multiExpr(x, e.Args[i]) }, len(e.Args), false) 74 if arg != nil { 75 check.arguments(x, e, sig, arg, n) 76 } else { 77 x.mode = invalid 78 } 79 80 // determine result 81 switch sig.results.Len() { 82 case 0: 83 x.mode = novalue 84 case 1: 85 if cgocall { 86 x.mode = commaerr 87 } else { 88 x.mode = value 89 } 90 x.typ = sig.results.vars[0].typ // unpack tuple 91 default: 92 x.mode = value 93 x.typ = sig.results 94 } 95 96 x.expr = e 97 check.hasCallOrRecv = true 98 99 return statement 100 } 101 } 102 103 // use type-checks each argument. 104 // Useful to make sure expressions are evaluated 105 // (and variables are "used") in the presence of other errors. 106 // The arguments may be nil. 107 func (check *Checker) use(arg ...ast.Expr) { 108 var x operand 109 for _, e := range arg { 110 // The nil check below is necessary since certain AST fields 111 // may legally be nil (e.g., the ast.SliceExpr.High field). 112 if e != nil { 113 check.rawExpr(&x, e, nil) 114 } 115 } 116 } 117 118 // useLHS is like use, but doesn't "use" top-level identifiers. 119 // It should be called instead of use if the arguments are 120 // expressions on the lhs of an assignment. 121 // The arguments must not be nil. 122 func (check *Checker) useLHS(arg ...ast.Expr) { 123 var x operand 124 for _, e := range arg { 125 // If the lhs is an identifier denoting a variable v, this assignment 126 // is not a 'use' of v. Remember current value of v.used and restore 127 // after evaluating the lhs via check.rawExpr. 128 var v *Var 129 var v_used bool 130 if ident, _ := unparen(e).(*ast.Ident); ident != nil { 131 // never type-check the blank name on the lhs 132 if ident.Name == "_" { 133 continue 134 } 135 if _, obj := check.scope.LookupParent(ident.Name, token.NoPos); obj != nil { 136 // It's ok to mark non-local variables, but ignore variables 137 // from other packages to avoid potential race conditions with 138 // dot-imported variables. 139 if w, _ := obj.(*Var); w != nil && w.pkg == check.pkg { 140 v = w 141 v_used = v.used 142 } 143 } 144 } 145 check.rawExpr(&x, e, nil) 146 if v != nil { 147 v.used = v_used // restore v.used 148 } 149 } 150 } 151 152 // useGetter is like use, but takes a getter instead of a list of expressions. 153 // It should be called instead of use if a getter is present to avoid repeated 154 // evaluation of the first argument (since the getter was likely obtained via 155 // unpack, which may have evaluated the first argument already). 156 func (check *Checker) useGetter(get getter, n int) { 157 var x operand 158 for i := 0; i < n; i++ { 159 get(&x, i) 160 } 161 } 162 163 // A getter sets x as the i'th operand, where 0 <= i < n and n is the total 164 // number of operands (context-specific, and maintained elsewhere). A getter 165 // type-checks the i'th operand; the details of the actual check are getter- 166 // specific. 167 type getter func(x *operand, i int) 168 169 // unpack takes a getter get and a number of operands n. If n == 1, unpack 170 // calls the incoming getter for the first operand. If that operand is 171 // invalid, unpack returns (nil, 0, false). Otherwise, if that operand is a 172 // function call, or a comma-ok expression and allowCommaOk is set, the result 173 // is a new getter and operand count providing access to the function results, 174 // or comma-ok values, respectively. The third result value reports if it 175 // is indeed the comma-ok case. In all other cases, the incoming getter and 176 // operand count are returned unchanged, and the third result value is false. 177 // 178 // In other words, if there's exactly one operand that - after type-checking 179 // by calling get - stands for multiple operands, the resulting getter provides 180 // access to those operands instead. 181 // 182 // If the returned getter is called at most once for a given operand index i 183 // (including i == 0), that operand is guaranteed to cause only one call of 184 // the incoming getter with that i. 185 // 186 func unpack(get getter, n int, allowCommaOk bool) (getter, int, bool) { 187 if n != 1 { 188 // zero or multiple values 189 return get, n, false 190 } 191 // possibly result of an n-valued function call or comma,ok value 192 var x0 operand 193 get(&x0, 0) 194 if x0.mode == invalid { 195 return nil, 0, false 196 } 197 198 if t, ok := x0.typ.(*Tuple); ok { 199 // result of an n-valued function call 200 return func(x *operand, i int) { 201 x.mode = value 202 x.expr = x0.expr 203 x.typ = t.At(i).typ 204 }, t.Len(), false 205 } 206 207 if x0.mode == mapindex || x0.mode == commaok || x0.mode == commaerr { 208 // comma-ok value 209 if allowCommaOk { 210 a := [2]Type{x0.typ, Typ[UntypedBool]} 211 if x0.mode == commaerr { 212 a[1] = universeError 213 } 214 return func(x *operand, i int) { 215 x.mode = value 216 x.expr = x0.expr 217 x.typ = a[i] 218 }, 2, true 219 } 220 x0.mode = value 221 } 222 223 // single value 224 return func(x *operand, i int) { 225 if i != 0 { 226 unreachable() 227 } 228 *x = x0 229 }, 1, false 230 } 231 232 // arguments checks argument passing for the call with the given signature. 233 // The arg function provides the operand for the i'th argument. 234 func (check *Checker) arguments(x *operand, call *ast.CallExpr, sig *Signature, arg getter, n int) { 235 if call.Ellipsis.IsValid() { 236 // last argument is of the form x... 237 if !sig.variadic { 238 check.errorf(atPos(call.Ellipsis), _NonVariadicDotDotDot, "cannot use ... in call to non-variadic %s", call.Fun) 239 check.useGetter(arg, n) 240 return 241 } 242 if len(call.Args) == 1 && n > 1 { 243 // f()... is not permitted if f() is multi-valued 244 check.errorf(atPos(call.Ellipsis), _InvalidDotDotDotOperand, "cannot use ... with %d-valued %s", n, call.Args[0]) 245 check.useGetter(arg, n) 246 return 247 } 248 } 249 250 // evaluate arguments 251 context := check.sprintf("argument to %s", call.Fun) 252 for i := 0; i < n; i++ { 253 arg(x, i) 254 if x.mode != invalid { 255 var ellipsis token.Pos 256 if i == n-1 && call.Ellipsis.IsValid() { 257 ellipsis = call.Ellipsis 258 } 259 check.argument(sig, i, x, ellipsis, context) 260 } 261 } 262 263 // check argument count 264 if sig.variadic { 265 // a variadic function accepts an "empty" 266 // last argument: count one extra 267 n++ 268 } 269 if n < sig.params.Len() { 270 check.errorf(inNode(call, call.Rparen), _WrongArgCount, "too few arguments in call to %s", call.Fun) 271 // ok to continue 272 } 273 } 274 275 // argument checks passing of argument x to the i'th parameter of the given signature. 276 // If ellipsis is valid, the argument is followed by ... at that position in the call. 277 func (check *Checker) argument(sig *Signature, i int, x *operand, ellipsis token.Pos, context string) { 278 check.singleValue(x) 279 if x.mode == invalid { 280 return 281 } 282 283 n := sig.params.Len() 284 285 // determine parameter type 286 var typ Type 287 switch { 288 case i < n: 289 typ = sig.params.vars[i].typ 290 case sig.variadic: 291 typ = sig.params.vars[n-1].typ 292 if debug { 293 if _, ok := typ.(*Slice); !ok { 294 check.dump("%v: expected unnamed slice type, got %s", sig.params.vars[n-1].Pos(), typ) 295 } 296 } 297 default: 298 check.errorf(x, _WrongArgCount, "too many arguments") 299 return 300 } 301 302 if ellipsis.IsValid() { 303 if i != n-1 { 304 check.errorf(atPos(ellipsis), _MisplacedDotDotDot, "can only use ... with matching parameter") 305 return 306 } 307 // argument is of the form x... and x is single-valued 308 if _, ok := x.typ.Underlying().(*Slice); !ok && x.typ != Typ[UntypedNil] { // see issue #18268 309 check.errorf(x, _InvalidDotDotDotOperand, "cannot use %s as parameter of type %s", x, typ) 310 return 311 } 312 } else if sig.variadic && i >= n-1 { 313 // use the variadic parameter slice's element type 314 typ = typ.(*Slice).elem 315 } 316 317 check.assignment(x, typ, context) 318 } 319 320 var cgoPrefixes = [...]string{ 321 "_Ciconst_", 322 "_Cfconst_", 323 "_Csconst_", 324 "_Ctype_", 325 "_Cvar_", // actually a pointer to the var 326 "_Cfpvar_fp_", 327 "_Cfunc_", 328 "_Cmacro_", // function to evaluate the expanded expression 329 } 330 331 func (check *Checker) selector(x *operand, e *ast.SelectorExpr) { 332 // these must be declared before the "goto Error" statements 333 var ( 334 obj Object 335 index []int 336 indirect bool 337 ) 338 339 sel := e.Sel.Name 340 // If the identifier refers to a package, handle everything here 341 // so we don't need a "package" mode for operands: package names 342 // can only appear in qualified identifiers which are mapped to 343 // selector expressions. 344 if ident, ok := e.X.(*ast.Ident); ok { 345 obj := check.lookup(ident.Name) 346 if pname, _ := obj.(*PkgName); pname != nil { 347 assert(pname.pkg == check.pkg) 348 check.recordUse(ident, pname) 349 pname.used = true 350 pkg := pname.imported 351 352 var exp Object 353 funcMode := value 354 if pkg.cgo { 355 // cgo special cases C.malloc: it's 356 // rewritten to _CMalloc and does not 357 // support two-result calls. 358 if sel == "malloc" { 359 sel = "_CMalloc" 360 } else { 361 funcMode = cgofunc 362 } 363 for _, prefix := range cgoPrefixes { 364 // cgo objects are part of the current package (in file 365 // _cgo_gotypes.go). Use regular lookup. 366 _, exp = check.scope.LookupParent(prefix+sel, check.pos) 367 if exp != nil { 368 break 369 } 370 } 371 if exp == nil { 372 check.errorf(e.Sel, _UndeclaredImportedName, "%s not declared by package C", sel) 373 goto Error 374 } 375 check.objDecl(exp, nil) 376 } else { 377 exp = pkg.scope.Lookup(sel) 378 if exp == nil { 379 if !pkg.fake { 380 check.errorf(e.Sel, _UndeclaredImportedName, "%s not declared by package %s", sel, pkg.name) 381 } 382 goto Error 383 } 384 if !exp.Exported() { 385 check.errorf(e.Sel, _UnexportedName, "%s not exported by package %s", sel, pkg.name) 386 // ok to continue 387 } 388 } 389 check.recordUse(e.Sel, exp) 390 391 // Simplified version of the code for *ast.Idents: 392 // - imported objects are always fully initialized 393 switch exp := exp.(type) { 394 case *Const: 395 assert(exp.Val() != nil) 396 x.mode = constant_ 397 x.typ = exp.typ 398 x.val = exp.val 399 case *TypeName: 400 x.mode = typexpr 401 x.typ = exp.typ 402 case *Var: 403 x.mode = variable 404 x.typ = exp.typ 405 if pkg.cgo && strings.HasPrefix(exp.name, "_Cvar_") { 406 x.typ = x.typ.(*Pointer).base 407 } 408 case *Func: 409 x.mode = funcMode 410 x.typ = exp.typ 411 if pkg.cgo && strings.HasPrefix(exp.name, "_Cmacro_") { 412 x.mode = value 413 x.typ = x.typ.(*Signature).results.vars[0].typ 414 } 415 case *Builtin: 416 x.mode = builtin 417 x.typ = exp.typ 418 x.id = exp.id 419 default: 420 check.dump("unexpected object %v", exp) 421 unreachable() 422 } 423 x.expr = e 424 return 425 } 426 } 427 428 check.exprOrType(x, e.X) 429 if x.mode == invalid { 430 goto Error 431 } 432 433 obj, index, indirect = check.lookupFieldOrMethod(x.typ, x.mode == variable, check.pkg, sel) 434 if obj == nil { 435 switch { 436 case index != nil: 437 // TODO(gri) should provide actual type where the conflict happens 438 check.errorf(e.Sel, _AmbiguousSelector, "ambiguous selector %s.%s", x.expr, sel) 439 case indirect: 440 check.errorf(e.Sel, _InvalidMethodExpr, "cannot call pointer method %s on %s", sel, x.typ) 441 default: 442 // Check if capitalization of sel matters and provide better error 443 // message in that case. 444 if len(sel) > 0 { 445 var changeCase string 446 if r := rune(sel[0]); unicode.IsUpper(r) { 447 changeCase = string(unicode.ToLower(r)) + sel[1:] 448 } else { 449 changeCase = string(unicode.ToUpper(r)) + sel[1:] 450 } 451 if obj, _, _ = check.lookupFieldOrMethod(x.typ, x.mode == variable, check.pkg, changeCase); obj != nil { 452 check.errorf(e.Sel, _MissingFieldOrMethod, "%s.%s undefined (type %s has no field or method %s, but does have %s)", x.expr, sel, x.typ, sel, changeCase) 453 break 454 } 455 } 456 check.errorf(e.Sel, _MissingFieldOrMethod, "%s.%s undefined (type %s has no field or method %s)", x.expr, sel, x.typ, sel) 457 } 458 goto Error 459 } 460 461 // methods may not have a fully set up signature yet 462 if m, _ := obj.(*Func); m != nil { 463 check.objDecl(m, nil) 464 } 465 466 if x.mode == typexpr { 467 // method expression 468 m, _ := obj.(*Func) 469 if m == nil { 470 // TODO(gri) should check if capitalization of sel matters and provide better error message in that case 471 check.errorf(e.Sel, _MissingFieldOrMethod, "%s.%s undefined (type %s has no method %s)", x.expr, sel, x.typ, sel) 472 goto Error 473 } 474 475 check.recordSelection(e, MethodExpr, x.typ, m, index, indirect) 476 477 // the receiver type becomes the type of the first function 478 // argument of the method expression's function type 479 var params []*Var 480 sig := m.typ.(*Signature) 481 if sig.params != nil { 482 params = sig.params.vars 483 } 484 x.mode = value 485 x.typ = &Signature{ 486 params: NewTuple(append([]*Var{NewVar(token.NoPos, check.pkg, "", x.typ)}, params...)...), 487 results: sig.results, 488 variadic: sig.variadic, 489 } 490 491 check.addDeclDep(m) 492 493 } else { 494 // regular selector 495 switch obj := obj.(type) { 496 case *Var: 497 check.recordSelection(e, FieldVal, x.typ, obj, index, indirect) 498 if x.mode == variable || indirect { 499 x.mode = variable 500 } else { 501 x.mode = value 502 } 503 x.typ = obj.typ 504 505 case *Func: 506 // TODO(gri) If we needed to take into account the receiver's 507 // addressability, should we report the type &(x.typ) instead? 508 check.recordSelection(e, MethodVal, x.typ, obj, index, indirect) 509 510 if debug { 511 // Verify that LookupFieldOrMethod and MethodSet.Lookup agree. 512 // TODO(gri) This only works because we call LookupFieldOrMethod 513 // _before_ calling NewMethodSet: LookupFieldOrMethod completes 514 // any incomplete interfaces so they are available to NewMethodSet 515 // (which assumes that interfaces have been completed already). 516 typ := x.typ 517 if x.mode == variable { 518 // If typ is not an (unnamed) pointer or an interface, 519 // use *typ instead, because the method set of *typ 520 // includes the methods of typ. 521 // Variables are addressable, so we can always take their 522 // address. 523 if _, ok := typ.(*Pointer); !ok && !IsInterface(typ) { 524 typ = &Pointer{base: typ} 525 } 526 } 527 // If we created a synthetic pointer type above, we will throw 528 // away the method set computed here after use. 529 // TODO(gri) Method set computation should probably always compute 530 // both, the value and the pointer receiver method set and represent 531 // them in a single structure. 532 // TODO(gri) Consider also using a method set cache for the lifetime 533 // of checker once we rely on MethodSet lookup instead of individual 534 // lookup. 535 mset := NewMethodSet(typ) 536 if m := mset.Lookup(check.pkg, sel); m == nil || m.obj != obj { 537 check.dump("%v: (%s).%v -> %s", e.Pos(), typ, obj.name, m) 538 check.dump("%s\n", mset) 539 // Caution: MethodSets are supposed to be used externally 540 // only (after all interface types were completed). It's 541 // now possible that we get here incorrectly. Not urgent 542 // to fix since we only run this code in debug mode. 543 // TODO(gri) fix this eventually. 544 panic("method sets and lookup don't agree") 545 } 546 } 547 548 x.mode = value 549 550 // remove receiver 551 sig := *obj.typ.(*Signature) 552 sig.recv = nil 553 x.typ = &sig 554 555 check.addDeclDep(obj) 556 557 default: 558 unreachable() 559 } 560 } 561 562 // everything went well 563 x.expr = e 564 return 565 566 Error: 567 x.mode = invalid 568 x.expr = e 569 }