aboutsummaryrefslogtreecommitdiff
path: root/src/cmd/compile
diff options
context:
space:
mode:
authorRobert Griesemer <gri@golang.org>2021-12-15 16:13:05 -0800
committerRobert Findley <rfindley@google.com>2021-12-20 15:13:38 +0000
commita2004de0885cc3796fed6dff54678efb8ffa4d01 (patch)
tree94a1dd154ece44bad4381d578f7871a3aef7a041 /src/cmd/compile
parent87b2a54827b5a845e9b29ede9414495e3e869f2e (diff)
downloadgo-a2004de0885cc3796fed6dff54678efb8ffa4d01.tar.gz
go-a2004de0885cc3796fed6dff54678efb8ffa4d01.zip
go/types, types2: delay "does not satisfy comparable" error until needed
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>
Diffstat (limited to 'src/cmd/compile')
-rw-r--r--src/cmd/compile/internal/types2/instantiate.go25
-rw-r--r--src/cmd/compile/internal/types2/testdata/check/issues.go26
-rw-r--r--src/cmd/compile/internal/types2/testdata/fixedbugs/issue47411.go26
-rw-r--r--src/cmd/compile/internal/types2/testdata/fixedbugs/issue49112.go215
4 files changed, 32 insertions, 20 deletions
diff --git a/src/cmd/compile/internal/types2/instantiate.go b/src/cmd/compile/internal/types2/instantiate.go
index cda6c7baf4..b2e1087c41 100644
--- a/src/cmd/compile/internal/types2/instantiate.go
+++ b/src/cmd/compile/internal/types2/instantiate.go
@@ -192,17 +192,7 @@ func (check *Checker) implements(V, T Type, qf Qualifier) error {
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!
@@ -220,10 +210,17 @@ func (check *Checker) implements(V, T Type, qf Qualifier) error {
}
}
+ // 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
@@ -234,7 +231,7 @@ func (check *Checker) implements(V, T Type, qf Qualifier) error {
// 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.
@@ -262,5 +259,5 @@ func (check *Checker) implements(V, T Type, qf Qualifier) error {
}
}
- return nil
+ return pending
}
diff --git a/src/cmd/compile/internal/types2/testdata/check/issues.go2 b/src/cmd/compile/internal/types2/testdata/check/issues.go2
index 76f9cc5010..5b6eebd4fd 100644
--- a/src/cmd/compile/internal/types2/testdata/check/issues.go2
+++ b/src/cmd/compile/internal/types2/testdata/check/issues.go2
@@ -58,7 +58,7 @@ func _() {
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.
@@ -74,8 +74,8 @@ func (u T2[U]) Add1() U {
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 _() {
diff --git a/src/cmd/compile/internal/types2/testdata/fixedbugs/issue47411.go2 b/src/cmd/compile/internal/types2/testdata/fixedbugs/issue47411.go2
index ce5db0a615..3f405baed7 100644
--- a/src/cmd/compile/internal/types2/testdata/fixedbugs/issue47411.go2
+++ b/src/cmd/compile/internal/types2/testdata/fixedbugs/issue47411.go2
@@ -16,11 +16,11 @@ func _[P comparable,
_ = 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} */ ]
}
diff --git a/src/cmd/compile/internal/types2/testdata/fixedbugs/issue49112.go2 b/src/cmd/compile/internal/types2/testdata/fixedbugs/issue49112.go2
new file mode 100644
index 0000000000..0efc9066ec
--- /dev/null
+++ b/src/cmd/compile/internal/types2/testdata/fixedbugs/issue49112.go2
@@ -0,0 +1,15 @@
+// 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{})
+}