// Copyright 2013 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

// This file implements typechecking of call and selector expressions.

package types

import (
	
	
	
	. 
	
)

// funcInst type-checks a function instantiation.
// The incoming x must be a generic function.
// If ix != nil, it provides some or all of the type arguments (ix.Indices).
// If target != nil, it may be used to infer missing type arguments of x, if any.
// At least one of T or ix must be provided.
//
// There are two modes of operation:
//
//  1. If infer == true, funcInst infers missing type arguments as needed and
//     instantiates the function x. The returned results are nil.
//
//  2. If infer == false and inst provides all type arguments, funcInst
//     instantiates the function x. The returned results are nil.
//     If inst doesn't provide enough type arguments, funcInst returns the
//     available arguments and the corresponding expression list; x remains
//     unchanged.
//
// If an error (other than a version error) occurs in any case, it is reported
// and x.mode is set to invalid.
func ( *Checker) ( *target,  token.Pos,  *operand,  *typeparams.IndexExpr,  bool) ([]Type, []ast.Expr) {
	assert( != nil ||  != nil)

	var  positioner
	if  != nil {
		 = inNode(.Orig, .Lbrack)
		.expr = .Orig // if we don't have an index expression, keep the existing expression of x
	} else {
		 = atPos()
	}
	 := !.verifyVersionf(, go1_18, "function instantiation")

	// targs and xlist are the type arguments and corresponding type expressions, or nil.
	var  []Type
	var  []ast.Expr
	if  != nil {
		 = .Indices
		 = .typeList()
		if  == nil {
			.mode = invalid
			return nil, nil
		}
		assert(len() == len())
	}

	// Check the number of type arguments (got) vs number of type parameters (want).
	// Note that x is a function value, not a type expression, so we don't need to
	// call under below.
	 := .typ.(*Signature)
	,  := len(), .TypeParams().Len()
	if  >  {
		// Providing too many type arguments is always an error.
		.errorf(.Indices[-1], WrongTypeArgCount, "got %d type arguments but want %d", , )
		.mode = invalid
		return nil, nil
	}

	if  <  {
		if ! {
			return , 
		}

		// If the uninstantiated or partially instantiated function x is used in
		// an assignment (tsig != nil), infer missing type arguments by treating
		// the assignment
		//
		//    var tvar tsig = x
		//
		// like a call g(tvar) of the synthetic generic function g
		//
		//    func g[type_parameters_of_x](func_type_of_x)
		//
		var  []*operand
		var  []*Var
		var  bool
		if  != nil && .tparams != nil {
			if ! && !.allowVersion(, go1_21) {
				if  != nil {
					.versionErrorf(, go1_21, "partially instantiated function in assignment")
				} else {
					.versionErrorf(, go1_21, "implicitly instantiated function in assignment")
				}
			}
			 := NewSignatureType(nil, nil, nil, .params, .results, .variadic)
			 = []*Var{NewVar(.Pos(), .pkg, "", )}
			// The type of the argument operand is tsig, which is the type of the LHS in an assignment
			// or the result type in a return statement. Create a pseudo-expression for that operand
			// that makes sense when reported in error messages from infer, below.
			 := ast.NewIdent(.desc)
			.NamePos = .Pos() // correct position
			 = []*operand{{mode: value, expr: , typ: .sig}}
			 = true
		}

		// Rename type parameters to avoid problems with recursive instantiations.
		// Note that NewTuple(params...) below is (*Tuple)(nil) if len(params) == 0, as desired.
		,  := .renameTParams(, .TypeParams().list(), NewTuple(...))

		 := .newError(CannotInferTypeArgs)
		 = .infer(atPos(), , , .(*Tuple), , , )
		if  == nil {
			if !.empty() {
				.report()
			}
			.mode = invalid
			return nil, nil
		}
		 = len()
	}
	assert( == )

	// instantiate function signature
	 = .instantiateSignature(.Pos(), .expr, , , )
	.typ = 
	.mode = value
	return nil, nil
}

func ( *Checker) ( token.Pos,  ast.Expr,  *Signature,  []Type,  []ast.Expr) ( *Signature) {
	assert( != nil)
	assert(len() == .TypeParams().Len())

	if .conf._Trace {
		.trace(, "-- instantiating signature %s with %s", , )
		.indent++
		defer func() {
			.indent--
			.trace(, "=> %s (under = %s)", , .Underlying())
		}()
	}

	 := .instance(, , , nil, .context()).(*Signature)
	assert(.TypeParams().Len() == 0) // signature is not generic anymore
	.recordInstance(, , )
	assert(len() <= len())

	// verify instantiation lazily (was go.dev/issue/50450)
	.later(func() {
		 := .TypeParams().list()
		if ,  := .verify(, , , .context());  != nil {
			// best position for error reporting
			 := 
			if  < len() {
				 = [].Pos()
			}
			.softErrorf(atPos(), InvalidTypeArg, "%s", )
		} else {
			.mono.recordInstance(.pkg, , , , )
		}
	}).describef(atPos(), "verify instantiation")

	return 
}

func ( *Checker) ( *operand,  *ast.CallExpr) exprKind {
	 := typeparams.UnpackIndexExpr(.Fun)
	if  != nil {
		if .indexExpr(, ) {
			// Delay function instantiation to argument checking,
			// where we combine type and value arguments for type
			// inference.
			assert(.mode == value)
		} else {
			 = nil
		}
		.expr = .Fun
		.record()
	} else {
		.exprOrType(, .Fun, true)
	}
	// x.typ may be generic

	switch .mode {
	case invalid:
		.use(.Args...)
		.expr = 
		return statement

	case typexpr:
		// conversion
		.nonGeneric(nil, )
		if .mode == invalid {
			return conversion
		}
		 := .typ
		.mode = invalid
		switch  := len(.Args);  {
		case 0:
			.errorf(inNode(, .Rparen), WrongArgCount, "missing argument in conversion to %s", )
		case 1:
			.expr(nil, , .Args[0])
			if .mode != invalid {
				if hasDots() {
					.errorf(.Args[0], BadDotDotDotSyntax, "invalid use of ... in conversion to %s", )
					break
				}
				if ,  := under().(*Interface);  != nil && !isTypeParam() {
					if !.IsMethodSet() {
						.errorf(, MisplacedConstraintIface, "cannot use interface %s in conversion (contains specific type constraints or is comparable)", )
						break
					}
				}
				.conversion(, )
			}
		default:
			.use(.Args...)
			.errorf(.Args[-1], WrongArgCount, "too many arguments in conversion to %s", )
		}
		.expr = 
		return conversion

	case builtin:
		// no need to check for non-genericity here
		 := .id
		if !.builtin(, , ) {
			.mode = invalid
		}
		.expr = 
		// a non-constant result implies a function call
		if .mode != invalid && .mode != constant_ {
			.hasCallOrRecv = true
		}
		return predeclaredFuncs[].kind
	}

	// ordinary function/method call
	// signature may be generic
	 := .mode == cgofunc

	// a type parameter may be "called" if all types have the same signature
	,  := coreType(.typ).(*Signature)
	if  == nil {
		.errorf(, InvalidCall, invalidOp+"cannot call non-function %s", )
		.mode = invalid
		.expr = 
		return statement
	}

	// Capture wasGeneric before sig is potentially instantiated below.
	 := .TypeParams().Len() > 0

	// evaluate type arguments, if any
	var  []ast.Expr
	var  []Type
	if  != nil {
		 = .Indices
		 = .typeList()
		if  == nil {
			.use(.Args...)
			.mode = invalid
			.expr = 
			return statement
		}
		assert(len() == len())

		// check number of type arguments (got) vs number of type parameters (want)
		,  := len(), .TypeParams().Len()
		if  >  {
			.errorf([], WrongTypeArgCount, "got %d type arguments but want %d", , )
			.use(.Args...)
			.mode = invalid
			.expr = 
			return statement
		}

		// If sig is generic and all type arguments are provided, preempt function
		// argument type inference by explicitly instantiating the signature. This
		// ensures that we record accurate type information for sig, even if there
		// is an error checking its arguments (for example, if an incorrect number
		// of arguments is supplied).
		if  ==  &&  > 0 {
			.verifyVersionf(atPos(.Lbrack), go1_18, "function instantiation")
			 = .instantiateSignature(.Pos(), .Orig, , , )
			// targs have been consumed; proceed with checking arguments of the
			// non-generic signature.
			 = nil
			 = nil
		}
	}

	// evaluate arguments
	, ,  := .genericExprList(.Args)
	 = .arguments(, , , , , , )

	if  && .TypeParams().Len() == 0 {
		// Update the recorded type of call.Fun to its instantiated type.
		.recordTypeAndValue(.Fun, value, , nil)
	}

	// determine result
	switch .results.Len() {
	case 0:
		.mode = novalue
	case 1:
		if  {
			.mode = commaerr
		} else {
			.mode = value
		}
		.typ = .results.vars[0].typ // unpack tuple
	default:
		.mode = value
		.typ = .results
	}
	.expr = 
	.hasCallOrRecv = true

	// if type inference failed, a parameterized result must be invalidated
	// (operands cannot have a parameterized type)
	if .mode == value && .TypeParams().Len() > 0 && isParameterized(.TypeParams().list(), .typ) {
		.mode = invalid
	}

	return statement
}

// exprList evaluates a list of expressions and returns the corresponding operands.
// A single-element expression list may evaluate to multiple operands.
func ( *Checker) ( []ast.Expr) ( []*operand) {
	if  := len();  == 1 {
		, _ = .multiExpr([0], false)
	} else if  > 1 {
		// multiple (possibly invalid) values
		 = make([]*operand, )
		for ,  := range  {
			var  operand
			.expr(nil, &, )
			[] = &
		}
	}
	return
}

// genericExprList is like exprList but result operands may be uninstantiated or partially
// instantiated generic functions (where constraint information is insufficient to infer
// the missing type arguments) for Go 1.21 and later.
// For each non-generic or uninstantiated generic operand, the corresponding targsList and
// xlistList elements do not exist (targsList and xlistList are nil) or the elements are nil.
// For each partially instantiated generic function operand, the corresponding targsList and
// xlistList elements are the operand's partial type arguments and type expression lists.
func ( *Checker) ( []ast.Expr) ( []*operand,  [][]Type,  [][]ast.Expr) {
	if debug {
		defer func() {
			// targsList and xlistList must have matching lengths
			assert(len() == len())
			// type arguments must only exist for partially instantiated functions
			for ,  := range  {
				if  < len() {
					if  := len([]);  > 0 {
						// x must be a partially instantiated function
						assert( < .typ.(*Signature).TypeParams().Len())
					}
				}
			}
		}()
	}

	// Before Go 1.21, uninstantiated or partially instantiated argument functions are
	// nor permitted. Checker.funcInst must infer missing type arguments in that case.
	 := true // for -lang < go1.21
	 := len()
	if  > 0 && .allowVersion([0], go1_21) {
		 = false
	}

	if  == 1 {
		// single value (possibly a partially instantiated function), or a multi-valued expression
		 := [0]
		var  operand
		if  := typeparams.UnpackIndexExpr();  != nil && .indexExpr(&, ) {
			// x is a generic function.
			,  := .funcInst(nil, .Pos(), &, , )
			if  != nil {
				// x was not instantiated: collect the (partial) type arguments.
				 = [][]Type{}
				 = [][]ast.Expr{}
				// Update x.expr so that we can record the partially instantiated function.
				.expr = .Orig
			} else {
				// x was instantiated: we must record it here because we didn't
				// use the usual expression evaluators.
				.record(&)
			}
			 = []*operand{&}
		} else {
			// x is not a function instantiation (it may still be a generic function).
			.rawExpr(nil, &, , nil, true)
			.exclude(&, 1<<novalue|1<<builtin|1<<typexpr)
			if ,  := .typ.(*Tuple);  && .mode != invalid {
				// x is a function call returning multiple values; it cannot be generic.
				 = make([]*operand, .Len())
				for ,  := range .vars {
					[] = &operand{mode: value, expr: , typ: .typ}
				}
			} else {
				// x is exactly one value (possibly invalid or uninstantiated generic function).
				 = []*operand{&}
			}
		}
	} else if  > 1 {
		// multiple values
		 = make([]*operand, )
		 = make([][]Type, )
		 = make([][]ast.Expr, )
		for ,  := range  {
			var  operand
			if  := typeparams.UnpackIndexExpr();  != nil && .indexExpr(&, ) {
				// x is a generic function.
				,  := .funcInst(nil, .Pos(), &, , )
				if  != nil {
					// x was not instantiated: collect the (partial) type arguments.
					[] = 
					[] = 
					// Update x.expr so that we can record the partially instantiated function.
					.expr = .Orig
				} else {
					// x was instantiated: we must record it here because we didn't
					// use the usual expression evaluators.
					.record(&)
				}
			} else {
				// x is exactly one value (possibly invalid or uninstantiated generic function).
				.genericExpr(&, )
			}
			[] = &
		}
	}

	return
}

// arguments type-checks arguments passed to a function call with the given signature.
// The function and its arguments may be generic, and possibly partially instantiated.
// targs and xlist are the function's type arguments (and corresponding expressions).
// args are the function arguments. If an argument args[i] is a partially instantiated
// generic function, atargs[i] and atxlist[i] are the corresponding type arguments
// (and corresponding expressions).
// If the callee is variadic, arguments adjusts its signature to match the provided
// arguments. The type parameters and arguments of the callee and all its arguments
// are used together to infer any missing type arguments, and the callee and argument
// functions are instantiated as necessary.
// The result signature is the (possibly adjusted and instantiated) function signature.
// If an error occurred, the result signature is the incoming sig.
func ( *Checker) ( *ast.CallExpr,  *Signature,  []Type,  []ast.Expr,  []*operand,  [][]Type,  [][]ast.Expr) ( *Signature) {
	 = 

	// Function call argument/parameter count requirements
	//
	//               | standard call    | dotdotdot call |
	// --------------+------------------+----------------+
	// standard func | nargs == npars   | invalid        |
	// --------------+------------------+----------------+
	// variadic func | nargs >= npars-1 | nargs == npars |
	// --------------+------------------+----------------+

	 := len()
	 := .params.Len()
	 := hasDots()

	// set up parameters
	 := .params // adjusted for variadic functions (may be nil for empty parameter lists!)
	 := false       // indicates if sigParams is different from sig.params
	if .variadic {
		if  {
			// variadic_func(a, b, c...)
			if len(.Args) == 1 &&  > 1 {
				// f()... is not permitted if f() is multi-valued
				.errorf(inNode(, .Ellipsis), InvalidDotDotDot, "cannot use ... with %d-valued %s", , .Args[0])
				return
			}
		} else {
			// variadic_func(a, b, c)
			if  >= -1 {
				// Create custom parameters for arguments: keep
				// the first npars-1 parameters and add one for
				// each argument mapping to the ... parameter.
				 := make([]*Var, -1) // npars > 0 for variadic functions
				copy(, .params.vars)
				 := .params.vars[-1]
				 := .typ.(*Slice).elem
				for len() <  {
					 = append(, NewParam(.pos, .pkg, .name, ))
				}
				 = NewTuple(...) // possibly nil!
				 = true
				 = 
			} else {
				// nargs < npars-1
				-- // for correct error message below
			}
		}
	} else {
		if  {
			// standard_func(a, b, c...)
			.errorf(inNode(, .Ellipsis), NonVariadicDotDotDot, "cannot use ... in call to non-variadic %s", .Fun)
			return
		}
		// standard_func(a, b, c)
	}

	// check argument count
	if  !=  {
		var  positioner = 
		 := "not enough"
		if  >  {
			 = [].expr // report at first extra argument
			 = "too many"
		} else {
			 = atPos(.Rparen) // report at closing )
		}
		// take care of empty parameter lists represented by nil tuples
		var  []*Var
		if .params != nil {
			 = .params.vars
		}
		 := .newError(WrongArgCount)
		.addf(, "%s arguments in call to %s", , .Fun)
		.addf(noposn, "have %s", .typesSummary(operandTypes(), false))
		.addf(noposn, "want %s", .typesSummary(varTypes(), .variadic))
		.report()
		return
	}

	// collect type parameters of callee and generic function arguments
	var  []*TypeParam

	// collect type parameters of callee
	 := .TypeParams().Len()
	if  > 0 {
		if !.allowVersion(, go1_18) {
			switch .Fun.(type) {
			case *ast.IndexExpr, *ast.IndexListExpr:
				 := typeparams.UnpackIndexExpr(.Fun)
				.versionErrorf(inNode(.Fun, .Lbrack), go1_18, "function instantiation")
			default:
				.versionErrorf(inNode(, .Lparen), go1_18, "implicit function instantiation")
			}
		}
		// rename type parameters to avoid problems with recursive calls
		var  Type
		,  = .renameTParams(.Pos(), .TypeParams().list(), )
		 = .(*Tuple)
		// make sure targs and tparams have the same length
		for len() < len() {
			 = append(, nil)
		}
	}
	assert(len() == len())

	// collect type parameters from generic function arguments
	var  []int // indices of generic function arguments
	if enableReverseTypeInference {
		for ,  := range  {
			// generic arguments cannot have a defined (*Named) type - no need for underlying type below
			if ,  := .typ.(*Signature);  != nil && .TypeParams().Len() > 0 {
				// The argument type is a generic function signature. This type is
				// pointer-identical with (it's copied from) the type of the generic
				// function argument and thus the function object.
				// Before we change the type (type parameter renaming, below), make
				// a clone of it as otherwise we implicitly modify the object's type
				// (go.dev/issues/63260).
				 = clone()
				// Rename type parameters for cases like f(g, g); this gives each
				// generic function argument a unique type identity (go.dev/issues/59956).
				// TODO(gri) Consider only doing this if a function argument appears
				//           multiple times, which is rare (possible optimization).
				,  := .renameTParams(.Pos(), .TypeParams().list(), )
				 = .(*Signature)
				.tparams = &TypeParamList{} // renameTParams doesn't touch associated type parameters
				.typ =                           // new type identity for the function argument
				 = append(, ...)
				// add partial list of type arguments, if any
				if  < len() {
					 = append(, []...)
				}
				// make sure targs and tparams have the same length
				for len() < len() {
					 = append(, nil)
				}
				 = append(, )
			}
		}
	}
	assert(len() == len())

	// at the moment we only support implicit instantiations of argument functions
	_ = len() > 0 && .verifyVersionf([[0]], go1_21, "implicitly instantiated function as argument")

	// tparams holds the type parameters of the callee and generic function arguments, if any:
	// the first n type parameters belong to the callee, followed by mi type parameters for each
	// of the generic function arguments, where mi = args[i].typ.(*Signature).TypeParams().Len().

	// infer missing type arguments of callee and function arguments
	if len() > 0 {
		 := .newError(CannotInferTypeArgs)
		 = .infer(, , , , , false, )
		if  == nil {
			// TODO(gri) If infer inferred the first targs[:n], consider instantiating
			//           the call signature for better error messages/gopls behavior.
			//           Perhaps instantiate as much as we can, also for arguments.
			//           This will require changes to how infer returns its results.
			if !.empty() {
				.errorf(.posn(), CannotInferTypeArgs, "in call to %s, %s", .Fun, .msg())
			}
			return
		}

		// update result signature: instantiate if needed
		if  > 0 {
			 = .instantiateSignature(.Pos(), .Fun, , [:], )
			// If the callee's parameter list was adjusted we need to update (instantiate)
			// it separately. Otherwise we can simply use the result signature's parameter
			// list.
			if  {
				 = .subst(.Pos(), , makeSubstMap([:], [:]), nil, .context()).(*Tuple)
			} else {
				 = .params
			}
		}

		// compute argument signatures: instantiate if needed
		 := 
		for ,  := range  {
			 := []
			 := .typ.(*Signature)
			 :=  + .TypeParams().Len()
			// targs[j:k] are the inferred type arguments for asig
			.typ = .instantiateSignature(.Pos(), .expr, , [:], nil) // TODO(gri) provide xlist if possible (partial instantiations)
			.record()                                                                 // record here because we didn't use the usual expr evaluators
			 = 
		}
	}

	// check arguments
	if len() > 0 {
		 := .sprintf("argument to %s", .Fun)
		for ,  := range  {
			.assignment(, .vars[].typ, )
		}
	}

	return
}

var cgoPrefixes = [...]string{
	"_Ciconst_",
	"_Cfconst_",
	"_Csconst_",
	"_Ctype_",
	"_Cvar_", // actually a pointer to the var
	"_Cfpvar_fp_",
	"_Cfunc_",
	"_Cmacro_", // function to evaluate the expanded expression
}

func ( *Checker) ( *operand,  *ast.SelectorExpr,  *TypeName,  bool) {
	// these must be declared before the "goto Error" statements
	var (
		      Object
		    []int
		 bool
	)

	 := .Sel.Name
	// If the identifier refers to a package, handle everything here
	// so we don't need a "package" mode for operands: package names
	// can only appear in qualified identifiers which are mapped to
	// selector expressions.
	if ,  := .X.(*ast.Ident);  {
		 := .lookup(.Name)
		if ,  := .(*PkgName);  != nil {
			assert(.pkg == .pkg)
			.recordUse(, )
			.used = true
			 := .imported

			var  Object
			 := value
			if .cgo {
				// cgo special cases C.malloc: it's
				// rewritten to _CMalloc and does not
				// support two-result calls.
				if  == "malloc" {
					 = "_CMalloc"
				} else {
					 = cgofunc
				}
				for ,  := range cgoPrefixes {
					// cgo objects are part of the current package (in file
					// _cgo_gotypes.go). Use regular lookup.
					_,  = .scope.LookupParent(+, .pos)
					if  != nil {
						break
					}
				}
				if  == nil {
					.errorf(.Sel, UndeclaredImportedName, "undefined: %s", ast.Expr()) // cast to ast.Expr to silence vet
					goto 
				}
				.objDecl(, nil)
			} else {
				 = .scope.Lookup()
				if  == nil {
					if !.fake {
						.errorf(.Sel, UndeclaredImportedName, "undefined: %s", ast.Expr())
					}
					goto 
				}
				if !.Exported() {
					.errorf(.Sel, UnexportedName, "name %s not exported by package %s", , .name)
					// ok to continue
				}
			}
			.recordUse(.Sel, )

			// Simplified version of the code for *ast.Idents:
			// - imported objects are always fully initialized
			switch exp := .(type) {
			case *Const:
				assert(.Val() != nil)
				.mode = constant_
				.typ = .typ
				.val = .val
			case *TypeName:
				.mode = typexpr
				.typ = .typ
			case *Var:
				.mode = variable
				.typ = .typ
				if .cgo && strings.HasPrefix(.name, "_Cvar_") {
					.typ = .typ.(*Pointer).base
				}
			case *Func:
				.mode = 
				.typ = .typ
				if .cgo && strings.HasPrefix(.name, "_Cmacro_") {
					.mode = value
					.typ = .typ.(*Signature).results.vars[0].typ
				}
			case *Builtin:
				.mode = builtin
				.typ = .typ
				.id = .id
			default:
				.dump("%v: unexpected object %v", .Sel.Pos(), )
				panic("unreachable")
			}
			.expr = 
			return
		}
	}

	.exprOrType(, .X, false)
	switch .mode {
	case typexpr:
		// don't crash for "type T T.x" (was go.dev/issue/51509)
		if  != nil && .typ == .typ {
			.cycleError([]Object{}, 0)
			goto 
		}
	case builtin:
		// types2 uses the position of '.' for the error
		.errorf(.Sel, UncalledBuiltin, "cannot select on %s", )
		goto 
	case invalid:
		goto 
	}

	// Avoid crashing when checking an invalid selector in a method declaration
	// (i.e., where def is not set):
	//
	//   type S[T any] struct{}
	//   type V = S[any]
	//   func (fs *S[T]) M(x V.M) {}
	//
	// All codepaths below return a non-type expression. If we get here while
	// expecting a type expression, it is an error.
	//
	// See go.dev/issue/57522 for more details.
	//
	// TODO(rfindley): We should do better by refusing to check selectors in all cases where
	// x.typ is incomplete.
	if  {
		.errorf(.Sel, NotAType, "%s is not a type", ast.Expr())
		goto 
	}

	, ,  = lookupFieldOrMethod(.typ, .mode == variable, .pkg, , false)
	if  == nil {
		// Don't report another error if the underlying type was invalid (go.dev/issue/49541).
		if !isValid(under(.typ)) {
			goto 
		}

		if  != nil {
			// TODO(gri) should provide actual type where the conflict happens
			.errorf(.Sel, AmbiguousSelector, "ambiguous selector %s.%s", .expr, )
			goto 
		}

		if  {
			if .mode == typexpr {
				.errorf(.Sel, InvalidMethodExpr, "invalid method expression %s.%s (needs pointer receiver (*%s).%s)", .typ, , .typ, )
			} else {
				.errorf(.Sel, InvalidMethodExpr, "cannot call pointer method %s on %s", , .typ)
			}
			goto 
		}

		var  string
		if isInterfacePtr(.typ) {
			 = .interfacePtrError(.typ)
		} else {
			, ,  := lookupFieldOrMethod(.typ, .mode == variable, .pkg, , true)
			 = .lookupError(.typ, , , false)
		}
		.errorf(.Sel, MissingFieldOrMethod, "%s.%s undefined (%s)", .expr, , )
		goto 
	}

	// methods may not have a fully set up signature yet
	if ,  := .(*Func);  != nil {
		.objDecl(, nil)
	}

	if .mode == typexpr {
		// method expression
		,  := .(*Func)
		if  == nil {
			.errorf(.Sel, MissingFieldOrMethod, "%s.%s undefined (type %s has no method %s)", .expr, , .typ, )
			goto 
		}

		.recordSelection(, MethodExpr, .typ, , , )

		 := .typ.(*Signature)
		if .recv == nil {
			.error(, InvalidDeclCycle, "illegal cycle in method declaration")
			goto 
		}

		// the receiver type becomes the type of the first function
		// argument of the method expression's function type
		var  []*Var
		if .params != nil {
			 = .params.vars
		}
		// Be consistent about named/unnamed parameters. This is not needed
		// for type-checking, but the newly constructed signature may appear
		// in an error message and then have mixed named/unnamed parameters.
		// (An alternative would be to not print parameter names in errors,
		// but it's useful to see them; this is cheap and method expressions
		// are rare.)
		 := ""
		if len() > 0 && [0].name != "" {
			// name needed
			 = .recv.name
			if  == "" {
				 = "_"
			}
		}
		 = append([]*Var{NewVar(.recv.pos, .recv.pkg, , .typ)}, ...)
		.mode = value
		.typ = &Signature{
			tparams:  .tparams,
			params:   NewTuple(...),
			results:  .results,
			variadic: .variadic,
		}

		.addDeclDep()

	} else {
		// regular selector
		switch obj := .(type) {
		case *Var:
			.recordSelection(, FieldVal, .typ, , , )
			if .mode == variable ||  {
				.mode = variable
			} else {
				.mode = value
			}
			.typ = .typ

		case *Func:
			// TODO(gri) If we needed to take into account the receiver's
			// addressability, should we report the type &(x.typ) instead?
			.recordSelection(, MethodVal, .typ, , , )

			// TODO(gri) The verification pass below is disabled for now because
			//           method sets don't match method lookup in some cases.
			//           For instance, if we made a copy above when creating a
			//           custom method for a parameterized received type, the
			//           method set method doesn't match (no copy there). There
			///          may be other situations.
			 := true
			if ! && debug {
				// Verify that LookupFieldOrMethod and MethodSet.Lookup agree.
				// TODO(gri) This only works because we call LookupFieldOrMethod
				// _before_ calling NewMethodSet: LookupFieldOrMethod completes
				// any incomplete interfaces so they are available to NewMethodSet
				// (which assumes that interfaces have been completed already).
				 := .typ
				if .mode == variable {
					// If typ is not an (unnamed) pointer or an interface,
					// use *typ instead, because the method set of *typ
					// includes the methods of typ.
					// Variables are addressable, so we can always take their
					// address.
					if ,  := .(*Pointer); ! && !IsInterface() {
						 = &Pointer{base: }
					}
				}
				// If we created a synthetic pointer type above, we will throw
				// away the method set computed here after use.
				// TODO(gri) Method set computation should probably always compute
				// both, the value and the pointer receiver method set and represent
				// them in a single structure.
				// TODO(gri) Consider also using a method set cache for the lifetime
				// of checker once we rely on MethodSet lookup instead of individual
				// lookup.
				 := NewMethodSet()
				if  := .Lookup(.pkg, );  == nil || .obj !=  {
					.dump("%v: (%s).%v -> %s", .Pos(), , .name, )
					.dump("%s\n", )
					// Caution: MethodSets are supposed to be used externally
					// only (after all interface types were completed). It's
					// now possible that we get here incorrectly. Not urgent
					// to fix since we only run this code in debug mode.
					// TODO(gri) fix this eventually.
					panic("method sets and lookup don't agree")
				}
			}

			.mode = value

			// remove receiver
			 := *.typ.(*Signature)
			.recv = nil
			.typ = &

			.addDeclDep()

		default:
			panic("unreachable")
		}
	}

	// everything went well
	.expr = 
	return

:
	.mode = invalid
	.expr = 
}

// use type-checks each argument.
// Useful to make sure expressions are evaluated
// (and variables are "used") in the presence of
// other errors. Arguments may be nil.
// Reports if all arguments evaluated without error.
func ( *Checker) ( ...ast.Expr) bool { return .useN(, false) }

// useLHS is like use, but doesn't "use" top-level identifiers.
// It should be called instead of use if the arguments are
// expressions on the lhs of an assignment.
func ( *Checker) ( ...ast.Expr) bool { return .useN(, true) }

func ( *Checker) ( []ast.Expr,  bool) bool {
	 := true
	for ,  := range  {
		if !.use1(, ) {
			 = false
		}
	}
	return 
}

func ( *Checker) ( ast.Expr,  bool) bool {
	var  operand
	.mode = value // anything but invalid
	switch n := ast.Unparen().(type) {
	case nil:
		// nothing to do
	case *ast.Ident:
		// don't report an error evaluating blank
		if .Name == "_" {
			break
		}
		// If the lhs is an identifier denoting a variable v, this assignment
		// is not a 'use' of v. Remember current value of v.used and restore
		// after evaluating the lhs via check.rawExpr.
		var  *Var
		var  bool
		if  {
			if ,  := .scope.LookupParent(.Name, nopos);  != nil {
				// It's ok to mark non-local variables, but ignore variables
				// from other packages to avoid potential race conditions with
				// dot-imported variables.
				if ,  := .(*Var);  != nil && .pkg == .pkg {
					 = 
					 = .used
				}
			}
		}
		.exprOrType(&, , true)
		if  != nil {
			.used =  // restore v.used
		}
	default:
		.rawExpr(nil, &, , nil, true)
	}
	return .mode != invalid
}