1// Copyright 2013 The Go Authors. All rights reserved.2// Use of this source code is governed by a BSD-style3// license that can be found in the LICENSE file.45// This file implements typechecking of call and selector expressions.67package types89import (10 "go/ast"11 "go/token"12 . "internal/types/errors"13 "strings"14)1516// funcInst type-checks a function instantiation.17// The incoming x must be a generic function.18// If ix != nil, it provides some or all of the type arguments (ix.Indices).19// If target != nil, it may be used to infer missing type arguments of x, if any.20// At least one of T or ix must be provided.21//22// There are two modes of operation:23//24// 1. If infer == true, funcInst infers missing type arguments as needed and25// instantiates the function x. The returned results are nil.26//27// 2. If infer == false and inst provides all type arguments, funcInst28// instantiates the function x. The returned results are nil.29// If inst doesn't provide enough type arguments, funcInst returns the30// available arguments; x remains unchanged.31//32// If an error (other than a version error) occurs in any case, it is reported33// and x.mode is set to invalid.34func (check *Checker) funcInst(T *target, pos token.Pos, x *operand, ix *indexedExpr, infer bool) []Type {35 assert(T != nil || ix != nil)3637 var instErrPos positioner38 if ix != nil {39 instErrPos = inNode(ix.orig, ix.lbrack)40 x.expr = ix.orig // if we don't have an index expression, keep the existing expression of x41 } else {42 instErrPos = atPos(pos)43 }44 versionErr := !check.verifyVersionf(instErrPos, go1_18, "function instantiation")4546 // targs and xlist are the type arguments and corresponding type expressions, or nil.47 var targs []Type48 var xlist []ast.Expr49 if ix != nil {50 xlist = ix.indices51 targs = check.typeList(xlist)52 if targs == nil {53 x.invalidate()54 return nil55 }56 assert(len(targs) == len(xlist))57 }5859 // Check the number of type arguments (got) vs number of type parameters (want).60 // Note that x is a function value, not a type expression, so we don't need to61 // call Underlying below.62 sig := x.typ().(*Signature)63 got, want := len(targs), sig.TypeParams().Len()64 if got > want {65 // Providing too many type arguments is always an error.66 check.errorf(ix.indices[got-1], WrongTypeArgCount, "got %d type arguments but want %d", got, want)67 x.invalidate()68 return nil69 }7071 if got < want {72 if !infer {73 return targs74 }7576 // If the uninstantiated or partially instantiated function x is used in77 // an assignment (tsig != nil), infer missing type arguments by treating78 // the assignment79 //80 // var tvar tsig = x81 //82 // like a call g(tvar) of the synthetic generic function g83 //84 // func g[type_parameters_of_x](func_type_of_x)85 //86 var args []*operand87 var params []*Var88 var reverse bool89 if T != nil && sig.tparams != nil {90 if !versionErr && !check.allowVersion(go1_21) {91 if ix != nil {92 check.versionErrorf(instErrPos, go1_21, "partially instantiated function in assignment")93 } else {94 check.versionErrorf(instErrPos, go1_21, "implicitly instantiated function in assignment")95 }96 }97 gsig := NewSignatureType(nil, nil, nil, sig.params, sig.results, sig.variadic)98 params = []*Var{NewParam(x.Pos(), check.pkg, "", gsig)}99 // The type of the argument operand is tsig, which is the type of the LHS in an assignment100 // or the result type in a return statement. Create a pseudo-expression for that operand101 // that makes sense when reported in error messages from infer, below.102 expr := ast.NewIdent(T.desc)103 expr.NamePos = x.Pos() // correct position104 args = []*operand{{mode_: value, expr: expr, typ_: T.sig}}105 reverse = true106 }107108 // Rename type parameters to avoid problems with recursive instantiations.109 // Note that NewTuple(params...) below is (*Tuple)(nil) if len(params) == 0, as desired.110 tparams, params2 := check.renameTParams(pos, sig.TypeParams().list(), NewTuple(params...))111112 err := check.newError(CannotInferTypeArgs)113 targs = check.infer(atPos(pos), tparams, targs, params2.(*Tuple), args, reverse, err)114 if targs == nil {115 if !err.empty() {116 err.report()117 }118 x.invalidate()119 return nil120 }121 got = len(targs)122 }123 assert(got == want)124125 // instantiate function signature126 sig = check.instantiateSignature(x.Pos(), x.expr, sig, targs, xlist)127 x.typ_ = sig128 x.mode_ = value129 return nil130}131132func (check *Checker) instantiateSignature(pos token.Pos, expr ast.Expr, typ *Signature, targs []Type, xlist []ast.Expr) (res *Signature) {133 assert(check != nil)134 assert(len(targs) == typ.TypeParams().Len())135136 if check.conf._Trace {137 check.trace(pos, "-- instantiating signature %s with %s", typ, targs)138 check.indent++139 defer func() {140 check.indent--141 check.trace(pos, "=> %s (under = %s)", res, res.Underlying())142 }()143 }144145 // For signatures, Checker.instance will always succeed because the type argument146 // count is correct at this point (see assertion above); hence the type assertion147 // to *Signature will always succeed.148 inst := check.instance(pos, typ, targs, nil, check.context()).(*Signature)149 assert(inst.TypeParams().Len() == 0) // signature is not generic anymore150 check.recordInstance(expr, targs, inst)151 assert(len(xlist) <= len(targs))152153 // verify instantiation lazily (was go.dev/issue/50450)154 check.later(func() {155 tparams := typ.TypeParams().list()156 // check type constraints157 if i, err := check.verify(pos, tparams, targs, check.context()); err != nil {158 // best position for error reporting159 pos := pos160 if i < len(xlist) {161 pos = xlist[i].Pos()162 }163 check.softErrorf(atPos(pos), InvalidTypeArg, "%s", err)164 } else {165 check.mono.recordInstance(check.pkg, pos, tparams, targs, xlist)166 }167 }).describef(atPos(pos), "verify instantiation")168169 return inst170}171172func (check *Checker) callExpr(x *operand, call *ast.CallExpr) exprKind {173 ix := unpackIndexedExpr(call.Fun)174 if ix != nil {175 if check.indexExpr(x, ix) {176 // Delay function instantiation to argument checking,177 // where we combine type and value arguments for type178 // inference.179 assert(x.mode() == value)180 } else {181 ix = nil182 }183 x.expr = call.Fun184 check.record(x)185 } else {186 check.exprOrType(x, call.Fun, true)187 }188 // x.typ may be generic189190 switch x.mode() {191 case invalid:192 check.use(call.Args...)193 x.expr = call194 return statement195196 case typexpr:197 // conversion198 check.nonGeneric(nil, x)199 if !x.isValid() {200 return conversion201 }202 T := x.typ()203 x.invalidate()204 // We cannot convert a value to an incomplete type; make sure it's complete.205 if !check.isComplete(T) {206 x.expr = call207 return conversion208 }209 switch n := len(call.Args); n {210 case 0:211 check.errorf(inNode(call, call.Rparen), WrongArgCount, "missing argument in conversion to %s", T)212 case 1:213 check.expr(newTarget(T, "conversion"), T, x, call.Args[0])214 if x.isValid() {215 if hasDots(call) {216 check.errorf(call.Args[0], BadDotDotDotSyntax, "invalid use of ... in conversion to %s", T)217 break218 }219 if t, _ := T.Underlying().(*Interface); t != nil && !isTypeParam(T) {220 if !t.IsMethodSet() {221 check.errorf(call, MisplacedConstraintIface, "cannot use interface %s in conversion (contains specific type constraints or is comparable)", T)222 break223 }224 }225 check.conversion(x, T)226 }227 default:228 check.use(call.Args...)229 check.errorf(call.Args[n-1], WrongArgCount, "too many arguments in conversion to %s", T)230 }231 x.expr = call232 return conversion233234 case builtin:235 // no need to check for non-genericity here236 id := x.id237 if !check.builtin(x, call, id) {238 x.invalidate()239 }240 x.expr = call241 // a non-constant result implies a function call242 if x.isValid() && x.mode() != constant_ {243 check.hasCallOrRecv = true244 }245 return predeclaredFuncs[id].kind246 }247248 // ordinary function/method call249 // signature may be generic250 cgocall := x.mode() == cgofunc251252 // If the operand type is a type parameter, all types in its type set253 // must have a common underlying type, which must be a signature.254 u, err := commonUnder(x.typ(), func(t, u Type) *typeError {255 if _, ok := u.(*Signature); u != nil && !ok {256 return typeErrorf("%s is not a function", t)257 }258 return nil259 })260 if err != nil {261 check.errorf(x, InvalidCall, invalidOp+"cannot call %s: %s", x, err.format(check))262 x.invalidate()263 x.expr = call264 return statement265 }266 sig := u.(*Signature) // u must be a signature per the commonUnder condition267268 // Capture wasGeneric before sig is potentially instantiated below.269 wasGeneric := sig.TypeParams().Len() > 0270271 // evaluate type arguments, if any272 var xlist []ast.Expr273 var targs []Type274 if ix != nil {275 xlist = ix.indices276 targs = check.typeList(xlist)277 if targs == nil {278 check.use(call.Args...)279 x.invalidate()280 x.expr = call281 return statement282 }283 assert(len(targs) == len(xlist))284285 // check number of type arguments (got) vs number of type parameters (want)286 got, want := len(targs), sig.TypeParams().Len()287 if got > want {288 check.errorf(xlist[want], WrongTypeArgCount, "got %d type arguments but want %d", got, want)289 check.use(call.Args...)290 x.invalidate()291 x.expr = call292 return statement293 }294295 // If sig is generic and all type arguments are provided, preempt function296 // argument type inference by explicitly instantiating the signature. This297 // ensures that we record accurate type information for sig, even if there298 // is an error checking its arguments (for example, if an incorrect number299 // of arguments is supplied).300 if got == want && want > 0 {301 check.verifyVersionf(atPos(ix.lbrack), go1_18, "function instantiation")302 sig = check.instantiateSignature(ix.Pos(), ix.orig, sig, targs, xlist)303 // targs have been consumed; proceed with checking arguments of the304 // non-generic signature.305 targs = nil306 xlist = nil307 }308 }309310 // evaluate arguments311 args, atargs := check.genericExprList(sig.argType, call.Args)312 sig = check.arguments(call, sig, targs, xlist, args, atargs)313314 if wasGeneric && sig.TypeParams().Len() == 0 {315 // Update the recorded type of call.Fun to its instantiated type.316 check.recordTypeAndValue(call.Fun, value, sig, nil)317 }318319 // determine result320 switch sig.results.Len() {321 case 0:322 x.mode_ = novalue323 case 1:324 if cgocall {325 x.mode_ = commaerr326 } else {327 x.mode_ = value328 }329 typ := sig.results.vars[0].typ // unpack tuple330 // We cannot return a value of an incomplete type; make sure it's complete.331 if !check.isComplete(typ) {332 x.invalidate()333 x.expr = call334 return statement335 }336 x.typ_ = typ337 default:338 x.mode_ = value339 x.typ_ = sig.results340 }341 x.expr = call342 check.hasCallOrRecv = true343344 // if type inference failed, a parameterized result must be invalidated345 // (operands cannot have a parameterized type)346 if x.mode() == value && sig.TypeParams().Len() > 0 && isParameterized(sig.TypeParams().list(), x.typ()) {347 x.invalidate()348 }349350 return statement351}352353// exprList evaluates a list of expressions and returns the corresponding operands.354// A single-element expression list may evaluate to multiple operands.355func (check *Checker) exprList(elist []ast.Expr) (xlist []*operand) {356 if n := len(elist); n == 1 {357 xlist, _ = check.multiExpr(elist[0], false)358 } else if n > 1 {359 // multiple (possibly invalid) values360 xlist = make([]*operand, n)361 for i, e := range elist {362 var x operand363 check.expr(nil, nil, &x, e)364 xlist[i] = &x365 }366 }367 return368}369370// genericExprList is like exprList but result operands may be uninstantiated or partially371// instantiated generic functions (where constraint information is insufficient to infer372// the missing type arguments) for Go 1.21 and later. Additionally, typeAt must return the373// corresponding target type for each operand, or nil if none exists.374// For each non-generic or uninstantiated generic operand, the corresponding targsList and375// elements do not exist (targsList is nil) or the elements are nil.376// For each partially instantiated generic function operand, the corresponding377// targsList elements are the operand's partial type arguments.378func (check *Checker) genericExprList(typeAt func(int) Type, elist []ast.Expr) (resList []*operand, targsList [][]Type) {379 if debug {380 defer func() {381 // type arguments must only exist for partially instantiated functions382 for i, x := range resList {383 if i < len(targsList) {384 if n := len(targsList[i]); n > 0 {385 // x must be a partially instantiated function386 assert(n < x.typ().(*Signature).TypeParams().Len())387 }388 }389 }390 }()391 }392393 // Before Go 1.21, uninstantiated or partially instantiated argument functions are394 // not permitted. Checker.funcInst must infer missing type arguments in that case.395 infer := true // for -lang < go1.21396 n := len(elist)397 if n > 0 && check.allowVersion(go1_21) {398 infer = false399 }400401 if n == 1 {402 // single value (possibly a partially instantiated function), or a multi-valued expression403 e := elist[0]404 var x operand405 if ix := unpackIndexedExpr(e); ix != nil && check.indexExpr(&x, ix) {406 // x is a generic function.407 targs := check.funcInst(nil, x.Pos(), &x, ix, infer)408 if targs != nil {409 // x was not instantiated: collect the (partial) type arguments.410 targsList = [][]Type{targs}411 // Update x.expr so that we can record the partially instantiated function.412 x.expr = ix.orig413 } else {414 // x was instantiated: we must record it here because we didn't415 // use the usual expression evaluators.416 check.record(&x)417 }418 resList = []*operand{&x}419 } else {420 // x is not a function instantiation (it may still be a generic function).421 check.rawExpr(nil, typeAt(0), &x, e, nil, true)422 check.exclude(&x, 1<<novalue|1<<builtin|1<<typexpr)423 if t, ok := x.typ().(*Tuple); ok && x.isValid() {424 // x is a function call returning multiple values; it cannot be generic.425 resList = make([]*operand, t.Len())426 for i, v := range t.vars {427 resList[i] = &operand{mode_: value, expr: e, typ_: v.typ}428 }429 } else {430 // x is exactly one value (possibly invalid or uninstantiated generic function).431 resList = []*operand{&x}432 }433 }434 } else if n > 1 {435 // multiple values436 resList = make([]*operand, n)437 targsList = make([][]Type, n)438 for i, e := range elist {439 var x operand440 if ix := unpackIndexedExpr(e); ix != nil && check.indexExpr(&x, ix) {441 // x is a generic function.442 targs := check.funcInst(nil, x.Pos(), &x, ix, infer)443 if targs != nil {444 // x was not instantiated: collect the (partial) type arguments.445 targsList[i] = targs446 // Update x.expr so that we can record the partially instantiated function.447 x.expr = ix.orig448 } else {449 // x was instantiated: we must record it here because we didn't450 // use the usual expression evaluators.451 check.record(&x)452 }453 } else {454 // x is exactly one value (possibly invalid or uninstantiated generic function).455 check.genericExpr(typeAt(i), &x, e, nil)456 }457 resList[i] = &x458 }459 }460461 return462}463464// arguments type-checks arguments passed to a function call with the given signature.465// The function and its arguments may be generic, and possibly partially instantiated.466// targs and xlist are the function's type arguments (and corresponding expressions).467// args are the function arguments. If an argument args[i] is a partially instantiated468// generic function, atargs[i] are the corresponding type arguments.469// If the callee is variadic, arguments adjusts its signature to match the provided470// arguments. The type parameters and arguments of the callee and all its arguments471// are used together to infer any missing type arguments, and the callee and argument472// functions are instantiated as necessary.473// The result signature is the (possibly adjusted and instantiated) function signature.474// If an error occurred, the result signature is the incoming sig.475func (check *Checker) arguments(call *ast.CallExpr, sig *Signature, targs []Type, xlist []ast.Expr, args []*operand, atargs [][]Type) (rsig *Signature) {476 rsig = sig477478 // Function call argument/parameter count requirements479 //480 // | standard call | dotdotdot call |481 // --------------+------------------+----------------+482 // standard func | nargs == npars | invalid |483 // --------------+------------------+----------------+484 // variadic func | nargs >= npars-1 | nargs == npars |485 // --------------+------------------+----------------+486487 nargs := len(args)488 npars := sig.params.Len()489 ddd := hasDots(call)490491 // set up parameters492 sigParams := sig.params // adjusted for variadic functions (may be nil for empty parameter lists!)493 adjusted := false // indicates if sigParams is different from sig.params494 if sig.variadic {495 if ddd {496 // variadic_func(a, b, c...)497 if len(call.Args) == 1 && nargs > 1 {498 // f()... is not permitted if f() is multi-valued499 check.errorf(inNode(call, call.Ellipsis), InvalidDotDotDot, "cannot use ... with %d-valued %s", nargs, call.Args[0])500 return501 }502 } else {503 // variadic_func(a, b, c)504 if nargs >= npars-1 {505 // Create custom parameters for arguments: keep506 // the first npars-1 parameters and add one for507 // each argument mapping to the ... parameter.508 vars := make([]*Var, npars-1) // npars > 0 for variadic functions509 copy(vars, sig.params.vars)510 last := sig.params.vars[npars-1]511 typ := last.typ.(*Slice).elem512 for len(vars) < nargs {513 vars = append(vars, NewParam(last.pos, last.pkg, last.name, typ))514 }515 sigParams = NewTuple(vars...) // possibly nil!516 adjusted = true517 npars = nargs518 } else {519 // nargs < npars-1520 npars-- // for correct error message below521 }522 }523 } else {524 if ddd {525 // standard_func(a, b, c...)526 check.errorf(inNode(call, call.Ellipsis), NonVariadicDotDotDot, "cannot use ... in call to non-variadic %s", call.Fun)527 return528 }529 // standard_func(a, b, c)530 }531532 // check argument count533 if nargs != npars {534 var at positioner = call535 qualifier := "not enough"536 if nargs > npars {537 at = args[npars].expr // report at first extra argument538 qualifier = "too many"539 } else {540 at = atPos(call.Rparen) // report at closing )541 }542 // take care of empty parameter lists represented by nil tuples543 var params []*Var544 if sig.params != nil {545 params = sig.params.vars546 }547 err := check.newError(WrongArgCount)548 err.addf(at, "%s arguments in call to %s", qualifier, call.Fun)549 err.addf(noposn, "have %s", check.typesSummary(operandTypes(args), false, ddd))550 err.addf(noposn, "want %s", check.typesSummary(varTypes(params), sig.variadic, false))551 err.report()552 return553 }554555 // collect type parameters of callee and generic function arguments556 var tparams []*TypeParam557558 // collect type parameters of callee559 n := sig.TypeParams().Len()560 if n > 0 {561 if !check.allowVersion(go1_18) {562 switch call.Fun.(type) {563 case *ast.IndexExpr, *ast.IndexListExpr:564 ix := unpackIndexedExpr(call.Fun)565 check.versionErrorf(inNode(call.Fun, ix.lbrack), go1_18, "function instantiation")566 default:567 check.versionErrorf(inNode(call, call.Lparen), go1_18, "implicit function instantiation")568 }569 }570 // rename type parameters to avoid problems with recursive calls571 var tmp Type572 tparams, tmp = check.renameTParams(call.Pos(), sig.TypeParams().list(), sigParams)573 sigParams = tmp.(*Tuple)574 // make sure targs and tparams have the same length575 for len(targs) < len(tparams) {576 targs = append(targs, nil)577 }578 }579 assert(len(tparams) == len(targs))580581 // collect type parameters from generic function arguments582 var genericArgs []int // indices of generic function arguments583 if enableReverseTypeInference {584 for i, arg := range args {585 // generic arguments cannot have a defined (*Named) type - no need for underlying type below586 if asig, _ := arg.typ().(*Signature); asig != nil && asig.TypeParams().Len() > 0 {587 // The argument type is a generic function signature. This type is588 // pointer-identical with (it's copied from) the type of the generic589 // function argument and thus the function object.590 // Before we change the type (type parameter renaming, below), make591 // a clone of it as otherwise we implicitly modify the object's type592 // (go.dev/issues/63260).593 asig = clone(asig)594 // Rename type parameters for cases like f(g, g); this gives each595 // generic function argument a unique type identity (go.dev/issues/59956).596 // TODO(gri) Consider only doing this if a function argument appears597 // multiple times, which is rare (possible optimization).598 atparams, tmp := check.renameTParams(call.Pos(), asig.TypeParams().list(), asig)599 asig = tmp.(*Signature)600 asig.tparams = &TypeParamList{atparams} // renameTParams doesn't touch associated type parameters601 arg.typ_ = asig // new type identity for the function argument602 tparams = append(tparams, atparams...)603 // add partial list of type arguments, if any604 if i < len(atargs) {605 targs = append(targs, atargs[i]...)606 }607 // make sure targs and tparams have the same length608 for len(targs) < len(tparams) {609 targs = append(targs, nil)610 }611 genericArgs = append(genericArgs, i)612 }613 }614 }615 assert(len(tparams) == len(targs))616617 // at the moment we only support implicit instantiations of argument functions618 _ = len(genericArgs) > 0 && check.verifyVersionf(args[genericArgs[0]], go1_21, "implicitly instantiated function as argument")619620 // tparams holds the type parameters of the callee and generic function arguments, if any:621 // the first n type parameters belong to the callee, followed by mi type parameters for each622 // of the generic function arguments, where mi = args[i].typ.(*Signature).TypeParams().Len().623624 // infer missing type arguments of callee and function arguments625 if len(tparams) > 0 {626 err := check.newError(CannotInferTypeArgs)627 targs = check.infer(call, tparams, targs, sigParams, args, false, err)628 if targs == nil {629 // TODO(gri) If infer inferred the first targs[:n], consider instantiating630 // the call signature for better error messages/gopls behavior.631 // Perhaps instantiate as much as we can, also for arguments.632 // This will require changes to how infer returns its results.633 if !err.empty() {634 check.errorf(err.posn(), CannotInferTypeArgs, "in call to %s, %s", call.Fun, err.msg())635 }636 return637 }638639 // update result signature: instantiate if needed640 if n > 0 {641 rsig = check.instantiateSignature(call.Pos(), call.Fun, sig, targs[:n], xlist)642 // If the callee's parameter list was adjusted we need to update (instantiate)643 // it separately. Otherwise we can simply use the result signature's parameter644 // list.645 if adjusted {646 sigParams = check.subst(call.Pos(), sigParams, makeSubstMap(tparams[:n], targs[:n]), nil, check.context()).(*Tuple)647 } else {648 sigParams = rsig.params649 }650 }651652 // compute argument signatures: instantiate if needed653 j := n654 for _, i := range genericArgs {655 arg := args[i]656 asig := arg.typ().(*Signature)657 k := j + asig.TypeParams().Len()658 // targs[j:k] are the inferred type arguments for asig659 arg.typ_ = check.instantiateSignature(call.Pos(), arg.expr, asig, targs[j:k], nil) // TODO(gri) provide xlist if possible (partial instantiations)660 check.record(arg) // record here because we didn't use the usual expr evaluators661 j = k662 }663 }664665 // check arguments666 if len(args) > 0 {667 context := check.sprintf("argument to %s", call.Fun)668 for i, a := range args {669 check.assignment(a, sigParams.vars[i].typ, context)670 }671 }672673 return674}675676var cgoPrefixes = [...]string{677 "_Ciconst_",678 "_Cfconst_",679 "_Csconst_",680 "_Ctype_",681 "_Cvar_", // actually a pointer to the var682 "_Cfpvar_fp_",683 "_Cfunc_",684 "_Cmacro_", // function to evaluate the expanded expression685}686687func (check *Checker) selector(x *operand, e *ast.SelectorExpr, wantType bool) {688 // these must be declared before the "goto Error" statements689 var (690 obj Object691 index []int692 indirect bool693 )694695 sel := e.Sel.Name696 // If the identifier refers to a package, handle everything here697 // so we don't need a "package" mode for operands: package names698 // can only appear in qualified identifiers which are mapped to699 // selector expressions.700 if ident, ok := e.X.(*ast.Ident); ok {701 obj := check.lookup(ident.Name)702 if pname, _ := obj.(*PkgName); pname != nil {703 assert(pname.pkg == check.pkg)704 check.recordUse(ident, pname)705 check.usedPkgNames[pname] = true706 pkg := pname.imported707708 var exp Object709 funcMode := value710 if pkg.cgo {711 // cgo special cases C.malloc: it's712 // rewritten to _CMalloc and does not713 // support two-result calls.714 if sel == "malloc" {715 sel = "_CMalloc"716 } else {717 funcMode = cgofunc718 }719 for _, prefix := range cgoPrefixes {720 // cgo objects are part of the current package (in file721 // _cgo_gotypes.go). Use regular lookup.722 exp = check.lookup(prefix + sel)723 if exp != nil {724 break725 }726 }727 if exp == nil {728 if isValidName(sel) {729 check.errorf(e.Sel, UndeclaredImportedName, "undefined: %s", ast.Expr(e)) // cast to ast.Expr to silence vet730 }731 goto Error732 }733 check.objDecl(exp)734 } else {735 exp = pkg.scope.Lookup(sel)736 if exp == nil {737 if !pkg.fake && isValidName(sel) {738 // Try to give a better error message when selector matches an object name ignoring case.739 exps := pkg.scope.lookupIgnoringCase(sel, true)740 if len(exps) >= 1 {741 // report just the first one742 check.errorf(e.Sel, UndeclaredImportedName, "undefined: %s (but have %s)", ast.Expr(e), exps[0].Name())743 } else {744 check.errorf(e.Sel, UndeclaredImportedName, "undefined: %s", ast.Expr(e))745 }746 }747 goto Error748 }749 if !exp.Exported() {750 check.errorf(e.Sel, UnexportedName, "name %s not exported by package %s", sel, pkg.name)751 // ok to continue752 }753 }754 check.recordUse(e.Sel, exp)755756 // Simplified version of the code for *ast.Idents:757 // - imported objects are always fully initialized758 switch exp := exp.(type) {759 case *Const:760 assert(exp.Val() != nil)761 x.mode_ = constant_762 x.typ_ = exp.typ763 x.val = exp.val764 case *TypeName:765 x.mode_ = typexpr766 x.typ_ = exp.typ767 case *Var:768 x.mode_ = variable769 x.typ_ = exp.typ770 if pkg.cgo && strings.HasPrefix(exp.name, "_Cvar_") {771 x.typ_ = x.typ().(*Pointer).base772 }773 case *Func:774 x.mode_ = funcMode775 x.typ_ = exp.typ776 if pkg.cgo && strings.HasPrefix(exp.name, "_Cmacro_") {777 x.mode_ = value778 x.typ_ = x.typ().(*Signature).results.vars[0].typ779 }780 case *Builtin:781 x.mode_ = builtin782 x.typ_ = exp.typ783 x.id = exp.id784 default:785 check.dump("%v: unexpected object %v", e.Sel.Pos(), exp)786 panic("unreachable")787 }788 x.expr = e789 return790 }791 }792793 check.exprOrType(x, e.X, false)794 switch x.mode() {795 case builtin:796 // types2 uses the position of '.' for the error797 check.errorf(e.Sel, UncalledBuiltin, "invalid use of %s in selector expression", x)798 goto Error799 case invalid:800 goto Error801 }802803 // We cannot select on an incomplete type; make sure it's complete.804 if !check.isComplete(x.typ()) {805 goto Error806 }807808 // Avoid crashing when checking an invalid selector in a method declaration.809 //810 // type S[T any] struct{}811 // type V = S[any]812 // func (fs *S[T]) M(x V.M) {}813 //814 // All codepaths below return a non-type expression. If we get here while815 // expecting a type expression, it is an error.816 //817 // See go.dev/issue/57522 for more details.818 if wantType {819 check.errorf(e.Sel, NotAType, "%s is not a type", ast.Expr(e))820 goto Error821 }822823 // Additionally, if x.typ is a pointer type, selecting implicitly dereferences the value, meaning824 // its base type must also be complete.825 if p, ok := x.typ().Underlying().(*Pointer); ok && !check.isComplete(p.base) {826 goto Error827 }828829 obj, index, indirect = lookupFieldOrMethod(x.typ(), x.mode() == variable, check.pkg, sel, false)830 if obj == nil {831 // Don't report another error if the underlying type was invalid (go.dev/issue/49541).832 if !isValid(x.typ().Underlying()) {833 goto Error834 }835836 if index != nil {837 // TODO(gri) should provide actual type where the conflict happens838 check.errorf(e.Sel, AmbiguousSelector, "ambiguous selector %s.%s", x.expr, sel)839 goto Error840 }841842 if indirect {843 if x.mode() == typexpr {844 check.errorf(e.Sel, InvalidMethodExpr, "invalid method expression %s.%s (needs pointer receiver (*%s).%s)", x.typ(), sel, x.typ(), sel)845 } else {846 check.errorf(e.Sel, InvalidMethodExpr, "cannot call pointer method %s on %s", sel, x.typ())847 }848 goto Error849 }850851 var why string852 if isInterfacePtr(x.typ()) {853 why = check.interfacePtrError(x.typ())854 } else {855 alt, _, _ := lookupFieldOrMethod(x.typ(), x.mode() == variable, check.pkg, sel, true)856 why = check.lookupError(x.typ(), sel, alt, false)857 }858 check.errorf(e.Sel, MissingFieldOrMethod, "%s.%s undefined (%s)", x.expr, sel, why)859 goto Error860 }861 // obj != nil862863 switch obj := obj.(type) {864 case *Var:865 if x.mode() == typexpr {866 check.errorf(e.X, MissingFieldOrMethod, "operand for field selector %s must be value of type %s", sel, x.typ())867 goto Error868 }869870 // field value871 check.recordSelection(e, FieldVal, x.typ(), obj, index, indirect)872 if x.mode() == variable || indirect {873 x.mode_ = variable874 } else {875 x.mode_ = value876 }877 x.typ_ = obj.typ878879 case *Func:880 check.objDecl(obj) // ensure fully set-up signature881 check.addDeclDep(obj)882 // TODO(mark): Assert that sig.rparams is nil here?883884 if x.mode() == typexpr {885 // method expression886 check.recordSelection(e, MethodExpr, x.typ(), obj, index, indirect)887888 sig := obj.typ.(*Signature)889 if sig.recv == nil {890 check.error(e, InvalidDeclCycle, "illegal cycle in method declaration")891 goto Error892 }893894 // The receiver type becomes the type of the first function895 // argument of the method expression's function type.896 var params []*Var897 if sig.params != nil {898 params = sig.params.vars899 }900 // Be consistent about named/unnamed parameters. This is not needed901 // for type-checking, but the newly constructed signature may appear902 // in an error message and then have mixed named/unnamed parameters.903 // (An alternative would be to not print parameter names in errors,904 // but it's useful to see them; this is cheap and method expressions905 // are rare.)906 name := ""907 if len(params) > 0 && params[0].name != "" {908 // name needed909 name = sig.recv.name910 if name == "" {911 name = "_"912 }913 }914 params = append([]*Var{NewParam(sig.recv.pos, sig.recv.pkg, name, x.typ())}, params...)915 x.mode_ = value916 x.typ_ = &Signature{917 tparams: sig.tparams,918 recvold: methodExprSentinel,919 params: NewTuple(params...),920 results: sig.results,921 variadic: sig.variadic,922 }923 } else {924 // method value925926 // TODO(gri) If we needed to take into account the receiver's927 // addressability, should we report the type &(x.typ) instead?928 check.recordSelection(e, MethodVal, x.typ(), obj, index, indirect)929930 // TODO(gri) The verification pass below is disabled for now because931 // method sets don't match method lookup in some cases.932 // For instance, if we made a copy above when creating a933 // custom method for a parameterized received type, the934 // method set method doesn't match (no copy there). There935 /// may be other situations.936 disabled := true937 if !disabled && debug {938 // Verify that LookupFieldOrMethod and MethodSet.Lookup agree.939 // TODO(gri) This only works because we call LookupFieldOrMethod940 // _before_ calling NewMethodSet: LookupFieldOrMethod completes941 // any incomplete interfaces so they are available to NewMethodSet942 // (which assumes that interfaces have been completed already).943 typ := x.typ_944 if x.mode() == variable {945 // If typ is not an (unnamed) pointer or an interface,946 // use *typ instead, because the method set of *typ947 // includes the methods of typ.948 // Variables are addressable, so we can always take their949 // address.950 if _, ok := typ.(*Pointer); !ok && !IsInterface(typ) {951 typ = &Pointer{base: typ}952 }953 }954 // If we created a synthetic pointer type above, we will throw955 // away the method set computed here after use.956 // TODO(gri) Method set computation should probably always compute957 // both, the value and the pointer receiver method set and represent958 // them in a single structure.959 // TODO(gri) Consider also using a method set cache for the lifetime960 // of checker once we rely on MethodSet lookup instead of individual961 // lookup.962 mset := NewMethodSet(typ)963 if m := mset.Lookup(check.pkg, sel); m == nil || m.obj != obj {964 check.dump("%v: (%s).%v -> %s", e.Pos(), typ, obj.name, m)965 check.dump("%s\n", mset)966 // Caution: MethodSets are supposed to be used externally967 // only (after all interface types were completed). It's968 // now possible that we get here incorrectly. Not urgent969 // to fix since we only run this code in debug mode.970 // TODO(gri) fix this eventually.971 panic("method sets and lookup don't agree")972 }973 }974975 x.mode_ = value976977 // remove/stash receiver978 sig := *obj.typ.(*Signature)979 sig.recvold = sig.recv980 sig.recv = nil981 x.typ_ = &sig982 }983984 default:985 panic("unreachable")986 }987988 // everything went well989 x.expr = e990 return991992Error:993 x.invalidate()994 x.typ_ = Typ[Invalid]995 x.expr = e996}997998// use type-checks each argument.999// Useful to make sure expressions are evaluated1000// (and variables are "used") in the presence of1001// other errors. Arguments may be nil.1002// Reports if all arguments evaluated without error.1003func (check *Checker) use(args ...ast.Expr) bool { return check.useN(args, false) }10041005// useLHS is like use, but doesn't "use" top-level identifiers.1006// It should be called instead of use if the arguments are1007// expressions on the lhs of an assignment.1008func (check *Checker) useLHS(args ...ast.Expr) bool { return check.useN(args, true) }10091010func (check *Checker) useN(args []ast.Expr, lhs bool) bool {1011 ok := true1012 for _, e := range args {1013 if !check.use1(e, lhs) {1014 ok = false1015 }1016 }1017 return ok1018}10191020func (check *Checker) use1(e ast.Expr, lhs bool) bool {1021 var x operand1022 x.mode_ = value // anything but invalid1023 switch n := ast.Unparen(e).(type) {1024 case nil:1025 // nothing to do1026 case *ast.Ident:1027 // don't report an error evaluating blank1028 if n.Name == "_" {1029 break1030 }1031 // If the lhs is an identifier denoting a variable v, this assignment1032 // is not a 'use' of v. Remember current value of v.used and restore1033 // after evaluating the lhs via check.rawExpr.1034 var v *Var1035 var v_used bool1036 if lhs {1037 if obj := check.lookup(n.Name); obj != nil {1038 // It's ok to mark non-local variables, but ignore variables1039 // from other packages to avoid potential race conditions with1040 // dot-imported variables.1041 if w, _ := obj.(*Var); w != nil && w.pkg == check.pkg {1042 v = w1043 v_used = check.usedVars[v]1044 }1045 }1046 }1047 check.exprOrType(&x, n, true)1048 if v != nil {1049 check.usedVars[v] = v_used // restore v.used1050 }1051 default:1052 check.rawExpr(nil, nil, &x, e, nil, true)1053 }1054 return x.isValid()1055}
Findings
✓ No findings reported for this file.