aboutsummaryrefslogtreecommitdiff
path: root/src/go/types/predicates.go
diff options
context:
space:
mode:
authorRobert Griesemer <gri@golang.org>2022-02-20 12:58:21 -0800
committerRobert Griesemer <gri@golang.org>2022-02-23 20:51:26 +0000
commit163da6feb525a98dab5c1f01d81b2c705ead51ea (patch)
tree0ca6c9eff2957fb140b428be5d5c9f768d4401f0 /src/go/types/predicates.go
parente534907f65f5a3eda47a069ea0aab33306c1d616 (diff)
downloadgo-163da6feb525a98dab5c1f01d81b2c705ead51ea.tar.gz
go-163da6feb525a98dab5c1f01d81b2c705ead51ea.zip
go/types, types2: add "dynamic" flag to comparable predicate
A type implements a comparable interface only if the type is statically known to be comparable. Specifically, a type cannot contain (component) interfaces that are not statically known to be comparable. This CL adds a flag "dynamic" to the comparable predicate to control whether interfaces are always (dynamically) comparable. Set the flag to true when testing for (traditional) Go comparability; set the flag to false when testing whether a type implements the comparable interface. Fixes #51257. Change-Id: If22bc047ee59337deb2e7844b8f488d67e5c5530 Reviewed-on: https://go-review.googlesource.com/c/go/+/387055 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/go/types/predicates.go')
-rw-r--r--src/go/types/predicates.go11
1 files changed, 6 insertions, 5 deletions
diff --git a/src/go/types/predicates.go b/src/go/types/predicates.go
index 14e99bf426..0360f27ee6 100644
--- a/src/go/types/predicates.go
+++ b/src/go/types/predicates.go
@@ -104,11 +104,12 @@ func isGeneric(t Type) bool {
// Comparable reports whether values of type T are comparable.
func Comparable(T Type) bool {
- return comparable(T, nil, nil)
+ return comparable(T, true, nil, nil)
}
+// If dynamic is set, non-type parameter interfaces are always comparable.
// If reportf != nil, it may be used to report why T is not comparable.
-func comparable(T Type, seen map[Type]bool, reportf func(string, ...interface{})) bool {
+func comparable(T Type, dynamic bool, seen map[Type]bool, reportf func(string, ...interface{})) bool {
if seen[T] {
return true
}
@@ -126,7 +127,7 @@ func comparable(T Type, seen map[Type]bool, reportf func(string, ...interface{})
return true
case *Struct:
for _, f := range t.fields {
- if !comparable(f.typ, seen, nil) {
+ if !comparable(f.typ, dynamic, seen, nil) {
if reportf != nil {
reportf("struct containing %s cannot be compared", f.typ)
}
@@ -135,7 +136,7 @@ func comparable(T Type, seen map[Type]bool, reportf func(string, ...interface{})
}
return true
case *Array:
- if !comparable(t.elem, seen, nil) {
+ if !comparable(t.elem, dynamic, seen, nil) {
if reportf != nil {
reportf("%s cannot be compared", t)
}
@@ -143,7 +144,7 @@ func comparable(T Type, seen map[Type]bool, reportf func(string, ...interface{})
}
return true
case *Interface:
- return !isTypeParam(T) || t.typeSet().IsComparable(seen)
+ return dynamic && !isTypeParam(T) || t.typeSet().IsComparable(seen)
}
return false
}