]> Cypherpunks.ru repositories - gostls13.git/commitdiff
go/types: implement Identical for *Union types
authorRobert Findley <rfindley@google.com>
Sun, 12 Sep 2021 18:33:04 +0000 (14:33 -0400)
committerRobert Findley <rfindley@google.com>
Wed, 15 Sep 2021 00:05:40 +0000 (00:05 +0000)
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>
src/go/types/api_test.go
src/go/types/predicates.go

index 49c054bd7db436e3ac89225eb1c4133d9bbaf208..4472748685e8655b183f9f1e07ec8a60b23e55b9 100644 (file)
@@ -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()
index 9aa565b68a6f594931def8509b1d3cef3252c590..a5d4be9bcc4680fc7428a556ce1b504e0ed0a0da 100644 (file)
@@ -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: