From 738cebb1747335c182af64614041ceb2b2303f74 Mon Sep 17 00:00:00 2001 From: Robert Griesemer Date: Tue, 14 Sep 2021 13:23:37 -0700 Subject: cmd/compile/internal/types2: implement Identical for *Union types 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 Run-TryBot: Robert Griesemer TryBot-Result: Go Bot Reviewed-by: Robert Findley --- src/cmd/compile/internal/types2/api_test.go | 42 +++++++++++++++++++++++++++ src/cmd/compile/internal/types2/predicates.go | 7 +++++ 2 files changed, 49 insertions(+) diff --git a/src/cmd/compile/internal/types2/api_test.go b/src/cmd/compile/internal/types2/api_test.go index 3ec0d78a23..5a20738631 100644 --- a/src/cmd/compile/internal/types2/api_test.go +++ b/src/cmd/compile/internal/types2/api_test.go @@ -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) diff --git a/src/cmd/compile/internal/types2/predicates.go b/src/cmd/compile/internal/types2/predicates.go index aa797fccc7..74ad3da72c 100644 --- a/src/cmd/compile/internal/types2/predicates.go +++ b/src/cmd/compile/internal/types2/predicates.go @@ -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: -- cgit v1.2.3-54-g00ecf