diff options
Diffstat (limited to 'src/cmd/compile/internal/types2/call.go')
-rw-r--r-- | src/cmd/compile/internal/types2/call.go | 68 |
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 = © } // 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, } |