Fixes #49112.
Change-Id: I8effbca7bcbb257b18fd4d3d1914fd10d4afaaae
Reviewed-on: https://go-review.googlesource.com/c/go/+/372594
Trust: Robert Griesemer <gri@golang.org>
Run-TryBot: Robert Griesemer <gri@golang.org>
TryBot-Result: Gopher Robot <gobot@golang.org>
Reviewed-by: Robert Findley <rfindley@google.com>
return errorf("cannot implement %s (empty type set)", T)
}
- // If T is comparable, V must be comparable.
- // TODO(gri) the error messages could be better, here
- if Ti.IsComparable() && !Comparable(V) {
- if Vi != nil && Vi.Empty() {
- return errorf("empty interface %s does not implement %s", V, T)
- }
- return errorf("%s does not implement comparable", V)
- }
-
- // V must implement T (methods)
- // - check only if we have methods
+ // V must implement T's methods, if any.
if Ti.NumMethods() > 0 {
if m, wrong := check.missingMethod(V, Ti, true); m != nil {
// TODO(gri) needs to print updated name to avoid major confusion in error message!
}
}
+ // If T is comparable, V must be comparable.
+ // Remember as a pending error and report only if we don't have a more specific error.
+ var pending error
+ if Ti.IsComparable() && !Comparable(V) {
+ pending = errorf("%s does not implement comparable", V)
+ }
+
// V must also be in the set of types of T, if any.
// Constraints with empty type sets were already excluded above.
if !Ti.typeSet().hasTerms() {
- return nil // nothing to do
+ return pending // nothing to do
}
// If V is itself an interface, each of its possible types must be in the set
// TODO(gri) report which type is missing
return errorf("%s does not implement %s", V, T)
}
- return nil
+ return pending
}
// Otherwise, V's type must be included in the iface type set.
}
}
- return nil
+ return pending
}
type T1[P interface{~uint}] struct{}
func _[P any]() {
- _ = T1[P /* ERROR empty interface P does not implement interface{~uint} */ ]{}
+ _ = T1[P /* ERROR P does not implement interface{~uint} */ ]{}
}
// This is the original (simplified) program causing the same issue.
return u.s + 1
}
-func NewT2[U any]() T2[U /* ERROR empty interface U does not implement Unsigned */ ] {
- return T2[U /* ERROR empty interface U does not implement Unsigned */ ]{}
+func NewT2[U any]() T2[U /* ERROR U does not implement Unsigned */ ] {
+ return T2[U /* ERROR U does not implement Unsigned */ ]{}
}
func _() {
_ = f[P]
_ = f[Q]
_ = f[func( /* ERROR does not implement comparable */ )]
- _ = f[R /* ERROR empty interface R does not implement comparable */ ]
+ _ = f[R /* ERROR R does not implement comparable */ ]
_ = g[int]
_ = g[P /* ERROR P does not implement interface{interface{comparable; ~int\|~string} */ ]
_ = g[Q]
- _ = g[func( /* ERROR does not implement comparable */ )]
- _ = g[R /* ERROR empty interface R does not implement interface{interface{comparable; ~int\|~string} */ ]
+ _ = g[func( /* ERROR func\(\) does not implement interface{interface{comparable; ~int\|~string}} */ )]
+ _ = g[R /* ERROR R does not implement interface{interface{comparable; ~int\|~string} */ ]
}
--- /dev/null
+// Copyright 2021 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[P int](P) {}
+
+func _() {
+ _ = f[int]
+ _ = f[[ /* ERROR \[\]int does not implement int */ ]int]
+
+ f(0)
+ f( /* ERROR \[\]int does not implement int */ []int{})
+}
return errorf("cannot implement %s (empty type set)", T)
}
- // If T is comparable, V must be comparable.
- // TODO(gri) the error messages could be better, here
- if Ti.IsComparable() && !Comparable(V) {
- if Vi != nil && Vi.Empty() {
- return errorf("empty interface %s does not implement %s", V, T)
- }
- return errorf("%s does not implement comparable", V)
- }
-
- // V must implement T (methods)
- // - check only if we have methods
+ // V must implement T's methods, if any.
if Ti.NumMethods() > 0 {
if m, wrong := check.missingMethod(V, Ti, true); m != nil {
// TODO(gri) needs to print updated name to avoid major confusion in error message!
}
}
+ // If T is comparable, V must be comparable.
+ // Remember as a pending error and report only if we don't have a more specific error.
+ var pending error
+ if Ti.IsComparable() && !Comparable(V) {
+ pending = errorf("%s does not implement comparable", V)
+ }
+
// V must also be in the set of types of T, if any.
// Constraints with empty type sets were already excluded above.
if !Ti.typeSet().hasTerms() {
- return nil // nothing to do
+ return pending // nothing to do
}
// If V is itself an interface, each of its possible types must be in the set
// TODO(gri) report which type is missing
return errorf("%s does not implement %s", V, T)
}
- return nil
+ return pending
}
// Otherwise, V's type must be included in the iface type set.
}
}
- return nil
+ return pending
}
type T1[P interface{~uint}] struct{}
func _[P any]() {
- _ = T1[P /* ERROR empty interface P does not implement interface{~uint} */ ]{}
+ _ = T1[P /* ERROR P does not implement interface{~uint} */ ]{}
}
// This is the original (simplified) program causing the same issue.
return u.s + 1
}
-func NewT2[U any]() T2[U /* ERROR empty interface U does not implement Unsigned */ ] {
- return T2[U /* ERROR empty interface U does not implement Unsigned */ ]{}
+func NewT2[U any]() T2[U /* ERROR U does not implement Unsigned */ ] {
+ return T2[U /* ERROR U does not implement Unsigned */ ]{}
}
func _() {
_ = f[P]
_ = f[Q]
_ = f[func /* ERROR does not implement comparable */ ()]
- _ = f[R /* ERROR empty interface R does not implement comparable */ ]
+ _ = f[R /* ERROR R does not implement comparable */ ]
_ = g[int]
_ = g[P /* ERROR P does not implement interface{interface{comparable; ~int\|~string} */ ]
_ = g[Q]
- _ = g[func /* ERROR does not implement comparable */ ()]
- _ = g[R /* ERROR empty interface R does not implement interface{interface{comparable; ~int\|~string} */ ]
+ _ = g[func /* ERROR func\(\) does not implement interface{interface{comparable; ~int\|~string}} */ ()]
+ _ = g[R /* ERROR R does not implement interface{interface{comparable; ~int\|~string} */ ]
}
--- /dev/null
+// Copyright 2021 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[P int](P) {}
+
+func _() {
+ _ = f[int]
+ _ = f[[ /* ERROR \[\]int does not implement int */ ]int]
+
+ f(0)
+ f/* ERROR \[\]int does not implement int */ ([]int{})
+}