diff options
author | Robert Griesemer <gri@golang.org> | 2022-02-20 12:58:21 -0800 |
---|---|---|
committer | Robert Griesemer <gri@golang.org> | 2022-02-23 20:51:26 +0000 |
commit | 163da6feb525a98dab5c1f01d81b2c705ead51ea (patch) | |
tree | 0ca6c9eff2957fb140b428be5d5c9f768d4401f0 /src/go/types/predicates.go | |
parent | e534907f65f5a3eda47a069ea0aab33306c1d616 (diff) | |
download | go-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.go | 11 |
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 } |