github.com/bir3/gocompiler@v0.3.205/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 "github.com/bir3/gocompiler/src/go/ast" 11 "github.com/bir3/gocompiler/src/go/internal/typeparams" 12 "github.com/bir3/gocompiler/src/go/token" 13 . "github.com/bir3/gocompiler/src/internal/types/errors" 14 "strings" 15 "unicode" 16 ) 17 18 // funcInst type-checks a function instantiation inst and returns the result in x. 19 // The operand x must be the evaluation of inst.X and its type must be a signature. 20 func (check *Checker) funcInst(x *operand, ix *typeparams.IndexExpr) { 21 if !check.allowVersion(check.pkg, 1, 18) { 22 check.softErrorf(inNode(ix.Orig, ix.Lbrack), UnsupportedFeature, "function instantiation requires go1.18 or later") 23 } 24 25 targs := check.typeList(ix.Indices) 26 if targs == nil { 27 x.mode = invalid 28 x.expr = ix.Orig 29 return 30 } 31 assert(len(targs) == len(ix.Indices)) 32 33 // check number of type arguments (got) vs number of type parameters (want) 34 sig := x.typ.(*Signature) 35 got, want := len(targs), sig.TypeParams().Len() 36 if got > want { 37 check.errorf(ix.Indices[got-1], WrongTypeArgCount, "got %d type arguments but want %d", got, want) 38 x.mode = invalid 39 x.expr = ix.Orig 40 return 41 } 42 43 if got < want { 44 targs = check.infer(ix.Orig, sig.TypeParams().list(), targs, nil, nil) 45 if targs == nil { 46 // error was already reported 47 x.mode = invalid 48 x.expr = ix.Orig 49 return 50 } 51 got = len(targs) 52 } 53 assert(got == want) 54 55 // instantiate function signature 56 sig = check.instantiateSignature(x.Pos(), sig, targs, ix.Indices) 57 assert(sig.TypeParams().Len() == 0) // signature is not generic anymore 58 check.recordInstance(ix.Orig, targs, sig) 59 x.typ = sig 60 x.mode = value 61 x.expr = ix.Orig 62 } 63 64 func (check *Checker) instantiateSignature(pos token.Pos, typ *Signature, targs []Type, xlist []ast.Expr) (res *Signature) { 65 assert(check != nil) 66 assert(len(targs) == typ.TypeParams().Len()) 67 68 if trace { 69 check.trace(pos, "-- instantiating signature %s with %s", typ, targs) 70 check.indent++ 71 defer func() { 72 check.indent-- 73 check.trace(pos, "=> %s (under = %s)", res, res.Underlying()) 74 }() 75 } 76 77 inst := check.instance(pos, typ, targs, nil, check.context()).(*Signature) 78 assert(len(xlist) <= len(targs)) 79 80 // verify instantiation lazily (was issue #50450) 81 check.later(func() { 82 tparams := typ.TypeParams().list() 83 if i, err := check.verify(pos, tparams, targs, check.context()); err != nil { 84 // best position for error reporting 85 pos := pos 86 if i < len(xlist) { 87 pos = xlist[i].Pos() 88 } 89 check.softErrorf(atPos(pos), InvalidTypeArg, "%s", err) 90 } else { 91 check.mono.recordInstance(check.pkg, pos, tparams, targs, xlist) 92 } 93 }).describef(atPos(pos), "verify instantiation") 94 95 return inst 96 } 97 98 func (check *Checker) callExpr(x *operand, call *ast.CallExpr) exprKind { 99 ix := typeparams.UnpackIndexExpr(call.Fun) 100 if ix != nil { 101 if check.indexExpr(x, ix) { 102 // Delay function instantiation to argument checking, 103 // where we combine type and value arguments for type 104 // inference. 105 assert(x.mode == value) 106 } else { 107 ix = nil 108 } 109 x.expr = call.Fun 110 check.record(x) 111 } else { 112 check.exprOrType(x, call.Fun, true) 113 } 114 // x.typ may be generic 115 116 switch x.mode { 117 case invalid: 118 check.use(call.Args...) 119 x.expr = call 120 return statement 121 122 case typexpr: 123 // conversion 124 check.nonGeneric(x) 125 if x.mode == invalid { 126 return conversion 127 } 128 T := x.typ 129 x.mode = invalid 130 switch n := len(call.Args); n { 131 case 0: 132 check.errorf(inNode(call, call.Rparen), WrongArgCount, "missing argument in conversion to %s", T) 133 case 1: 134 check.expr(x, call.Args[0]) 135 if x.mode != invalid { 136 if call.Ellipsis.IsValid() { 137 check.errorf(call.Args[0], BadDotDotDotSyntax, "invalid use of ... in conversion to %s", T) 138 break 139 } 140 if t, _ := under(T).(*Interface); t != nil && !isTypeParam(T) { 141 if !t.IsMethodSet() { 142 check.errorf(call, MisplacedConstraintIface, "cannot use interface %s in conversion (contains specific type constraints or is comparable)", T) 143 break 144 } 145 } 146 check.conversion(x, T) 147 } 148 default: 149 check.use(call.Args...) 150 check.errorf(call.Args[n-1], WrongArgCount, "too many arguments in conversion to %s", T) 151 } 152 x.expr = call 153 return conversion 154 155 case builtin: 156 // no need to check for non-genericity here 157 id := x.id 158 if !check.builtin(x, call, id) { 159 x.mode = invalid 160 } 161 x.expr = call 162 // a non-constant result implies a function call 163 if x.mode != invalid && x.mode != constant_ { 164 check.hasCallOrRecv = true 165 } 166 return predeclaredFuncs[id].kind 167 } 168 169 // ordinary function/method call 170 // signature may be generic 171 cgocall := x.mode == cgofunc 172 173 // a type parameter may be "called" if all types have the same signature 174 sig, _ := coreType(x.typ).(*Signature) 175 if sig == nil { 176 check.errorf(x, InvalidCall, invalidOp+"cannot call non-function %s", x) 177 x.mode = invalid 178 x.expr = call 179 return statement 180 } 181 182 // Capture wasGeneric before sig is potentially instantiated below. 183 wasGeneric := sig.TypeParams().Len() > 0 184 185 // evaluate type arguments, if any 186 var xlist []ast.Expr 187 var targs []Type 188 if ix != nil { 189 xlist = ix.Indices 190 targs = check.typeList(xlist) 191 if targs == nil { 192 check.use(call.Args...) 193 x.mode = invalid 194 x.expr = call 195 return statement 196 } 197 assert(len(targs) == len(xlist)) 198 199 // check number of type arguments (got) vs number of type parameters (want) 200 got, want := len(targs), sig.TypeParams().Len() 201 if got > want { 202 check.errorf(xlist[want], WrongTypeArgCount, "got %d type arguments but want %d", got, want) 203 check.use(call.Args...) 204 x.mode = invalid 205 x.expr = call 206 return statement 207 } 208 209 // If sig is generic and all type arguments are provided, preempt function 210 // argument type inference by explicitly instantiating the signature. This 211 // ensures that we record accurate type information for sig, even if there 212 // is an error checking its arguments (for example, if an incorrect number 213 // of arguments is supplied). 214 if got == want && want > 0 { 215 if !check.allowVersion(check.pkg, 1, 18) { 216 check.softErrorf(inNode(call.Fun, ix.Lbrack), UnsupportedFeature, "function instantiation requires go1.18 or later") 217 } 218 219 sig = check.instantiateSignature(ix.Pos(), sig, targs, xlist) 220 assert(sig.TypeParams().Len() == 0) // signature is not generic anymore 221 check.recordInstance(ix.Orig, targs, sig) 222 223 // targs have been consumed; proceed with checking arguments of the 224 // non-generic signature. 225 targs = nil 226 xlist = nil 227 } 228 } 229 230 // evaluate arguments 231 args, _ := check.exprList(call.Args, false) 232 sig = check.arguments(call, sig, targs, args, xlist) 233 234 if wasGeneric && sig.TypeParams().Len() == 0 { 235 // Update the recorded type of call.Fun to its instantiated type. 236 check.recordTypeAndValue(call.Fun, value, sig, nil) 237 } 238 239 // determine result 240 switch sig.results.Len() { 241 case 0: 242 x.mode = novalue 243 case 1: 244 if cgocall { 245 x.mode = commaerr 246 } else { 247 x.mode = value 248 } 249 x.typ = sig.results.vars[0].typ // unpack tuple 250 default: 251 x.mode = value 252 x.typ = sig.results 253 } 254 x.expr = call 255 check.hasCallOrRecv = true 256 257 // if type inference failed, a parametrized result must be invalidated 258 // (operands cannot have a parametrized type) 259 if x.mode == value && sig.TypeParams().Len() > 0 && isParameterized(sig.TypeParams().list(), x.typ) { 260 x.mode = invalid 261 } 262 263 return statement 264 } 265 266 func (check *Checker) exprList(elist []ast.Expr, allowCommaOk bool) (xlist []*operand, commaOk bool) { 267 switch len(elist) { 268 case 0: 269 // nothing to do 270 271 case 1: 272 // single (possibly comma-ok) value, or function returning multiple values 273 e := elist[0] 274 var x operand 275 check.multiExpr(&x, e) 276 if t, ok := x.typ.(*Tuple); ok && x.mode != invalid { 277 // multiple values 278 xlist = make([]*operand, t.Len()) 279 for i, v := range t.vars { 280 xlist[i] = &operand{mode: value, expr: e, typ: v.typ} 281 } 282 break 283 } 284 285 // exactly one (possibly invalid or comma-ok) value 286 xlist = []*operand{&x} 287 if allowCommaOk && (x.mode == mapindex || x.mode == commaok || x.mode == commaerr) { 288 x2 := &operand{mode: value, expr: e, typ: Typ[UntypedBool]} 289 if x.mode == commaerr { 290 x2.typ = universeError 291 } 292 xlist = append(xlist, x2) 293 commaOk = true 294 } 295 296 default: 297 // multiple (possibly invalid) values 298 xlist = make([]*operand, len(elist)) 299 for i, e := range elist { 300 var x operand 301 check.expr(&x, e) 302 xlist[i] = &x 303 } 304 } 305 306 return 307 } 308 309 // xlist is the list of type argument expressions supplied in the source code. 310 func (check *Checker) arguments(call *ast.CallExpr, sig *Signature, targs []Type, args []*operand, xlist []ast.Expr) (rsig *Signature) { 311 rsig = sig 312 313 // TODO(gri) try to eliminate this extra verification loop 314 for _, a := range args { 315 switch a.mode { 316 case typexpr: 317 check.errorf(a, NotAnExpr, "%s used as value", a) 318 return 319 case invalid: 320 return 321 } 322 } 323 324 // Function call argument/parameter count requirements 325 // 326 // | standard call | dotdotdot call | 327 // --------------+------------------+----------------+ 328 // standard func | nargs == npars | invalid | 329 // --------------+------------------+----------------+ 330 // variadic func | nargs >= npars-1 | nargs == npars | 331 // --------------+------------------+----------------+ 332 333 nargs := len(args) 334 npars := sig.params.Len() 335 ddd := call.Ellipsis.IsValid() 336 337 // set up parameters 338 sigParams := sig.params // adjusted for variadic functions (may be nil for empty parameter lists!) 339 adjusted := false // indicates if sigParams is different from t.params 340 if sig.variadic { 341 if ddd { 342 // variadic_func(a, b, c...) 343 if len(call.Args) == 1 && nargs > 1 { 344 // f()... is not permitted if f() is multi-valued 345 check.errorf(inNode(call, call.Ellipsis), InvalidDotDotDot, "cannot use ... with %d-valued %s", nargs, call.Args[0]) 346 return 347 } 348 } else { 349 // variadic_func(a, b, c) 350 if nargs >= npars-1 { 351 // Create custom parameters for arguments: keep 352 // the first npars-1 parameters and add one for 353 // each argument mapping to the ... parameter. 354 vars := make([]*Var, npars-1) // npars > 0 for variadic functions 355 copy(vars, sig.params.vars) 356 last := sig.params.vars[npars-1] 357 typ := last.typ.(*Slice).elem 358 for len(vars) < nargs { 359 vars = append(vars, NewParam(last.pos, last.pkg, last.name, typ)) 360 } 361 sigParams = NewTuple(vars...) // possibly nil! 362 adjusted = true 363 npars = nargs 364 } else { 365 // nargs < npars-1 366 npars-- // for correct error message below 367 } 368 } 369 } else { 370 if ddd { 371 // standard_func(a, b, c...) 372 check.errorf(inNode(call, call.Ellipsis), NonVariadicDotDotDot, "cannot use ... in call to non-variadic %s", call.Fun) 373 return 374 } 375 // standard_func(a, b, c) 376 } 377 378 // check argument count 379 if nargs != npars { 380 var at positioner = call 381 qualifier := "not enough" 382 if nargs > npars { 383 at = args[npars].expr // report at first extra argument 384 qualifier = "too many" 385 } else { 386 at = atPos(call.Rparen) // report at closing ) 387 } 388 // take care of empty parameter lists represented by nil tuples 389 var params []*Var 390 if sig.params != nil { 391 params = sig.params.vars 392 } 393 err := newErrorf(at, WrongArgCount, "%s arguments in call to %s", qualifier, call.Fun) 394 err.errorf(token.NoPos, "have %s", check.typesSummary(operandTypes(args), false)) 395 err.errorf(token.NoPos, "want %s", check.typesSummary(varTypes(params), sig.variadic)) 396 check.report(err) 397 return 398 } 399 400 // infer type arguments and instantiate signature if necessary 401 if sig.TypeParams().Len() > 0 { 402 if !check.allowVersion(check.pkg, 1, 18) { 403 switch call.Fun.(type) { 404 case *ast.IndexExpr, *ast.IndexListExpr: 405 ix := typeparams.UnpackIndexExpr(call.Fun) 406 check.softErrorf(inNode(call.Fun, ix.Lbrack), UnsupportedFeature, "function instantiation requires go1.18 or later") 407 default: 408 check.softErrorf(inNode(call, call.Lparen), UnsupportedFeature, "implicit function instantiation requires go1.18 or later") 409 } 410 } 411 targs := check.infer(call, sig.TypeParams().list(), targs, sigParams, args) 412 if targs == nil { 413 return // error already reported 414 } 415 416 // compute result signature 417 rsig = check.instantiateSignature(call.Pos(), sig, targs, xlist) 418 assert(rsig.TypeParams().Len() == 0) // signature is not generic anymore 419 check.recordInstance(call.Fun, targs, rsig) 420 421 // Optimization: Only if the parameter list was adjusted do we 422 // need to compute it from the adjusted list; otherwise we can 423 // simply use the result signature's parameter list. 424 if adjusted { 425 sigParams = check.subst(call.Pos(), sigParams, makeSubstMap(sig.TypeParams().list(), targs), nil, check.context()).(*Tuple) 426 } else { 427 sigParams = rsig.params 428 } 429 } 430 431 // check arguments 432 if len(args) > 0 { 433 context := check.sprintf("argument to %s", call.Fun) 434 for i, a := range args { 435 check.assignment(a, sigParams.vars[i].typ, context) 436 } 437 } 438 439 return 440 } 441 442 var cgoPrefixes = [...]string{ 443 "_Ciconst_", 444 "_Cfconst_", 445 "_Csconst_", 446 "_Ctype_", 447 "_Cvar_", // actually a pointer to the var 448 "_Cfpvar_fp_", 449 "_Cfunc_", 450 "_Cmacro_", // function to evaluate the expanded expression 451 } 452 453 func (check *Checker) selector(x *operand, e *ast.SelectorExpr, def *Named, wantType bool) { 454 // these must be declared before the "goto Error" statements 455 var ( 456 obj Object 457 index []int 458 indirect bool 459 ) 460 461 sel := e.Sel.Name 462 // If the identifier refers to a package, handle everything here 463 // so we don't need a "package" mode for operands: package names 464 // can only appear in qualified identifiers which are mapped to 465 // selector expressions. 466 if ident, ok := e.X.(*ast.Ident); ok { 467 obj := check.lookup(ident.Name) 468 if pname, _ := obj.(*PkgName); pname != nil { 469 assert(pname.pkg == check.pkg) 470 check.recordUse(ident, pname) 471 pname.used = true 472 pkg := pname.imported 473 474 var exp Object 475 funcMode := value 476 if pkg.cgo { 477 // cgo special cases C.malloc: it's 478 // rewritten to _CMalloc and does not 479 // support two-result calls. 480 if sel == "malloc" { 481 sel = "_CMalloc" 482 } else { 483 funcMode = cgofunc 484 } 485 for _, prefix := range cgoPrefixes { 486 // cgo objects are part of the current package (in file 487 // _cgo_gotypes.go). Use regular lookup. 488 _, exp = check.scope.LookupParent(prefix+sel, check.pos) 489 if exp != nil { 490 break 491 } 492 } 493 if exp == nil { 494 check.errorf(e.Sel, UndeclaredImportedName, "undefined: %s", ast.Expr(e)) // cast to ast.Expr to silence vet 495 goto Error 496 } 497 check.objDecl(exp, nil) 498 } else { 499 exp = pkg.scope.Lookup(sel) 500 if exp == nil { 501 if !pkg.fake { 502 check.errorf(e.Sel, UndeclaredImportedName, "undefined: %s", ast.Expr(e)) 503 } 504 goto Error 505 } 506 if !exp.Exported() { 507 check.errorf(e.Sel, UnexportedName, "%s not exported by package %s", sel, pkg.name) 508 // ok to continue 509 } 510 } 511 check.recordUse(e.Sel, exp) 512 513 // Simplified version of the code for *ast.Idents: 514 // - imported objects are always fully initialized 515 switch exp := exp.(type) { 516 case *Const: 517 assert(exp.Val() != nil) 518 x.mode = constant_ 519 x.typ = exp.typ 520 x.val = exp.val 521 case *TypeName: 522 x.mode = typexpr 523 x.typ = exp.typ 524 case *Var: 525 x.mode = variable 526 x.typ = exp.typ 527 if pkg.cgo && strings.HasPrefix(exp.name, "_Cvar_") { 528 x.typ = x.typ.(*Pointer).base 529 } 530 case *Func: 531 x.mode = funcMode 532 x.typ = exp.typ 533 if pkg.cgo && strings.HasPrefix(exp.name, "_Cmacro_") { 534 x.mode = value 535 x.typ = x.typ.(*Signature).results.vars[0].typ 536 } 537 case *Builtin: 538 x.mode = builtin 539 x.typ = exp.typ 540 x.id = exp.id 541 default: 542 check.dump("%v: unexpected object %v", e.Sel.Pos(), exp) 543 unreachable() 544 } 545 x.expr = e 546 return 547 } 548 } 549 550 check.exprOrType(x, e.X, false) 551 switch x.mode { 552 case typexpr: 553 // don't crash for "type T T.x" (was issue #51509) 554 if def != nil && x.typ == def { 555 check.cycleError([]Object{def.obj}) 556 goto Error 557 } 558 case builtin: 559 // types2 uses the position of '.' for the error 560 check.errorf(e.Sel, UncalledBuiltin, "cannot select on %s", x) 561 goto Error 562 case invalid: 563 goto Error 564 } 565 566 // Avoid crashing when checking an invalid selector in a method declaration 567 // (i.e., where def is not set): 568 // 569 // type S[T any] struct{} 570 // type V = S[any] 571 // func (fs *S[T]) M(x V.M) {} 572 // 573 // All codepaths below return a non-type expression. If we get here while 574 // expecting a type expression, it is an error. 575 // 576 // See issue #57522 for more details. 577 // 578 // TODO(rfindley): We should do better by refusing to check selectors in all cases where 579 // x.typ is incomplete. 580 if wantType { 581 check.errorf(e.Sel, NotAType, "%s is not a type", ast.Expr(e)) 582 goto Error 583 } 584 585 obj, index, indirect = LookupFieldOrMethod(x.typ, x.mode == variable, check.pkg, sel) 586 if obj == nil { 587 // Don't report another error if the underlying type was invalid (issue #49541). 588 if under(x.typ) == Typ[Invalid] { 589 goto Error 590 } 591 592 if index != nil { 593 // TODO(gri) should provide actual type where the conflict happens 594 check.errorf(e.Sel, AmbiguousSelector, "ambiguous selector %s.%s", x.expr, sel) 595 goto Error 596 } 597 598 if indirect { 599 if x.mode == typexpr { 600 check.errorf(e.Sel, InvalidMethodExpr, "invalid method expression %s.%s (needs pointer receiver (*%s).%s)", x.typ, sel, x.typ, sel) 601 } else { 602 check.errorf(e.Sel, InvalidMethodExpr, "cannot call pointer method %s on %s", sel, x.typ) 603 } 604 goto Error 605 } 606 607 var why string 608 if isInterfacePtr(x.typ) { 609 why = check.interfacePtrError(x.typ) 610 } else { 611 why = check.sprintf("type %s has no field or method %s", x.typ, sel) 612 // Check if capitalization of sel matters and provide better error message in that case. 613 // TODO(gri) This code only looks at the first character but LookupFieldOrMethod should 614 // have an (internal) mechanism for case-insensitive lookup that we should use 615 // instead (see types2). 616 if len(sel) > 0 { 617 var changeCase string 618 if r := rune(sel[0]); unicode.IsUpper(r) { 619 changeCase = string(unicode.ToLower(r)) + sel[1:] 620 } else { 621 changeCase = string(unicode.ToUpper(r)) + sel[1:] 622 } 623 if obj, _, _ = LookupFieldOrMethod(x.typ, x.mode == variable, check.pkg, changeCase); obj != nil { 624 why += ", but does have " + changeCase 625 } 626 } 627 } 628 check.errorf(e.Sel, MissingFieldOrMethod, "%s.%s undefined (%s)", x.expr, sel, why) 629 goto Error 630 } 631 632 // methods may not have a fully set up signature yet 633 if m, _ := obj.(*Func); m != nil { 634 check.objDecl(m, nil) 635 } 636 637 if x.mode == typexpr { 638 // method expression 639 m, _ := obj.(*Func) 640 if m == nil { 641 // TODO(gri) should check if capitalization of sel matters and provide better error message in that case 642 check.errorf(e.Sel, MissingFieldOrMethod, "%s.%s undefined (type %s has no method %s)", x.expr, sel, x.typ, sel) 643 goto Error 644 } 645 646 check.recordSelection(e, MethodExpr, x.typ, m, index, indirect) 647 648 sig := m.typ.(*Signature) 649 if sig.recv == nil { 650 check.error(e, InvalidDeclCycle, "illegal cycle in method declaration") 651 goto Error 652 } 653 654 // the receiver type becomes the type of the first function 655 // argument of the method expression's function type 656 var params []*Var 657 if sig.params != nil { 658 params = sig.params.vars 659 } 660 // Be consistent about named/unnamed parameters. This is not needed 661 // for type-checking, but the newly constructed signature may appear 662 // in an error message and then have mixed named/unnamed parameters. 663 // (An alternative would be to not print parameter names in errors, 664 // but it's useful to see them; this is cheap and method expressions 665 // are rare.) 666 name := "" 667 if len(params) > 0 && params[0].name != "" { 668 // name needed 669 name = sig.recv.name 670 if name == "" { 671 name = "_" 672 } 673 } 674 params = append([]*Var{NewVar(sig.recv.pos, sig.recv.pkg, name, x.typ)}, params...) 675 x.mode = value 676 x.typ = &Signature{ 677 tparams: sig.tparams, 678 params: NewTuple(params...), 679 results: sig.results, 680 variadic: sig.variadic, 681 } 682 683 check.addDeclDep(m) 684 685 } else { 686 // regular selector 687 switch obj := obj.(type) { 688 case *Var: 689 check.recordSelection(e, FieldVal, x.typ, obj, index, indirect) 690 if x.mode == variable || indirect { 691 x.mode = variable 692 } else { 693 x.mode = value 694 } 695 x.typ = obj.typ 696 697 case *Func: 698 // TODO(gri) If we needed to take into account the receiver's 699 // addressability, should we report the type &(x.typ) instead? 700 check.recordSelection(e, MethodVal, x.typ, obj, index, indirect) 701 702 // TODO(gri) The verification pass below is disabled for now because 703 // method sets don't match method lookup in some cases. 704 // For instance, if we made a copy above when creating a 705 // custom method for a parameterized received type, the 706 // method set method doesn't match (no copy there). There 707 /// may be other situations. 708 disabled := true 709 if !disabled && debug { 710 // Verify that LookupFieldOrMethod and MethodSet.Lookup agree. 711 // TODO(gri) This only works because we call LookupFieldOrMethod 712 // _before_ calling NewMethodSet: LookupFieldOrMethod completes 713 // any incomplete interfaces so they are available to NewMethodSet 714 // (which assumes that interfaces have been completed already). 715 typ := x.typ 716 if x.mode == variable { 717 // If typ is not an (unnamed) pointer or an interface, 718 // use *typ instead, because the method set of *typ 719 // includes the methods of typ. 720 // Variables are addressable, so we can always take their 721 // address. 722 if _, ok := typ.(*Pointer); !ok && !IsInterface(typ) { 723 typ = &Pointer{base: typ} 724 } 725 } 726 // If we created a synthetic pointer type above, we will throw 727 // away the method set computed here after use. 728 // TODO(gri) Method set computation should probably always compute 729 // both, the value and the pointer receiver method set and represent 730 // them in a single structure. 731 // TODO(gri) Consider also using a method set cache for the lifetime 732 // of checker once we rely on MethodSet lookup instead of individual 733 // lookup. 734 mset := NewMethodSet(typ) 735 if m := mset.Lookup(check.pkg, sel); m == nil || m.obj != obj { 736 check.dump("%v: (%s).%v -> %s", e.Pos(), typ, obj.name, m) 737 check.dump("%s\n", mset) 738 // Caution: MethodSets are supposed to be used externally 739 // only (after all interface types were completed). It's 740 // now possible that we get here incorrectly. Not urgent 741 // to fix since we only run this code in debug mode. 742 // TODO(gri) fix this eventually. 743 panic("method sets and lookup don't agree") 744 } 745 } 746 747 x.mode = value 748 749 // remove receiver 750 sig := *obj.typ.(*Signature) 751 sig.recv = nil 752 x.typ = &sig 753 754 check.addDeclDep(obj) 755 756 default: 757 unreachable() 758 } 759 } 760 761 // everything went well 762 x.expr = e 763 return 764 765 Error: 766 x.mode = invalid 767 x.expr = e 768 } 769 770 // use type-checks each argument. 771 // Useful to make sure expressions are evaluated 772 // (and variables are "used") in the presence of other errors. 773 // The arguments may be nil. 774 func (check *Checker) use(arg ...ast.Expr) { 775 var x operand 776 for _, e := range arg { 777 // The nil check below is necessary since certain AST fields 778 // may legally be nil (e.g., the ast.SliceExpr.High field). 779 if e != nil { 780 check.rawExpr(&x, e, nil, false) 781 } 782 } 783 } 784 785 // useLHS is like use, but doesn't "use" top-level identifiers. 786 // It should be called instead of use if the arguments are 787 // expressions on the lhs of an assignment. 788 // The arguments must not be nil. 789 func (check *Checker) useLHS(arg ...ast.Expr) { 790 var x operand 791 for _, e := range arg { 792 // If the lhs is an identifier denoting a variable v, this assignment 793 // is not a 'use' of v. Remember current value of v.used and restore 794 // after evaluating the lhs via check.rawExpr. 795 var v *Var 796 var v_used bool 797 if ident, _ := unparen(e).(*ast.Ident); ident != nil { 798 // never type-check the blank name on the lhs 799 if ident.Name == "_" { 800 continue 801 } 802 if _, obj := check.scope.LookupParent(ident.Name, token.NoPos); obj != nil { 803 // It's ok to mark non-local variables, but ignore variables 804 // from other packages to avoid potential race conditions with 805 // dot-imported variables. 806 if w, _ := obj.(*Var); w != nil && w.pkg == check.pkg { 807 v = w 808 v_used = v.used 809 } 810 } 811 } 812 check.rawExpr(&x, e, nil, false) 813 if v != nil { 814 v.used = v_used // restore v.used 815 } 816 } 817 }