cmd/compile/internal/types2: define Identical for instances

Instantiation of parameterized types may occur in other packages, so we
need an intrinsic notion of type identity for instances.

Add the natural definition: two instances are identical if their bases
and type arguments are identical.

Type unification was already considering type arguments, but has some
inaccurate logic with respect to objects. This will be addressed in a
follow-up CL.

Change-Id: Ib2ce67c05de65eb302ee588cc40c89c60018da50
Reviewed-on: https://go-review.googlesource.com/c/go/+/341856
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>
This commit is contained in:
Rob Findley 2021-08-11 11:45:11 -04:00 committed by Robert Findley
parent fc27eb50ff
commit 50f4ebbdd3
3 changed files with 47 additions and 5 deletions

View file

@ -1879,3 +1879,28 @@ func TestInstantiate(t *testing.T) {
t.Fatalf("unexpected result type: %s points to %s", res, p)
}
}
func TestInstanceIdentity(t *testing.T) {
imports := make(testImporter)
conf := Config{Importer: imports}
makePkg := func(src string) {
f, err := parseSrc("", src)
if err != nil {
t.Fatal(err)
}
name := f.PkgName.Value
pkg, err := conf.Check(name, []*syntax.File{f}, nil)
if err != nil {
t.Fatal(err)
}
imports[name] = pkg
}
makePkg(genericPkg + `lib; type T[P any] struct{}`)
makePkg(genericPkg + `a; import "generic_lib"; var A generic_lib.T[int]`)
makePkg(genericPkg + `b; import "generic_lib"; var B generic_lib.T[int]`)
a := imports["generic_a"].Scope().Lookup("A")
b := imports["generic_b"].Scope().Lookup("B")
if !Identical(a.Type(), b.Type()) {
t.Errorf("mismatching types: a.A: %s, b.B: %s", a.Type(), b.Type())
}
}

View file

@ -304,6 +304,28 @@ func identical(x, y Type, cmpTags bool, p *ifacePair) bool {
if y, ok := y.(*Named); ok {
x.expand(nil)
y.expand(nil)
xargs := x.TArgs()
yargs := y.TArgs()
if len(xargs) != len(yargs) {
return false
}
if len(xargs) > 0 {
// Instances are identical if their original type and type arguments
// are identical.
if !Identical(x.orig, y.orig) {
return false
}
for i, xa := range xargs {
if !Identical(xa, yargs[i]) {
return false
}
}
return true
}
// TODO(gri) Why is x == y not sufficient? And if it is,
// we can just return false here because x == y
// is caught in the very beginning of this function.

View file

@ -426,11 +426,6 @@ func (u *unifier) nify(x, y Type, p *ifacePair) bool {
}
case *Named:
// Two named types are identical if their type names originate
// in the same type declaration.
// if y, ok := y.(*Named); ok {
// return x.obj == y.obj
// }
if y, ok := y.(*Named); ok {
x.expand(nil)
y.expand(nil)