mirror of
https://github.com/golang/go
synced 2024-11-17 17:54:48 -07:00
go/types, types2: flip message contents for reverse type inference errors
Add a new flag 'reverse' to control the formatting of type inference error messages. This change only impacts error messages. Fixes #60747. Change-Id: I81e13075e3157252ccc09f358bd29bd676c34499 Reviewed-on: https://go-review.googlesource.com/c/go/+/549055 Reviewed-by: Robert Findley <rfindley@google.com> Reviewed-by: Robert Griesemer <gri@google.com> Auto-Submit: Robert Griesemer <gri@google.com> Run-TryBot: Robert Griesemer <gri@google.com> TryBot-Result: Gopher Robot <gobot@golang.org>
This commit is contained in:
parent
2643a59172
commit
0ac1e3b245
@ -87,6 +87,7 @@ func (check *Checker) funcInst(T *target, pos syntax.Pos, x *operand, inst *synt
|
||||
//
|
||||
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 {
|
||||
@ -102,13 +103,14 @@ func (check *Checker) funcInst(T *target, pos syntax.Pos, x *operand, inst *synt
|
||||
// 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
|
||||
@ -608,7 +610,7 @@ func (check *Checker) arguments(call *syntax.CallExpr, sig *Signature, targs []T
|
||||
|
||||
// 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.
|
||||
|
@ -24,9 +24,11 @@ const enableReverseTypeInference = true // disable for debugging
|
||||
// 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
|
||||
@ -137,7 +139,11 @@ func (check *Checker) infer(pos syntax.Pos, tparams []*TypeParam, targs []Type,
|
||||
// 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)
|
||||
}
|
||||
|
@ -89,6 +89,7 @@ func (check *Checker) funcInst(T *target, pos token.Pos, x *operand, ix *typepar
|
||||
//
|
||||
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 {
|
||||
@ -105,13 +106,14 @@ func (check *Checker) funcInst(T *target, pos token.Pos, x *operand, ix *typepar
|
||||
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
|
||||
@ -610,7 +612,7 @@ func (check *Checker) arguments(call *ast.CallExpr, sig *Signature, targs []Type
|
||||
|
||||
// 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.
|
||||
|
@ -26,9 +26,11 @@ const enableReverseTypeInference = true // disable for debugging
|
||||
// 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
|
||||
@ -139,7 +141,11 @@ func (check *Checker) infer(posn positioner, tparams []*TypeParam, targs []Type,
|
||||
// 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)
|
||||
}
|
||||
|
@ -27,9 +27,9 @@ var (
|
||||
_ 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"
|
||||
@ -49,13 +49,13 @@ func _() {
|
||||
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
|
||||
@ -66,11 +66,11 @@ func _() func(int) int { return f3[int] }
|
||||
|
||||
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 }
|
||||
|
@ -13,4 +13,4 @@ func g[P any](P, string) {}
|
||||
// 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"
|
||||
|
@ -6,8 +6,8 @@ package p
|
||||
|
||||
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"
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user