//
var args []*operand
var params []*Var
+ var reverse bool
if T != nil && sig.tparams != nil {
if !versionErr && !check.allowVersion(check.pkg, instErrPos, go1_21) {
if inst != nil {
// that makes sense when reported in error messages from infer, below.
expr := syntax.NewName(x.Pos(), T.desc)
args = []*operand{{mode: value, expr: expr, typ: T.sig}}
+ reverse = true
}
// Rename type parameters to avoid problems with recursive instantiations.
// 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)
+ targs = check.infer(pos, tparams, targs, params2.(*Tuple), args, reverse)
if targs == nil {
// error was already reported
x.mode = invalid
// infer missing type arguments of callee and function arguments
if len(tparams) > 0 {
- targs = check.infer(call.Pos(), tparams, targs, sigParams, args)
+ targs = check.infer(call.Pos(), tparams, targs, sigParams, args, false)
if targs == nil {
// TODO(gri) If infer inferred the first targs[:n], consider instantiating
// the call signature for better error messages/gopls behavior.
// based on the given type parameters tparams, type arguments targs, function parameters params, and
// function arguments args, if any. There must be at least one type parameter, no more type arguments
// than type parameters, and params and args must match in number (incl. zero).
+// 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) (inferred []Type) {
+func (check *Checker) infer(pos syntax.Pos, tparams []*TypeParam, targs []Type, params *Tuple, args []*operand, reverse bool) (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
// InvalidTypeArg). We can't differentiate these cases, so fall back on
// the more general CannotInferTypeArgs.
if inferred != tpar {
- check.errorf(arg, CannotInferTypeArgs, "type %s of %s does not match inferred type %s for %s", targ, arg.expr, 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)
+ } else {
+ check.errorf(arg, CannotInferTypeArgs, "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)
}
//
var args []*operand
var params []*Var
+ var reverse bool
if T != nil && sig.tparams != nil {
if !versionErr && !check.allowVersion(check.pkg, instErrPos, go1_21) {
if ix != nil {
expr := ast.NewIdent(T.desc)
expr.NamePos = x.Pos() // correct position
args = []*operand{{mode: value, expr: expr, typ: T.sig}}
+ reverse = true
}
// Rename type parameters to avoid problems with recursive instantiations.
// 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)
+ targs = check.infer(atPos(pos), tparams, targs, params2.(*Tuple), args, reverse)
if targs == nil {
// error was already reported
x.mode = invalid
// infer missing type arguments of callee and function arguments
if len(tparams) > 0 {
- targs = check.infer(call, tparams, targs, sigParams, args)
+ targs = check.infer(call, tparams, targs, sigParams, args, false)
if targs == nil {
// TODO(gri) If infer inferred the first targs[:n], consider instantiating
// the call signature for better error messages/gopls behavior.
// based on the given type parameters tparams, type arguments targs, function parameters params, and
// function arguments args, if any. There must be at least one type parameter, no more type arguments
// than type parameters, and params and args must match in number (incl. zero).
+// 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) (inferred []Type) {
+func (check *Checker) infer(posn positioner, tparams []*TypeParam, targs []Type, params *Tuple, args []*operand, reverse bool) (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
// InvalidTypeArg). We can't differentiate these cases, so fall back on
// the more general CannotInferTypeArgs.
if inferred != tpar {
- check.errorf(arg, CannotInferTypeArgs, "type %s of %s does not match inferred type %s for %s", targ, arg.expr, 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)
+ } else {
+ check.errorf(arg, CannotInferTypeArgs, "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)
}
_ func(int) int = f3[int]
v6 func(int, int) = f4
- v7 func(int, string) = f4 // ERROR "type func(int, string) of v7 does not match inferred type func(int, int) for func(P, P)"
+ v7 func(int, string) = f4 // ERROR "inferred type func(int, int) for func(P, P) does not match type func(int, string) of v7"
v8 func(int) []int = f5
- v9 func(string) []int = f5 // ERROR "type func(string) []int of v9 does not match inferred type func(string) []string for func(P) []P"
+ v9 func(string) []int = f5 // ERROR "inferred type func(string) []string for func(P) []P does not match type func(string) []int of v9"
_, _ func(int) = f1, f1
_, _ func(int) = f1, f2 // ERROR "cannot infer P"
v5 = f3[int]
v6 = f4
- v7 = f4 // ERROR "type func(int, string) of v7 does not match inferred type func(int, int) for func(P, P)"
+ v7 = f4 // ERROR "inferred type func(int, int) for func(P, P) does not match type func(int, string) of v7"
v8 = f5
- v9 = f5 // ERROR "type func(string) []int of v9 does not match inferred type func(string) []string for func(P) []P"
+ v9 = f5 // ERROR "inferred type func(string) []string for func(P) []P does not match type func(string) []int of v9"
// non-trivial LHS
var a [2]func(string) []int
- a[0] = f5 // ERROR "type func(string) []int of a[0] does not match inferred type func(string) []string for func(P) []P"
+ a[0] = f5 // ERROR "inferred type func(string) []string for func(P) []P does not match type func(string) []int of a[0]"
}
// Return statements
func _() func(int, int) { return f4 }
func _() func(int, string) {
- return f4 /* ERROR "type func(int, string) of result variable does not match inferred type func(int, int) for func(P, P)" */
+ return f4 /* ERROR "inferred type func(int, int) for func(P, P) does not match type func(int, string) of result variable" */
}
func _() func(int) []int { return f5 }
func _() func(string) []int {
- return f5 /* ERROR "type func(string) []int of result variable does not match inferred type func(string) []string for func(P) []P" */
+ return f5 /* ERROR "inferred type func(string) []string for func(P) []P does not match type func(string) []int of result variable" */
}
func _() (_, _ func(int)) { return f1, f1 }
// be identical to match).
// The result is an error from type inference, rather than an
// error from an assignment mismatch.
-var f func(int, String) = g // ERROR "type func(int, String) of f does not match inferred type func(int, string) for func(P, string)"
+var f func(int, String) = g // ERROR "inferred type func(int, string) for func(P, string) does not match type func(int, String) of f"
func f[P any](P) P { panic(0) }
-var v func(string) int = f // ERROR "type func(string) int of v does not match inferred type func(string) string for func(P) P"
+var v func(string) int = f // ERROR "inferred type func(string) string for func(P) P does not match type func(string) int of v"
func _() func(string) int {
- return f // ERROR "type func(string) int of result variable does not match inferred type func(string) string for func(P) P"
+ return f // ERROR "inferred type func(string) string for func(P) P does not match type func(string) int of result variable"
}