mirror of
https://github.com/golang/go
synced 2024-11-26 02:07:57 -07:00
cmd/compile: use "satisfies" (not "implements") for constraint errors
Per the latest spec, we distinguish between interface implementation and constraint satisfaction. Use the verb "satisfy" when reporting an error about failing constraint satisfaction. This CL only changes error messages. It has no impact on correct code. Fixes #57564. Change-Id: I6dfb3b2093c2e04fe5566628315fb5f6bd709f17 Reviewed-on: https://go-review.googlesource.com/c/go/+/460396 Reviewed-by: Robert Griesemer <gri@google.com> TryBot-Result: Gopher Robot <gobot@golang.org> Run-TryBot: Robert Griesemer <gri@google.com> Reviewed-by: Ian Lance Taylor <iant@google.com>
This commit is contained in:
parent
79cdecc852
commit
46e3d9d12a
@ -188,7 +188,7 @@ func (check *Checker) verify(pos syntax.Pos, tparams []*TypeParam, targs []Type,
|
||||
// is set, T is a type constraint.
|
||||
//
|
||||
// If the provided cause is non-nil, it may be set to an error string
|
||||
// explaining why V does not implement T.
|
||||
// explaining why V does not implement (or satisfy, for constraints) T.
|
||||
func (check *Checker) implements(V, T Type, constraint bool, cause *string) bool {
|
||||
Vu := under(V)
|
||||
Tu := under(T)
|
||||
@ -199,6 +199,11 @@ func (check *Checker) implements(V, T Type, constraint bool, cause *string) bool
|
||||
return true // avoid follow-on errors (see issue #49541 for an example)
|
||||
}
|
||||
|
||||
verb := "implement"
|
||||
if constraint {
|
||||
verb = "satisfy"
|
||||
}
|
||||
|
||||
Ti, _ := Tu.(*Interface)
|
||||
if Ti == nil {
|
||||
if cause != nil {
|
||||
@ -208,7 +213,7 @@ func (check *Checker) implements(V, T Type, constraint bool, cause *string) bool
|
||||
} else {
|
||||
detail = check.sprintf("%s is not an interface", T)
|
||||
}
|
||||
*cause = check.sprintf("%s does not implement %s (%s)", V, T, detail)
|
||||
*cause = check.sprintf("%s does not %s %s (%s)", V, verb, T, detail)
|
||||
}
|
||||
return false
|
||||
}
|
||||
@ -230,7 +235,7 @@ func (check *Checker) implements(V, T Type, constraint bool, cause *string) bool
|
||||
// No type with non-empty type set satisfies the empty type set.
|
||||
if Ti.typeSet().IsEmpty() {
|
||||
if cause != nil {
|
||||
*cause = check.sprintf("cannot implement %s (empty type set)", T)
|
||||
*cause = check.sprintf("cannot %s %s (empty type set)", verb, T)
|
||||
}
|
||||
return false
|
||||
}
|
||||
@ -238,7 +243,7 @@ func (check *Checker) implements(V, T Type, constraint bool, cause *string) bool
|
||||
// V must implement T's methods, if any.
|
||||
if m, wrong := check.missingMethod(V, Ti, true); m != nil /* !Implements(V, Ti) */ {
|
||||
if cause != nil {
|
||||
*cause = check.sprintf("%s does not implement %s %s", V, T, check.missingMethodCause(V, T, m, wrong))
|
||||
*cause = check.sprintf("%s does not %s %s %s", V, verb, T, check.missingMethodCause(V, T, m, wrong))
|
||||
}
|
||||
return false
|
||||
}
|
||||
@ -258,7 +263,7 @@ func (check *Checker) implements(V, T Type, constraint bool, cause *string) bool
|
||||
// TODO(gri) remove this check for Go 1.21
|
||||
if check != nil && check.conf.OldComparableSemantics {
|
||||
if cause != nil {
|
||||
*cause = check.sprintf("%s does not implement comparable", V)
|
||||
*cause = check.sprintf("%s does not %s comparable", V, verb)
|
||||
}
|
||||
return false
|
||||
}
|
||||
@ -270,12 +275,12 @@ func (check *Checker) implements(V, T Type, constraint bool, cause *string) bool
|
||||
return true
|
||||
}
|
||||
if cause != nil {
|
||||
*cause = check.sprintf("%s to implement comparable requires go1.20 or later", V)
|
||||
*cause = check.sprintf("%s to %s comparable requires go1.20 or later", V, verb)
|
||||
}
|
||||
return false
|
||||
}
|
||||
if cause != nil {
|
||||
*cause = check.sprintf("%s does not implement comparable", V)
|
||||
*cause = check.sprintf("%s does not %s comparable", V, verb)
|
||||
}
|
||||
return false
|
||||
}
|
||||
@ -293,7 +298,7 @@ func (check *Checker) implements(V, T Type, constraint bool, cause *string) bool
|
||||
if !Vi.typeSet().subsetOf(Ti.typeSet()) {
|
||||
// TODO(gri) report which type is missing
|
||||
if cause != nil {
|
||||
*cause = check.sprintf("%s does not implement %s", V, T)
|
||||
*cause = check.sprintf("%s does not %s %s", V, verb, T)
|
||||
}
|
||||
return false
|
||||
}
|
||||
@ -320,9 +325,9 @@ func (check *Checker) implements(V, T Type, constraint bool, cause *string) bool
|
||||
}) {
|
||||
if cause != nil {
|
||||
if alt != nil {
|
||||
*cause = check.sprintf("%s does not implement %s (possibly missing ~ for %s in constraint %s)", V, T, alt, T)
|
||||
*cause = check.sprintf("%s does not %s %s (possibly missing ~ for %s in constraint %s)", V, verb, T, alt, T)
|
||||
} else {
|
||||
*cause = check.sprintf("%s does not implement %s (%s missing in %s)", V, T, V, Ti.typeSet().terms)
|
||||
*cause = check.sprintf("%s does not %s %s (%s missing in %s)", V, verb, T, V, Ti.typeSet().terms)
|
||||
}
|
||||
}
|
||||
return false
|
||||
|
@ -188,7 +188,7 @@ func (check *Checker) verify(pos token.Pos, tparams []*TypeParam, targs []Type,
|
||||
// is set, T is a type constraint.
|
||||
//
|
||||
// If the provided cause is non-nil, it may be set to an error string
|
||||
// explaining why V does not implement T.
|
||||
// explaining why V does not implement (or satisfy, for constraints) T.
|
||||
func (check *Checker) implements(V, T Type, constraint bool, cause *string) bool {
|
||||
Vu := under(V)
|
||||
Tu := under(T)
|
||||
@ -199,6 +199,11 @@ func (check *Checker) implements(V, T Type, constraint bool, cause *string) bool
|
||||
return true // avoid follow-on errors (see issue #49541 for an example)
|
||||
}
|
||||
|
||||
verb := "implement"
|
||||
if constraint {
|
||||
verb = "satisfy"
|
||||
}
|
||||
|
||||
Ti, _ := Tu.(*Interface)
|
||||
if Ti == nil {
|
||||
if cause != nil {
|
||||
@ -208,7 +213,7 @@ func (check *Checker) implements(V, T Type, constraint bool, cause *string) bool
|
||||
} else {
|
||||
detail = check.sprintf("%s is not an interface", T)
|
||||
}
|
||||
*cause = check.sprintf("%s does not implement %s (%s)", V, T, detail)
|
||||
*cause = check.sprintf("%s does not %s %s (%s)", V, verb, T, detail)
|
||||
}
|
||||
return false
|
||||
}
|
||||
@ -230,7 +235,7 @@ func (check *Checker) implements(V, T Type, constraint bool, cause *string) bool
|
||||
// No type with non-empty type set satisfies the empty type set.
|
||||
if Ti.typeSet().IsEmpty() {
|
||||
if cause != nil {
|
||||
*cause = check.sprintf("cannot implement %s (empty type set)", T)
|
||||
*cause = check.sprintf("cannot %s %s (empty type set)", verb, T)
|
||||
}
|
||||
return false
|
||||
}
|
||||
@ -238,7 +243,7 @@ func (check *Checker) implements(V, T Type, constraint bool, cause *string) bool
|
||||
// V must implement T's methods, if any.
|
||||
if m, wrong := check.missingMethod(V, Ti, true); m != nil /* !Implements(V, Ti) */ {
|
||||
if cause != nil {
|
||||
*cause = check.sprintf("%s does not implement %s %s", V, T, check.missingMethodCause(V, T, m, wrong))
|
||||
*cause = check.sprintf("%s does not %s %s %s", V, verb, T, check.missingMethodCause(V, T, m, wrong))
|
||||
}
|
||||
return false
|
||||
}
|
||||
@ -258,7 +263,7 @@ func (check *Checker) implements(V, T Type, constraint bool, cause *string) bool
|
||||
// TODO(gri) remove this check for Go 1.21
|
||||
if check != nil && check.conf.oldComparableSemantics {
|
||||
if cause != nil {
|
||||
*cause = check.sprintf("%s does not implement comparable", V)
|
||||
*cause = check.sprintf("%s does not %s comparable", V, verb)
|
||||
}
|
||||
return false
|
||||
}
|
||||
@ -270,12 +275,12 @@ func (check *Checker) implements(V, T Type, constraint bool, cause *string) bool
|
||||
return true
|
||||
}
|
||||
if cause != nil {
|
||||
*cause = check.sprintf("%s to implement comparable requires go1.20 or later", V)
|
||||
*cause = check.sprintf("%s to %s comparable requires go1.20 or later", V, verb)
|
||||
}
|
||||
return false
|
||||
}
|
||||
if cause != nil {
|
||||
*cause = check.sprintf("%s does not implement comparable", V)
|
||||
*cause = check.sprintf("%s does not %s comparable", V, verb)
|
||||
}
|
||||
return false
|
||||
}
|
||||
@ -293,7 +298,7 @@ func (check *Checker) implements(V, T Type, constraint bool, cause *string) bool
|
||||
if !Vi.typeSet().subsetOf(Ti.typeSet()) {
|
||||
// TODO(gri) report which type is missing
|
||||
if cause != nil {
|
||||
*cause = check.sprintf("%s does not implement %s", V, T)
|
||||
*cause = check.sprintf("%s does not %s %s", V, verb, T)
|
||||
}
|
||||
return false
|
||||
}
|
||||
@ -320,9 +325,9 @@ func (check *Checker) implements(V, T Type, constraint bool, cause *string) bool
|
||||
}) {
|
||||
if cause != nil {
|
||||
if alt != nil {
|
||||
*cause = check.sprintf("%s does not implement %s (possibly missing ~ for %s in constraint %s)", V, T, alt, T)
|
||||
*cause = check.sprintf("%s does not %s %s (possibly missing ~ for %s in constraint %s)", V, verb, T, alt, T)
|
||||
} else {
|
||||
*cause = check.sprintf("%s does not implement %s (%s missing in %s)", V, T, V, Ti.typeSet().terms)
|
||||
*cause = check.sprintf("%s does not %s %s (%s missing in %s)", V, verb, T, V, Ti.typeSet().terms)
|
||||
}
|
||||
}
|
||||
return false
|
||||
|
8
src/internal/types/testdata/check/issues1.go
vendored
8
src/internal/types/testdata/check/issues1.go
vendored
@ -22,7 +22,7 @@ func _[X comparable, Y interface{comparable; m()}]() {
|
||||
eql(x, x)
|
||||
eql(y, y)
|
||||
eql(y, nil /* ERROR cannot use nil as Y value in argument to eql */ )
|
||||
eql[io /* ERROR does not implement comparable */ .Reader](nil, nil)
|
||||
eql[io /* ERROR does not satisfy comparable */ .Reader](nil, nil)
|
||||
}
|
||||
|
||||
// If we have a receiver of pointer to type parameter type (below: *T)
|
||||
@ -58,7 +58,7 @@ func _() {
|
||||
type T1[P interface{~uint}] struct{}
|
||||
|
||||
func _[P any]() {
|
||||
_ = T1[P /* ERROR P does not implement interface{~uint} */ ]{}
|
||||
_ = T1[P /* ERROR P does not satisfy interface{~uint} */ ]{}
|
||||
}
|
||||
|
||||
// This is the original (simplified) program causing the same issue.
|
||||
@ -74,8 +74,8 @@ func (u T2[U]) Add1() U {
|
||||
return u.s + 1
|
||||
}
|
||||
|
||||
func NewT2[U any]() T2[U /* ERROR U does not implement Unsigned */ ] {
|
||||
return T2[U /* ERROR U does not implement Unsigned */ ]{}
|
||||
func NewT2[U any]() T2[U /* ERROR U does not satisfy Unsigned */ ] {
|
||||
return T2[U /* ERROR U does not satisfy Unsigned */ ]{}
|
||||
}
|
||||
|
||||
func _() {
|
||||
|
28
src/internal/types/testdata/check/typeinst1.go
vendored
28
src/internal/types/testdata/check/typeinst1.go
vendored
@ -210,7 +210,7 @@ func f0[T I0]() {}
|
||||
var _ = f0[int]
|
||||
var _ = f0[bool]
|
||||
var _ = f0[string]
|
||||
var _ = f0[float64 /* ERROR does not implement I0 */ ]
|
||||
var _ = f0[float64 /* ERROR does not satisfy I0 */ ]
|
||||
|
||||
type I01 interface {
|
||||
E0
|
||||
@ -219,9 +219,9 @@ type I01 interface {
|
||||
|
||||
func f01[T I01]() {}
|
||||
var _ = f01[int]
|
||||
var _ = f01[bool /* ERROR does not implement I0 */ ]
|
||||
var _ = f01[bool /* ERROR does not satisfy I0 */ ]
|
||||
var _ = f01[string]
|
||||
var _ = f01[float64 /* ERROR does not implement I0 */ ]
|
||||
var _ = f01[float64 /* ERROR does not satisfy I0 */ ]
|
||||
|
||||
type I012 interface {
|
||||
E0
|
||||
@ -230,10 +230,10 @@ type I012 interface {
|
||||
}
|
||||
|
||||
func f012[T I012]() {}
|
||||
var _ = f012[int /* ERROR cannot implement I012.*empty type set */ ]
|
||||
var _ = f012[bool /* ERROR cannot implement I012.*empty type set */ ]
|
||||
var _ = f012[string /* ERROR cannot implement I012.*empty type set */ ]
|
||||
var _ = f012[float64 /* ERROR cannot implement I012.*empty type set */ ]
|
||||
var _ = f012[int /* ERROR cannot satisfy I012.*empty type set */ ]
|
||||
var _ = f012[bool /* ERROR cannot satisfy I012.*empty type set */ ]
|
||||
var _ = f012[string /* ERROR cannot satisfy I012.*empty type set */ ]
|
||||
var _ = f012[float64 /* ERROR cannot satisfy I012.*empty type set */ ]
|
||||
|
||||
type I12 interface {
|
||||
E1
|
||||
@ -241,9 +241,9 @@ type I12 interface {
|
||||
}
|
||||
|
||||
func f12[T I12]() {}
|
||||
var _ = f12[int /* ERROR does not implement I12 */ ]
|
||||
var _ = f12[bool /* ERROR does not implement I12 */ ]
|
||||
var _ = f12[string /* ERROR does not implement I12 */ ]
|
||||
var _ = f12[int /* ERROR does not satisfy I12 */ ]
|
||||
var _ = f12[bool /* ERROR does not satisfy I12 */ ]
|
||||
var _ = f12[string /* ERROR does not satisfy I12 */ ]
|
||||
var _ = f12[float64]
|
||||
|
||||
type I0_ interface {
|
||||
@ -253,9 +253,9 @@ type I0_ interface {
|
||||
|
||||
func f0_[T I0_]() {}
|
||||
var _ = f0_[int]
|
||||
var _ = f0_[bool /* ERROR does not implement I0_ */ ]
|
||||
var _ = f0_[string /* ERROR does not implement I0_ */ ]
|
||||
var _ = f0_[float64 /* ERROR does not implement I0_ */ ]
|
||||
var _ = f0_[bool /* ERROR does not satisfy I0_ */ ]
|
||||
var _ = f0_[string /* ERROR does not satisfy I0_ */ ]
|
||||
var _ = f0_[float64 /* ERROR does not satisfy I0_ */ ]
|
||||
|
||||
// Using a function instance as a type is an error.
|
||||
var _ f0 // ERROR not a type
|
||||
@ -273,7 +273,7 @@ func gg[T any]() {}
|
||||
func hh[T ~int]() {}
|
||||
|
||||
func _[T none]() {
|
||||
_ = ff[int /* ERROR cannot implement none \(empty type set\) */ ]
|
||||
_ = ff[int /* ERROR cannot satisfy none \(empty type set\) */ ]
|
||||
_ = ff[T] // pathological but ok because T's type set is empty, too
|
||||
_ = gg[int]
|
||||
_ = gg[T]
|
||||
|
@ -97,7 +97,7 @@ func _() {
|
||||
// last.
|
||||
related2(1.2, []float64{})
|
||||
related2(1.0, []int{})
|
||||
related2 /* ERROR does not implement */ (float64(1.0), []int{}) // TODO(gri) fix error position
|
||||
related2 /* ERROR does not satisfy */ (float64(1.0), []int{}) // TODO(gri) fix error position
|
||||
}
|
||||
|
||||
type List[P any] []P
|
||||
|
@ -16,6 +16,6 @@ func f[V interface{}, A, B Box[V]]() {}
|
||||
|
||||
func _() {
|
||||
f[int, Optional[int], Optional[int]]()
|
||||
_ = f[int, Optional[int], Optional /* ERROR does not implement Box */ [string]]
|
||||
_ = f[int, Optional[int], Optional /* ERROR Optional.* does not implement Box.* */ [string]]
|
||||
_ = f[int, Optional[int], Optional /* ERROR does not satisfy Box */ [string]]
|
||||
_ = f[int, Optional[int], Optional /* ERROR Optional.* does not satisfy Box.* */ [string]]
|
||||
}
|
||||
|
@ -12,5 +12,5 @@ type number interface {
|
||||
func f[T number]() {}
|
||||
|
||||
func _() {
|
||||
_ = f[int /* ERROR int does not implement number \(int missing in float64 | ~int32\)*/]
|
||||
_ = f[int /* ERROR int does not satisfy number \(int missing in float64 \| ~int32\)*/]
|
||||
}
|
||||
|
@ -8,10 +8,10 @@ func f1[T any, C chan T | <-chan T](ch C) {}
|
||||
|
||||
func _(ch chan int) { f1(ch) }
|
||||
func _(ch <-chan int) { f1(ch) }
|
||||
func _(ch chan<- int) { f1 /* ERROR chan<- int does not implement chan int \| <-chan int */ (ch) }
|
||||
func _(ch chan<- int) { f1 /* ERROR chan<- int does not satisfy chan int \| <-chan int */ (ch) }
|
||||
|
||||
func f2[T any, C chan T | chan<- T](ch C) {}
|
||||
|
||||
func _(ch chan int) { f2(ch) }
|
||||
func _(ch <-chan int) { f2 /* ERROR <-chan int does not implement chan int \| chan<- int */ (ch) }
|
||||
func _(ch <-chan int) { f2 /* ERROR <-chan int does not satisfy chan int \| chan<- int */ (ch) }
|
||||
func _(ch chan<- int) { f2(ch) }
|
||||
|
@ -15,12 +15,12 @@ func _[P comparable,
|
||||
_ = f[int]
|
||||
_ = f[P]
|
||||
_ = f[Q]
|
||||
_ = f[func /* ERROR does not implement comparable */ ()]
|
||||
_ = f[R /* ERROR R does not implement comparable */ ]
|
||||
_ = f[func /* ERROR does not satisfy comparable */ ()]
|
||||
_ = f[R /* ERROR R does not satisfy comparable */ ]
|
||||
|
||||
_ = g[int]
|
||||
_ = g[P /* ERROR P does not implement interface{interface{comparable; ~int \| ~string} */ ]
|
||||
_ = g[P /* ERROR P does not satisfy interface{interface{comparable; ~int \| ~string} */ ]
|
||||
_ = g[Q]
|
||||
_ = g[func /* ERROR func\(\) does not implement interface{interface{comparable; ~int \| ~string}} */ ()]
|
||||
_ = g[R /* ERROR R does not implement interface{interface{comparable; ~int \| ~string} */ ]
|
||||
_ = g[func /* ERROR func\(\) does not satisfy interface{interface{comparable; ~int \| ~string}} */ ()]
|
||||
_ = g[R /* ERROR R does not satisfy interface{interface{comparable; ~int \| ~string} */ ]
|
||||
}
|
||||
|
@ -8,8 +8,8 @@ func f[P int](P) {}
|
||||
|
||||
func _() {
|
||||
_ = f[int]
|
||||
_ = f[[ /* ERROR \[\]int does not implement int */ ]int]
|
||||
_ = f[[ /* ERROR \[\]int does not satisfy int */ ]int]
|
||||
|
||||
f(0)
|
||||
f/* ERROR \[\]int does not implement int */ ([]int{})
|
||||
f/* ERROR \[\]int does not satisfy int */ ([]int{})
|
||||
}
|
||||
|
@ -17,7 +17,7 @@ func _() {
|
||||
_ = f2[myInt]
|
||||
_ = f2[myFloat /* ERROR possibly missing ~ for float64 in constraint ~int \| string \| float64 */]
|
||||
var x myInt
|
||||
f3 /* ERROR myInt does not implement int \(possibly missing ~ for int in constraint int\) */ (x)
|
||||
f3 /* ERROR myInt does not satisfy int \(possibly missing ~ for int in constraint int\) */ (x)
|
||||
}
|
||||
|
||||
// test case from the issue
|
||||
@ -33,5 +33,5 @@ func Map[S SliceConstraint[E], E any](s S, f func(E) E) S {
|
||||
type MySlice []int
|
||||
|
||||
func f(s MySlice) {
|
||||
Map[MySlice /* ERROR MySlice does not implement SliceConstraint\[int\] \(possibly missing ~ for \[\]int in constraint SliceConstraint\[int\]\) */, int](s, nil)
|
||||
Map[MySlice /* ERROR MySlice does not satisfy SliceConstraint\[int\] \(possibly missing ~ for \[\]int in constraint SliceConstraint\[int\]\) */, int](s, nil)
|
||||
}
|
||||
|
@ -17,7 +17,7 @@ func g[_ interface{ C }]() {}
|
||||
func h[_ C | int]() {}
|
||||
|
||||
func _() {
|
||||
_ = f[int /* ERROR cannot implement C \(empty type set\) */]
|
||||
_ = g[int /* ERROR cannot implement interface{C} \(empty type set\) */]
|
||||
_ = f[int /* ERROR cannot satisfy C \(empty type set\) */]
|
||||
_ = g[int /* ERROR cannot satisfy interface{C} \(empty type set\) */]
|
||||
_ = h[int]
|
||||
}
|
||||
|
@ -25,8 +25,8 @@ func f0t[P ~struct{f int}](p P) {
|
||||
var _ = f0[Sf]
|
||||
var _ = f0t[Sf]
|
||||
|
||||
var _ = f0[Sm /* ERROR does not implement */ ]
|
||||
var _ = f0t[Sm /* ERROR does not implement */ ]
|
||||
var _ = f0[Sm /* ERROR does not satisfy */ ]
|
||||
var _ = f0t[Sm /* ERROR does not satisfy */ ]
|
||||
|
||||
func f1[P interface{ Sf; m() }](p P) {
|
||||
_ = p.f // ERROR p\.f undefined
|
||||
@ -35,7 +35,7 @@ func f1[P interface{ Sf; m() }](p P) {
|
||||
}
|
||||
|
||||
var _ = f1[Sf /* ERROR missing method m */ ]
|
||||
var _ = f1[Sm /* ERROR does not implement */ ]
|
||||
var _ = f1[Sm /* ERROR does not satisfy */ ]
|
||||
|
||||
type Sm struct {}
|
||||
|
||||
|
@ -13,16 +13,16 @@ type T interface{ m() }
|
||||
|
||||
func _[P comparable, Q ~int, R any]() {
|
||||
_ = f1[int]
|
||||
_ = f1[T /* ERROR T does not implement comparable */ ]
|
||||
_ = f1[any /* ERROR any does not implement comparable */ ]
|
||||
_ = f1[T /* ERROR T does not satisfy comparable */ ]
|
||||
_ = f1[any /* ERROR any does not satisfy comparable */ ]
|
||||
_ = f1[P]
|
||||
_ = f1[Q]
|
||||
_ = f1[R /* ERROR R does not implement comparable */]
|
||||
_ = f1[R /* ERROR R does not satisfy comparable */]
|
||||
|
||||
_ = f2[int]
|
||||
_ = f2[T /* ERROR T does not implement comparable */ ]
|
||||
_ = f2[any /* ERROR any does not implement comparable */ ]
|
||||
_ = f2[T /* ERROR T does not satisfy comparable */ ]
|
||||
_ = f2[any /* ERROR any does not satisfy comparable */ ]
|
||||
_ = f2[P]
|
||||
_ = f2[Q]
|
||||
_ = f2[R /* ERROR R does not implement comparable */]
|
||||
_ = f2[R /* ERROR R does not satisfy comparable */]
|
||||
}
|
||||
|
@ -21,7 +21,7 @@ type numericAbs[T Numeric] interface {
|
||||
|
||||
// AbsDifference computes the absolute value of the difference of
|
||||
// a and b, where the absolute value is determined by the Abs method.
|
||||
func absDifference[T numericAbs[T /* ERROR T does not implement Numeric */]](a, b T) T {
|
||||
func absDifference[T numericAbs[T /* ERROR T does not satisfy Numeric */]](a, b T) T {
|
||||
// Field accesses are not permitted for now. Keep an error so
|
||||
// we can find and fix this code once the situation changes.
|
||||
return a.Value // ERROR a\.Value undefined
|
||||
@ -33,15 +33,15 @@ func absDifference[T numericAbs[T /* ERROR T does not implement Numeric */]](a,
|
||||
// The second example from the issue.
|
||||
type T[P int] struct{ f P }
|
||||
|
||||
func _[P T[P /* ERROR "P does not implement int" */ ]]() {}
|
||||
func _[P T[P /* ERROR "P does not satisfy int" */ ]]() {}
|
||||
|
||||
// Additional tests
|
||||
func _[P T[T /* ERROR "T\[P\] does not implement int" */ [P /* ERROR "P does not implement int" */ ]]]() {}
|
||||
func _[P T[Q /* ERROR "Q does not implement int" */ ], Q T[P /* ERROR "P does not implement int" */ ]]() {}
|
||||
func _[P T[T /* ERROR "T\[P\] does not satisfy int" */ [P /* ERROR "P does not satisfy int" */ ]]]() {}
|
||||
func _[P T[Q /* ERROR "Q does not satisfy int" */ ], Q T[P /* ERROR "P does not satisfy int" */ ]]() {}
|
||||
func _[P T[Q], Q int]() {}
|
||||
|
||||
type C[P comparable] struct{ f P }
|
||||
func _[P C[C[P]]]() {}
|
||||
func _[P C[C /* ERROR "C\[Q\] does not implement comparable" */ [Q /* ERROR "Q does not implement comparable" */]], Q func()]() {}
|
||||
func _[P C[C /* ERROR "C\[Q\] does not satisfy comparable" */ [Q /* ERROR "Q does not satisfy comparable" */]], Q func()]() {}
|
||||
func _[P [10]C[P]]() {}
|
||||
func _[P struct{ f C[C[P]]}]() {}
|
||||
|
@ -14,13 +14,13 @@ type S3 struct{ x [10]interface{ m() } }
|
||||
|
||||
func _[P1 comparable, P2 S2]() {
|
||||
_ = f[S1]
|
||||
_ = f[S2 /* ERROR S2 does not implement comparable */ ]
|
||||
_ = f[S3 /* ERROR S3 does not implement comparable */ ]
|
||||
_ = f[S2 /* ERROR S2 does not satisfy comparable */ ]
|
||||
_ = f[S3 /* ERROR S3 does not satisfy comparable */ ]
|
||||
|
||||
type L1 struct { x P1 }
|
||||
type L2 struct { x P2 }
|
||||
_ = f[L1]
|
||||
_ = f[L2 /* ERROR L2 does not implement comparable */ ]
|
||||
_ = f[L2 /* ERROR L2 does not satisfy comparable */ ]
|
||||
}
|
||||
|
||||
|
||||
@ -41,7 +41,7 @@ func NewSetFromSlice[T comparable](items []T) *Set[T] {
|
||||
type T struct{ x any }
|
||||
|
||||
func main() {
|
||||
NewSetFromSlice /* ERROR T does not implement comparable */ ([]T{
|
||||
NewSetFromSlice /* ERROR T does not satisfy comparable */ ([]T{
|
||||
{"foo"},
|
||||
{5},
|
||||
})
|
||||
|
@ -12,7 +12,7 @@ func g[M map[K]V, K comparable, V any](M) {}
|
||||
func _[M1 ~map[K]V, M2 map[K]V, K comparable, V any]() {
|
||||
var m1 M1
|
||||
f(m1)
|
||||
g /* ERROR M1 does not implement map\[K\]V */ (m1) // M1 has tilde
|
||||
g /* ERROR M1 does not satisfy map\[K\]V */ (m1) // M1 has tilde
|
||||
|
||||
var m2 M2
|
||||
f(m2)
|
||||
@ -20,5 +20,5 @@ func _[M1 ~map[K]V, M2 map[K]V, K comparable, V any]() {
|
||||
|
||||
var m3 Map
|
||||
f(m3)
|
||||
g /* ERROR Map does not implement map\[string\]int */ (m3) // M in g does not have tilde
|
||||
g /* ERROR Map does not satisfy map\[string\]int */ (m3) // M in g does not have tilde
|
||||
}
|
||||
|
@ -49,6 +49,6 @@ func f[T interface{comparable; []byte|string}](x T) {
|
||||
}
|
||||
|
||||
func _(s []byte) {
|
||||
f /* ERROR \[\]byte does not implement interface{comparable; \[\]byte \| string} */ (s)
|
||||
_ = f[[ /* ERROR does not implement */ ]byte]
|
||||
f /* ERROR \[\]byte does not satisfy interface{comparable; \[\]byte \| string} */ (s)
|
||||
_ = f[[ /* ERROR does not satisfy */ ]byte]
|
||||
}
|
||||
|
@ -17,13 +17,13 @@ func G1[T C1](t T) { _ = t == t }
|
||||
func G2[T C2](t T) { _ = t == t }
|
||||
|
||||
func F1[V [2]any](v V) {
|
||||
_ = G1[V /* ERROR "V does not implement comparable" */]
|
||||
_ = G1[V /* ERROR "V does not satisfy comparable" */]
|
||||
_ = G1[[2]any]
|
||||
_ = G1[int]
|
||||
}
|
||||
|
||||
func F2[V [2]any](v V) {
|
||||
_ = G2[V /* ERROR "V does not implement C2" */]
|
||||
_ = G2[[ /* ERROR "\[2\]any does not implement C2 \(\[2\]any missing in int\)" */ 2]any]
|
||||
_ = G2[V /* ERROR "V does not satisfy C2" */]
|
||||
_ = G2[[ /* ERROR "\[2\]any does not satisfy C2 \(\[2\]any missing in int\)" */ 2]any]
|
||||
_ = G2[int]
|
||||
}
|
||||
|
12
src/internal/types/testdata/spec/comparable.go
vendored
12
src/internal/types/testdata/spec/comparable.go
vendored
@ -11,16 +11,16 @@ type T interface{ m() }
|
||||
|
||||
func _[P comparable, Q ~int, R any]() {
|
||||
_ = f1[int]
|
||||
_ = f1[T /* T does implement comparable */]
|
||||
_ = f1[any /* any does implement comparable */]
|
||||
_ = f1[T /* T does satisfy comparable */]
|
||||
_ = f1[any /* any does satisfy comparable */]
|
||||
_ = f1[P]
|
||||
_ = f1[Q]
|
||||
_ = f1[R /* ERROR R does not implement comparable */]
|
||||
_ = f1[R /* ERROR R does not satisfy comparable */]
|
||||
|
||||
_ = f2[int]
|
||||
_ = f2[T /* T does implement comparable */]
|
||||
_ = f2[any /* any does implement comparable */]
|
||||
_ = f2[T /* T does satisfy comparable */]
|
||||
_ = f2[any /* any does satisfy comparable */]
|
||||
_ = f2[P]
|
||||
_ = f2[Q]
|
||||
_ = f2[R /* ERROR R does not implement comparable */]
|
||||
_ = f2[R /* ERROR R does not satisfy comparable */]
|
||||
}
|
||||
|
@ -13,16 +13,16 @@ type T interface{ m() }
|
||||
|
||||
func _[P comparable, Q ~int, R any]() {
|
||||
_ = f1[int]
|
||||
_ = f1[T /* ERROR T to implement comparable requires go1\.20 or later */]
|
||||
_ = f1[any /* ERROR any to implement comparable requires go1\.20 or later */]
|
||||
_ = f1[T /* ERROR T to satisfy comparable requires go1\.20 or later */]
|
||||
_ = f1[any /* ERROR any to satisfy comparable requires go1\.20 or later */]
|
||||
_ = f1[P]
|
||||
_ = f1[Q]
|
||||
_ = f1[R /* ERROR R does not implement comparable */]
|
||||
_ = f1[R /* ERROR R does not satisfy comparable */]
|
||||
|
||||
_ = f2[int]
|
||||
_ = f2[T /* ERROR T to implement comparable requires go1\.20 or later */]
|
||||
_ = f2[any /* ERROR any to implement comparable requires go1\.20 or later */]
|
||||
_ = f2[T /* ERROR T to satisfy comparable requires go1\.20 or later */]
|
||||
_ = f2[any /* ERROR any to satisfy comparable requires go1\.20 or later */]
|
||||
_ = f2[P]
|
||||
_ = f2[Q]
|
||||
_ = f2[R /* ERROR R does not implement comparable */]
|
||||
_ = f2[R /* ERROR R does not satisfy comparable */]
|
||||
}
|
||||
|
@ -13,16 +13,16 @@ type T interface{ m() }
|
||||
|
||||
func _[P comparable, Q ~int, R any]() {
|
||||
_ = f1[int]
|
||||
_ = f1[T /* ERROR T does not implement comparable */]
|
||||
_ = f1[any /* ERROR any does not implement comparable */]
|
||||
_ = f1[T /* ERROR T does not satisfy comparable */]
|
||||
_ = f1[any /* ERROR any does not satisfy comparable */]
|
||||
_ = f1[P]
|
||||
_ = f1[Q]
|
||||
_ = f1[R /* ERROR R does not implement comparable */]
|
||||
_ = f1[R /* ERROR R does not satisfy comparable */]
|
||||
|
||||
_ = f2[int]
|
||||
_ = f2[T /* ERROR T does not implement comparable */]
|
||||
_ = f2[any /* ERROR any does not implement comparable */]
|
||||
_ = f2[T /* ERROR T does not satisfy comparable */]
|
||||
_ = f2[any /* ERROR any does not satisfy comparable */]
|
||||
_ = f2[P]
|
||||
_ = f2[Q]
|
||||
_ = f2[R /* ERROR R does not implement comparable */]
|
||||
_ = f2[R /* ERROR R does not satisfy comparable */]
|
||||
}
|
||||
|
@ -7,5 +7,5 @@ package b
|
||||
import "./a"
|
||||
|
||||
func init() {
|
||||
a.F[func()]() // ERROR "does not implement comparable"
|
||||
a.F[func()]() // ERROR "does not satisfy comparable"
|
||||
}
|
||||
|
@ -28,11 +28,11 @@ func main() {
|
||||
}
|
||||
|
||||
const want2 = "ay"
|
||||
if got := a.Min[string]("bb", "ay"); got != want2 { // ERROR "string does not implement"
|
||||
if got := a.Min[string]("bb", "ay"); got != want2 { // ERROR "string does not satisfy"
|
||||
panic(fmt.Sprintf("got %d, want %d", got, want2))
|
||||
}
|
||||
|
||||
if got := a.Min("bb", "ay"); got != want2 { // ERROR "string does not implement"
|
||||
if got := a.Min("bb", "ay"); got != want2 { // ERROR "string does not satisfy"
|
||||
panic(fmt.Sprintf("got %d, want %d", got, want2))
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user