diff options
author | Robert Griesemer <gri@golang.org> | 2021-12-15 16:13:05 -0800 |
---|---|---|
committer | Robert Findley <rfindley@google.com> | 2021-12-20 15:13:38 +0000 |
commit | a2004de0885cc3796fed6dff54678efb8ffa4d01 (patch) | |
tree | 94a1dd154ece44bad4381d578f7871a3aef7a041 /src/cmd/compile | |
parent | 87b2a54827b5a845e9b29ede9414495e3e869f2e (diff) | |
download | go-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')
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{}) +} |