aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRobert Findley <rfindley@google.com>2021-09-12 14:33:04 -0400
committerRobert Findley <rfindley@google.com>2021-09-15 00:05:40 +0000
commit0bb40b08c4884952d7facce3135ff9e50847763f (patch)
tree577fa213e35b251afbbfbd145c37e24d97e95810
parentcb4e1de0213c836983d1b441386c53e1a66e1b0a (diff)
downloadgo-0bb40b08c4884952d7facce3135ff9e50847763f.tar.gz
go-0bb40b08c4884952d7facce3135ff9e50847763f.zip
go/types: implement Identical for *Union types
This aligns with the API proposal (#47916). Change-Id: I732e5b107e729718ed37e053ad3f434993a97ecd Reviewed-on: https://go-review.googlesource.com/c/go/+/349413 Trust: Robert Findley <rfindley@google.com> Run-TryBot: Robert Findley <rfindley@google.com> TryBot-Result: Go Bot <gobot@golang.org> Reviewed-by: Robert Griesemer <gri@golang.org>
-rw-r--r--src/go/types/api_test.go42
-rw-r--r--src/go/types/predicates.go9
2 files changed, 51 insertions, 0 deletions
diff --git a/src/go/types/api_test.go b/src/go/types/api_test.go
index 49c054bd7d..4472748685 100644
--- a/src/go/types/api_test.go
+++ b/src/go/types/api_test.go
@@ -1621,6 +1621,48 @@ func TestIdentical_issue15173(t *testing.T) {
}
}
+func TestIdenticalUnions(t *testing.T) {
+ tname := NewTypeName(token.NoPos, nil, "myInt", nil)
+ myInt := NewNamed(tname, Typ[Int], nil)
+ tmap := map[string]*Term{
+ "int": NewTerm(false, Typ[Int]),
+ "~int": NewTerm(true, Typ[Int]),
+ "string": NewTerm(false, Typ[String]),
+ "~string": NewTerm(true, Typ[String]),
+ "myInt": NewTerm(false, myInt),
+ }
+ makeUnion := func(s string) *Union {
+ parts := strings.Split(s, "|")
+ var terms []*Term
+ for _, p := range parts {
+ term := tmap[p]
+ if term == nil {
+ t.Fatalf("missing term %q", p)
+ }
+ terms = append(terms, term)
+ }
+ return NewUnion(terms)
+ }
+ for _, test := range []struct {
+ x, y string
+ want bool
+ }{
+ // These tests are just sanity checks. The tests for type sets and
+ // interfaces provide much more test coverage.
+ {"int|~int", "~int", true},
+ {"myInt|~int", "~int", true},
+ {"int|string", "string|int", true},
+ {"int|int|string", "string|int", true},
+ {"myInt|string", "int|string", false},
+ } {
+ x := makeUnion(test.x)
+ y := makeUnion(test.y)
+ if got := Identical(x, y); got != test.want {
+ t.Errorf("Identical(%v, %v) = %t", test.x, test.y, got)
+ }
+ }
+}
+
func TestIssue15305(t *testing.T) {
const src = "package p; func f() int16; var _ = f(undef)"
fset := token.NewFileSet()
diff --git a/src/go/types/predicates.go b/src/go/types/predicates.go
index 9aa565b68a..a5d4be9bcc 100644
--- a/src/go/types/predicates.go
+++ b/src/go/types/predicates.go
@@ -6,6 +6,8 @@
package types
+import "go/token"
+
// isNamed reports whether typ has a name.
// isNamed may be called with types that are not fully set up.
func isNamed(typ Type) bool {
@@ -225,6 +227,13 @@ func identical(x, y Type, cmpTags bool, p *ifacePair) bool {
identical(x.results, y.results, cmpTags, p)
}
+ case *Union:
+ if y, _ := y.(*Union); y != nil {
+ xset := computeUnionTypeSet(nil, token.NoPos, x)
+ yset := computeUnionTypeSet(nil, token.NoPos, y)
+ return xset.terms.equal(yset.terms)
+ }
+
case *Interface:
// Two interface types are identical if they describe the same type sets.
// With the existing implementation restriction, this simplifies to: