// Note that NewTuple(params...) below is (*Tuple)(nil) if len(params) == 0, as desired.
tparams, params2 := check.renameTParams(pos, sig.TypeParams().list(), NewTuple(params...))
- targs = check.infer(pos, tparams, targs, params2.(*Tuple), args, reverse)
+ var err error_
+ targs = check.infer(pos, tparams, targs, params2.(*Tuple), args, reverse, &err)
if targs == nil {
- // error was already reported
+ if !err.empty() {
+ err.code = CannotInferTypeArgs
+ check.report(&err)
+ }
x.mode = invalid
return nil, nil
}
// infer missing type arguments of callee and function arguments
if len(tparams) > 0 {
- targs = check.infer(call.Pos(), tparams, targs, sigParams, args, false)
+ var err error_
+ targs = check.infer(call.Pos(), tparams, targs, sigParams, args, false, &err)
if targs == 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.
- return // error already reported
+ if !err.empty() {
+ check.errorf(err.pos(), CannotInferTypeArgs, "in call to %s, %s", call.Fun, err.msg(check.qualifier))
+ }
+ return
}
// update result signature: instantiate if needed
import (
"cmd/compile/internal/syntax"
"fmt"
- . "internal/types/errors"
"strings"
)
// If reverse is set, an error message's contents are reversed for a better error message for some
// errors related to reverse type inference (where the function call is synthetic).
// If successful, infer returns the complete list of given and inferred type arguments, one for each
-// type parameter. Otherwise the result is nil and appropriate errors will be reported.
-func (check *Checker) infer(pos syntax.Pos, tparams []*TypeParam, targs []Type, params *Tuple, args []*operand, reverse bool) (inferred []Type) {
+// type parameter. Otherwise the result is nil. Errors are reported through the err parameter.
+// Note: infer may fail (return nil) due to invalid args operands without reporting additional errors.
+func (check *Checker) infer(pos syntax.Pos, tparams []*TypeParam, targs []Type, params *Tuple, args []*operand, reverse bool, err *error_) (inferred []Type) {
// Don't verify result conditions if there's no error handler installed:
// in that case, an error leads to an exit panic and the result value may
// be incorrect. But in that case it doesn't matter because callers won't
}
}
if allFailed {
- check.errorf(arg, CannotInferTypeArgs, "type %s of %s does not match %s (cannot infer %s)", targ, arg.expr, tpar, typeParamsString(tparams))
+ err.errorf(arg, "type %s of %s does not match %s (cannot infer %s)", targ, arg.expr, tpar, typeParamsString(tparams))
return
}
}
// the more general CannotInferTypeArgs.
if inferred != tpar {
if reverse {
- check.errorf(arg, CannotInferTypeArgs, "inferred type %s for %s does not match type %s of %s", inferred, tpar, targ, arg.expr)
+ err.errorf(arg, "inferred type %s for %s does not match type %s of %s", inferred, tpar, targ, arg.expr)
} else {
- check.errorf(arg, CannotInferTypeArgs, "type %s of %s does not match inferred type %s for %s", targ, arg.expr, inferred, tpar)
+ err.errorf(arg, "type %s of %s does not match inferred type %s for %s", targ, arg.expr, inferred, tpar)
}
} else {
- check.errorf(arg, CannotInferTypeArgs, "type %s of %s does not match %s", targ, arg.expr, tpar)
+ err.errorf(arg, "type %s of %s does not match %s", targ, arg.expr, tpar)
}
}
// TODO(gri) Type parameters that appear in the constraint and
// for which we have type arguments inferred should
// use those type arguments for a better error message.
- check.errorf(pos, CannotInferTypeArgs, "%s (type %s) does not satisfy %s", tpar, tx, tpar.Constraint())
+ err.errorf(pos, "%s (type %s) does not satisfy %s", tpar, tx, tpar.Constraint())
return nil
}
case single && !core.tilde:
constraint := tpar.iface()
if m, _ := check.missingMethod(tx, constraint, true, func(x, y Type) bool { return u.unify(x, y, exact) }, &cause); m != nil {
// TODO(gri) better error message (see TODO above)
- check.errorf(pos, CannotInferTypeArgs, "%s (type %s) does not satisfy %s %s", tpar, tx, tpar.Constraint(), cause)
+ err.errorf(pos, "%s (type %s) does not satisfy %s %s", tpar, tx, tpar.Constraint(), cause)
return nil
}
}
} else {
m := maxType(max, arg.typ)
if m == nil {
- check.errorf(arg, CannotInferTypeArgs, "mismatched types %s and %s (cannot infer %s)", max, arg.typ, tpar)
+ err.errorf(arg, "mismatched types %s and %s (cannot infer %s)", max, arg.typ, tpar)
return nil
}
max = m
for i, typ := range inferred {
if typ == nil || isParameterized(tparams, typ) {
obj := tparams[i].obj
- check.errorf(pos, CannotInferTypeArgs, "cannot infer %s (%s)", obj.name, obj.pos)
+ err.errorf(pos, "cannot infer %s (%s)", obj.name, obj.pos)
return nil
}
}
}
var err error_
err.code = WrongResultCount
- err.errorf(at.Pos(), "%s return values", qualifier)
- err.errorf(nopos, "have %s", check.typesSummary(operandTypes(rhs), false))
- err.errorf(nopos, "want %s", check.typesSummary(varTypes(lhs), false))
+ err.errorf(at, "%s return values", qualifier)
+ err.errorf(noposn, "have %s", check.typesSummary(operandTypes(rhs), false))
+ err.errorf(noposn, "want %s", check.typesSummary(varTypes(lhs), false))
check.report(&err)
}
// Note that NewTuple(params...) below is (*Tuple)(nil) if len(params) == 0, as desired.
tparams, params2 := check.renameTParams(pos, sig.TypeParams().list(), NewTuple(params...))
- targs = check.infer(atPos(pos), tparams, targs, params2.(*Tuple), args, reverse)
+ var err error_
+ targs = check.infer(atPos(pos), tparams, targs, params2.(*Tuple), args, reverse, &err)
if targs == nil {
- // error was already reported
+ if !err.empty() {
+ err.code = CannotInferTypeArgs
+ check.report(&err)
+ }
x.mode = invalid
return nil, nil
}
params = sig.params.vars
}
err := newErrorf(at, WrongArgCount, "%s arguments in call to %s", qualifier, call.Fun)
- err.errorf(nopos, "have %s", check.typesSummary(operandTypes(args), false))
- err.errorf(nopos, "want %s", check.typesSummary(varTypes(params), sig.variadic))
+ err.errorf(noposn, "have %s", check.typesSummary(operandTypes(args), false))
+ err.errorf(noposn, "want %s", check.typesSummary(varTypes(params), sig.variadic))
check.report(err)
return
}
// infer missing type arguments of callee and function arguments
if len(tparams) > 0 {
- targs = check.infer(call, tparams, targs, sigParams, args, false)
+ var err error_
+ targs = check.infer(call, tparams, targs, sigParams, args, false, &err)
if targs == 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.
- return // error already reported
+ if !err.empty() {
+ check.errorf(err.posn(), CannotInferTypeArgs, "in call to %s, %s", call.Fun, err.msg(check.fset, check.qualifier))
+ }
+ return
}
// update result signature: instantiate if needed
"strings"
)
-// nopos indicates an unknown position
+// nopos, noposn indicate an unknown position
var nopos token.Pos
+var noposn = atPos(nopos)
// debugging/development support
const debug = false // leave on during development
return err.desc == nil
}
-func (err *error_) pos() token.Pos {
+func (err *error_) posn() positioner {
if err.empty() {
- return nopos
+ return noposn
}
- return err.desc[0].posn.Pos()
+ return err.desc[0].posn
}
func (err *error_) msg(fset *token.FileSet, qf Qualifier) string {
if err.empty() {
return "no error"
}
- return fmt.Sprintf("%d: %s", err.pos(), err.msg(nil, nil))
+ return fmt.Sprintf("%d: %s", err.posn().Pos(), err.msg(nil, nil))
}
// errorf adds formatted error information to err.
// It may be called multiple times to provide additional information.
-func (err *error_) errorf(at token.Pos, format string, args ...interface{}) {
- err.desc = append(err.desc, errorDesc{atPos(at), format, args})
+func (err *error_) errorf(at positioner, format string, args ...interface{}) {
+ err.desc = append(err.desc, errorDesc{at, format, args})
}
func (check *Checker) qualifier(pkg *Package) string {
}
want = "0: foo 42"
- err.errorf(nopos, "foo %d", 42)
+ err.errorf(noposn, "foo %d", 42)
if got := err.String(); got != want {
t.Errorf("simple error: got %q, want %q", got, want)
}
want = "0: foo 42\n\tbar 43"
- err.errorf(nopos, "bar %d", 43)
+ err.errorf(noposn, "bar %d", 43)
if got := err.String(); got != want {
t.Errorf("simple error: got %q, want %q", got, want)
}
import (
"fmt"
"go/token"
- . "internal/types/errors"
"strings"
)
// If reverse is set, an error message's contents are reversed for a better error message for some
// errors related to reverse type inference (where the function call is synthetic).
// If successful, infer returns the complete list of given and inferred type arguments, one for each
-// type parameter. Otherwise the result is nil and appropriate errors will be reported.
-func (check *Checker) infer(posn positioner, tparams []*TypeParam, targs []Type, params *Tuple, args []*operand, reverse bool) (inferred []Type) {
+// type parameter. Otherwise the result is nil. Errors are reported through the err parameter.
+// Note: infer may fail (return nil) due to invalid args operands without reporting additional errors.
+func (check *Checker) infer(posn positioner, tparams []*TypeParam, targs []Type, params *Tuple, args []*operand, reverse bool, err *error_) (inferred []Type) {
// Don't verify result conditions if there's no error handler installed:
// in that case, an error leads to an exit panic and the result value may
// be incorrect. But in that case it doesn't matter because callers won't
}
}
if allFailed {
- check.errorf(arg, CannotInferTypeArgs, "type %s of %s does not match %s (cannot infer %s)", targ, arg.expr, tpar, typeParamsString(tparams))
+ err.errorf(arg, "type %s of %s does not match %s (cannot infer %s)", targ, arg.expr, tpar, typeParamsString(tparams))
return
}
}
// the more general CannotInferTypeArgs.
if inferred != tpar {
if reverse {
- check.errorf(arg, CannotInferTypeArgs, "inferred type %s for %s does not match type %s of %s", inferred, tpar, targ, arg.expr)
+ err.errorf(arg, "inferred type %s for %s does not match type %s of %s", inferred, tpar, targ, arg.expr)
} else {
- check.errorf(arg, CannotInferTypeArgs, "type %s of %s does not match inferred type %s for %s", targ, arg.expr, inferred, tpar)
+ err.errorf(arg, "type %s of %s does not match inferred type %s for %s", targ, arg.expr, inferred, tpar)
}
} else {
- check.errorf(arg, CannotInferTypeArgs, "type %s of %s does not match %s", targ, arg.expr, tpar)
+ err.errorf(arg, "type %s of %s does not match %s", targ, arg.expr, tpar)
}
}
// TODO(gri) Type parameters that appear in the constraint and
// for which we have type arguments inferred should
// use those type arguments for a better error message.
- check.errorf(posn, CannotInferTypeArgs, "%s (type %s) does not satisfy %s", tpar, tx, tpar.Constraint())
+ err.errorf(posn, "%s (type %s) does not satisfy %s", tpar, tx, tpar.Constraint())
return nil
}
case single && !core.tilde:
constraint := tpar.iface()
if m, _ := check.missingMethod(tx, constraint, true, func(x, y Type) bool { return u.unify(x, y, exact) }, &cause); m != nil {
// TODO(gri) better error message (see TODO above)
- check.errorf(posn, CannotInferTypeArgs, "%s (type %s) does not satisfy %s %s", tpar, tx, tpar.Constraint(), cause)
+ err.errorf(posn, "%s (type %s) does not satisfy %s %s", tpar, tx, tpar.Constraint(), cause)
return nil
}
}
} else {
m := maxType(max, arg.typ)
if m == nil {
- check.errorf(arg, CannotInferTypeArgs, "mismatched types %s and %s (cannot infer %s)", max, arg.typ, tpar)
+ err.errorf(arg, "mismatched types %s and %s (cannot infer %s)", max, arg.typ, tpar)
return nil
}
max = m
for i, typ := range inferred {
if typ == nil || isParameterized(tparams, typ) {
obj := tparams[i].obj
- check.errorf(posn, CannotInferTypeArgs, "cannot infer %s (%s)", obj.name, obj.pos)
+ err.errorf(posn, "cannot infer %s (%s)", obj.name, obj.pos)
return nil
}
}
}
var versions func()
-var _ = Clip /* ERROR "S (type func()) does not satisfy ~[]E" */ (versions)
+var _ = Clip /* ERROR "in call to Clip, S (type func()) does not satisfy ~[]E" */ (versions)