// ti's are user-friendly string representations for the given types.
// If variadic is set and the last type is a slice, its string is of
// the form "...E" where E is the slice's element type.
-func (check *Checker) typesSummary(list []Type, variadic bool) string {
+// If hasDots is set, the last argument string is of the form "T..."
+// where T is the last type.
+// Only one of variadic and hasDots may be set.
+func (check *Checker) typesSummary(list []Type, variadic, hasDots bool) string {
+ assert(!(variadic && hasDots))
var res []string
for i, t := range list {
var s string
fallthrough // should not happen but be cautious
case !isValid(t):
s = "unknown type"
- case isUntyped(t):
+ case isUntyped(t): // => *Basic
if isNumeric(t) {
// Do not imply a specific type requirement:
// "have number, want float64" is better than
// for compactness.
s = strings.Replace(t.(*Basic).name, "untyped ", "", -1)
}
- case variadic && i == len(list)-1:
- s = check.sprintf("...%s", t.(*Slice).elem)
- }
- if s == "" {
+ default:
s = check.sprintf("%s", t)
}
+ // handle ... parameters/arguments
+ if i == len(list)-1 {
+ switch {
+ case variadic:
+ // In correct code, the parameter type is a slice, but be careful.
+ if t, _ := t.(*Slice); t != nil {
+ s = check.sprintf("%s", t.elem)
+ }
+ s = "..." + s
+ case hasDots:
+ s += "..."
+ }
+ }
res = append(res, s)
}
return "(" + strings.Join(res, ", ") + ")"
}
err := check.newError(WrongResultCount)
err.addf(at, "%s return values", qualifier)
- err.addf(nopos, "have %s", check.typesSummary(operandTypes(rhs), false))
- err.addf(nopos, "want %s", check.typesSummary(varTypes(lhs), false))
+ err.addf(nopos, "have %s", check.typesSummary(operandTypes(rhs), false, false))
+ err.addf(nopos, "want %s", check.typesSummary(varTypes(lhs), false, false))
err.report()
}
}
err := check.newError(WrongArgCount)
err.addf(at, "%s arguments in call to %s", qualifier, call.Fun)
- err.addf(nopos, "have %s", check.typesSummary(operandTypes(args), ddd))
- err.addf(nopos, "want %s", check.typesSummary(varTypes(params), sig.variadic))
+ err.addf(nopos, "have %s", check.typesSummary(operandTypes(args), false, ddd))
+ err.addf(nopos, "want %s", check.typesSummary(varTypes(params), sig.variadic, false))
err.report()
return
}
// ti's are user-friendly string representations for the given types.
// If variadic is set and the last type is a slice, its string is of
// the form "...E" where E is the slice's element type.
-func (check *Checker) typesSummary(list []Type, variadic bool) string {
+// If hasDots is set, the last argument string is of the form "T..."
+// where T is the last type.
+// Only one of variadic and hasDots may be set.
+func (check *Checker) typesSummary(list []Type, variadic, hasDots bool) string {
+ assert(!(variadic && hasDots))
var res []string
for i, t := range list {
var s string
fallthrough // should not happen but be cautious
case !isValid(t):
s = "unknown type"
- case isUntyped(t):
+ case isUntyped(t): // => *Basic
if isNumeric(t) {
// Do not imply a specific type requirement:
// "have number, want float64" is better than
// for compactness.
s = strings.Replace(t.(*Basic).name, "untyped ", "", -1)
}
- case variadic && i == len(list)-1:
- s = check.sprintf("...%s", t.(*Slice).elem)
- }
- if s == "" {
+ default:
s = check.sprintf("%s", t)
}
+ // handle ... parameters/arguments
+ if i == len(list)-1 {
+ switch {
+ case variadic:
+ // In correct code, the parameter type is a slice, but be careful.
+ if t, _ := t.(*Slice); t != nil {
+ s = check.sprintf("%s", t.elem)
+ }
+ s = "..." + s
+ case hasDots:
+ s += "..."
+ }
+ }
res = append(res, s)
}
return "(" + strings.Join(res, ", ") + ")"
}
err := check.newError(WrongResultCount)
err.addf(at, "%s return values", qualifier)
- err.addf(noposn, "have %s", check.typesSummary(operandTypes(rhs), false))
- err.addf(noposn, "want %s", check.typesSummary(varTypes(lhs), false))
+ err.addf(noposn, "have %s", check.typesSummary(operandTypes(rhs), false, false))
+ err.addf(noposn, "want %s", check.typesSummary(varTypes(lhs), false, false))
err.report()
}
}
err := check.newError(WrongArgCount)
err.addf(at, "%s arguments in call to %s", qualifier, call.Fun)
- err.addf(noposn, "have %s", check.typesSummary(operandTypes(args), ddd))
- err.addf(noposn, "want %s", check.typesSummary(varTypes(params), sig.variadic))
+ err.addf(noposn, "have %s", check.typesSummary(operandTypes(args), false, ddd))
+ err.addf(noposn, "want %s", check.typesSummary(varTypes(params), sig.variadic, false))
err.report()
return
}
func _() {
var values []int
vf(values /* ERROR "(variable of type []int) as string value" */)
- vf(values...) /* ERROR "have (...int)" */
- vf("ab", "cd", values /* ERROR "have (string, string, ...int)" */ ...)
+ vf(values...) /* ERROR "have ([]int...)\n\twant (string, ...int)" */
+ vf("ab", "cd", values /* ERROR "have (string, string, []int...)\n\twant (string, ...int)" */ ...)
}
func vf(method string, values ...int) {
--- /dev/null
+// Copyright 2024 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package p
+
+func f(...any)
+
+func _(x int, s []int) {
+ f(0, x /* ERROR "have (number, int...)\n\twant (...any)" */ ...)
+ f(0, s /* ERROR "have (number, []int...)\n\twant (...any)" */ ...)
+ f(0, 0 /* ERROR "have (number, number...)\n\twant (...any)" */ ...)
+}