]> Cypherpunks repositories - gostls13.git/commitdiff
cmd/compile/internal/types2: implement Identical for *Union types
authorRobert Griesemer <gri@golang.org>
Tue, 14 Sep 2021 20:23:37 +0000 (13:23 -0700)
committerRobert Griesemer <gri@golang.org>
Wed, 15 Sep 2021 03:29:43 +0000 (03:29 +0000)
This is a clean port of CL 349413 from go/types to types2.

Change-Id: I18bad5e29b1e719b30a73fb2aa32fe252538496e
Reviewed-on: https://go-review.googlesource.com/c/go/+/349992
Trust: Robert Griesemer <gri@golang.org>
Run-TryBot: Robert Griesemer <gri@golang.org>
TryBot-Result: Go Bot <gobot@golang.org>
Reviewed-by: Robert Findley <rfindley@google.com>
src/cmd/compile/internal/types2/api_test.go
src/cmd/compile/internal/types2/predicates.go

index 3ec0d78a2354d5fbcc67bf50f7d2cc23756ca4f7..5a207386318af1f5b65a3ca406e0542d16074ed0 100644 (file)
@@ -1645,6 +1645,48 @@ func TestIdentical_issue15173(t *testing.T) {
        }
 }
 
+func TestIdenticalUnions(t *testing.T) {
+       tname := NewTypeName(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)"
        f, err := parseSrc("issue15305.go", src)
index aa797fccc70476bb449ab0e77a480578f3e8cf5f..74ad3da72cb35c91bd2a02a3013cc8c65977963c 100644 (file)
@@ -225,6 +225,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, nopos, x)
+                       yset := computeUnionTypeSet(nil, 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: