aboutsummaryrefslogtreecommitdiff
path: root/src/cmd/compile/internal/types2/call.go
diff options
context:
space:
mode:
Diffstat (limited to 'src/cmd/compile/internal/types2/call.go')
-rw-r--r--src/cmd/compile/internal/types2/call.go68
1 files changed, 43 insertions, 25 deletions
diff --git a/src/cmd/compile/internal/types2/call.go b/src/cmd/compile/internal/types2/call.go
index 6d149340b2..049d80dd9e 100644
--- a/src/cmd/compile/internal/types2/call.go
+++ b/src/cmd/compile/internal/types2/call.go
@@ -26,7 +26,7 @@ func (check *Checker) funcInst(x *operand, inst *syntax.IndexExpr) {
// check number of type arguments (got) vs number of type parameters (want)
sig := x.typ.(*Signature)
- got, want := len(targs), len(sig.tparams)
+ got, want := len(targs), sig.TParams().Len()
if !useConstraintTypeInference && got != want || got > want {
check.errorf(xlist[got-1], "got %d type arguments but want %d", got, want)
x.mode = invalid
@@ -37,7 +37,7 @@ func (check *Checker) funcInst(x *operand, inst *syntax.IndexExpr) {
// if we don't have enough type arguments, try type inference
inferred := false
if got < want {
- targs = check.infer(inst.Pos(), sig.tparams, targs, nil, nil, true)
+ targs = check.infer(inst.Pos(), sig.TParams().list(), targs, nil, nil, true)
if targs == nil {
// error was already reported
x.mode = invalid
@@ -56,8 +56,8 @@ func (check *Checker) funcInst(x *operand, inst *syntax.IndexExpr) {
}
// instantiate function signature
- res := check.instantiate(x.Pos(), sig, targs, poslist).(*Signature)
- assert(res.tparams == nil) // signature is not generic anymore
+ res := check.Instantiate(x.Pos(), sig, targs, poslist, true).(*Signature)
+ assert(res.TParams().Len() == 0) // signature is not generic anymore
if inferred {
check.recordInferred(inst, targs, res)
}
@@ -99,7 +99,6 @@ func (check *Checker) callExpr(x *operand, call *syntax.CallExpr) exprKind {
check.expr(x, call.ArgList[0])
if x.mode != invalid {
if t := asInterface(T); t != nil {
- check.completeInterface(nopos, t)
if t.IsConstraint() {
check.errorf(call, "cannot use interface %s in conversion (contains type list or is comparable)", T)
break
@@ -156,7 +155,7 @@ func (check *Checker) callExpr(x *operand, call *syntax.CallExpr) exprKind {
assert(len(targs) == len(xlist))
// check number of type arguments (got) vs number of type parameters (want)
- got, want := len(targs), len(sig.tparams)
+ got, want := len(targs), sig.TParams().Len()
if got > want {
check.errorf(xlist[want], "got %d type arguments but want %d", got, want)
check.use(call.ArgList...)
@@ -190,7 +189,7 @@ func (check *Checker) callExpr(x *operand, call *syntax.CallExpr) exprKind {
// if type inference failed, a parametrized result must be invalidated
// (operands cannot have a parametrized type)
- if x.mode == value && len(sig.tparams) > 0 && isParameterized(sig.tparams, x.typ) {
+ if x.mode == value && sig.TParams().Len() > 0 && isParameterized(sig.TParams().list(), x.typ) {
x.mode = invalid
}
@@ -318,24 +317,24 @@ func (check *Checker) arguments(call *syntax.CallExpr, sig *Signature, targs []T
}
// infer type arguments and instantiate signature if necessary
- if len(sig.tparams) > 0 {
+ if sig.TParams().Len() > 0 {
// TODO(gri) provide position information for targs so we can feed
// it to the instantiate call for better error reporting
- targs = check.infer(call.Pos(), sig.tparams, targs, sigParams, args, true)
+ targs := check.infer(call.Pos(), sig.TParams().list(), targs, sigParams, args, true)
if targs == nil {
return // error already reported
}
// compute result signature
- rsig = check.instantiate(call.Pos(), sig, targs, nil).(*Signature)
- assert(rsig.tparams == nil) // signature is not generic anymore
+ rsig = check.Instantiate(call.Pos(), sig, targs, nil, true).(*Signature)
+ assert(rsig.TParams().Len() == 0) // signature is not generic anymore
check.recordInferred(call, targs, rsig)
// Optimization: Only if the parameter list was adjusted do we
// need to compute it from the adjusted list; otherwise we can
// simply use the result signature's parameter list.
if adjusted {
- sigParams = check.subst(call.Pos(), sigParams, makeSubstMap(sig.tparams, targs)).(*Tuple)
+ sigParams = check.subst(call.Pos(), sigParams, makeSubstMap(sig.TParams().list(), targs)).(*Tuple)
} else {
sigParams = rsig.params
}
@@ -468,7 +467,7 @@ func (check *Checker) selector(x *operand, e *syntax.SelectorExpr) {
check.instantiatedOperand(x)
- obj, index, indirect = check.lookupFieldOrMethod(x.typ, x.mode == variable, check.pkg, sel)
+ obj, index, indirect = LookupFieldOrMethod(x.typ, x.mode == variable, check.pkg, sel)
if obj == nil {
switch {
case index != nil:
@@ -480,11 +479,10 @@ func (check *Checker) selector(x *operand, e *syntax.SelectorExpr) {
var why string
if tpar := asTypeParam(x.typ); tpar != nil {
// Type parameter bounds don't specify fields, so don't mention "field".
- switch obj := tpar.Bound().obj.(type) {
- case nil:
+ if tname := tpar.iface().obj; tname != nil {
+ why = check.sprintf("interface %s has no method %s", tname.name, sel)
+ } else {
why = check.sprintf("type bound for %s has no method %s", x.typ, sel)
- case *TypeName:
- why = check.sprintf("interface %s has no method %s", obj.name, sel)
}
} else {
why = check.sprintf("type %s has no field or method %s", x.typ, sel)
@@ -498,7 +496,7 @@ func (check *Checker) selector(x *operand, e *syntax.SelectorExpr) {
} else {
changeCase = string(unicode.ToUpper(r)) + sel[1:]
}
- if obj, _, _ = check.lookupFieldOrMethod(x.typ, x.mode == variable, check.pkg, changeCase); obj != nil {
+ if obj, _, _ = LookupFieldOrMethod(x.typ, x.mode == variable, check.pkg, changeCase); obj != nil {
why += ", but does have " + changeCase
}
}
@@ -518,7 +516,7 @@ func (check *Checker) selector(x *operand, e *syntax.SelectorExpr) {
// the signature accordingly.
// TODO(gri) factor this code out
sig := m.typ.(*Signature)
- if len(sig.rparams) > 0 {
+ if sig.RParams().Len() > 0 {
// For inference to work, we must use the receiver type
// matching the receiver in the actual method declaration.
// If the method is embedded, the matching receiver is the
@@ -547,7 +545,7 @@ func (check *Checker) selector(x *operand, e *syntax.SelectorExpr) {
// the receiver type arguments here, the receiver must be be otherwise invalid
// and an error has been reported elsewhere.
arg := operand{mode: variable, expr: x.expr, typ: recv}
- targs := check.infer(m.pos, sig.rparams, nil, NewTuple(sig.recv), []*operand{&arg}, false /* no error reporting */)
+ targs := check.infer(m.pos, sig.RParams().list(), nil, NewTuple(sig.recv), []*operand{&arg}, false /* no error reporting */)
//check.dump("### inferred targs = %s", targs)
if targs == nil {
// We may reach here if there were other errors (see issue #40056).
@@ -557,7 +555,7 @@ func (check *Checker) selector(x *operand, e *syntax.SelectorExpr) {
// (If we modify m, some tests will fail; possibly because the m is in use.)
// TODO(gri) investigate and provide a correct explanation here
copy := *m
- copy.typ = check.subst(e.Pos(), m.typ, makeSubstMap(sig.rparams, targs))
+ copy.typ = check.subst(e.Pos(), m.typ, makeSubstMap(sig.RParams().list(), targs))
obj = &copy
}
// TODO(gri) we also need to do substitution for parameterized interface methods
@@ -576,17 +574,37 @@ func (check *Checker) selector(x *operand, e *syntax.SelectorExpr) {
check.recordSelection(e, MethodExpr, x.typ, m, index, indirect)
- // the receiver type becomes the type of the first function
- // argument of the method expression's function type
- var params []*Var
sig := m.typ.(*Signature)
+ if sig.recv == nil {
+ check.error(e, "illegal cycle in method declaration")
+ goto Error
+ }
+
+ // The receiver type becomes the type of the first function
+ // argument of the method expression's function type.
+ var params []*Var
if sig.params != nil {
params = sig.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.)
+ name := ""
+ if len(params) > 0 && params[0].name != "" {
+ // name needed
+ name = sig.recv.name
+ if name == "" {
+ name = "_"
+ }
+ }
+ params = append([]*Var{NewVar(sig.recv.pos, sig.recv.pkg, name, x.typ)}, params...)
x.mode = value
x.typ = &Signature{
tparams: sig.tparams,
- params: NewTuple(append([]*Var{NewVar(nopos, check.pkg, "_", x.typ)}, params...)...),
+ params: NewTuple(params...),
results: sig.results,
variadic: sig.variadic,
}