Black Lives Matter. Support the Equal Justice Initiative.

Source file src/go/types/call.go

Documentation: go/types

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

View as plain text