diff --git a/src/cmd/compile/internal/types2/api_test.go b/src/cmd/compile/internal/types2/api_test.go index dfa4de1175..be05d06fd0 100644 --- a/src/cmd/compile/internal/types2/api_test.go +++ b/src/cmd/compile/internal/types2/api_test.go @@ -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()) + } +} diff --git a/src/cmd/compile/internal/types2/predicates.go b/src/cmd/compile/internal/types2/predicates.go index 070a0b3932..3c883e1ab5 100644 --- a/src/cmd/compile/internal/types2/predicates.go +++ b/src/cmd/compile/internal/types2/predicates.go @@ -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. diff --git a/src/cmd/compile/internal/types2/unify.go b/src/cmd/compile/internal/types2/unify.go index 28f9cf751c..710fc51b53 100644 --- a/src/cmd/compile/internal/types2/unify.go +++ b/src/cmd/compile/internal/types2/unify.go @@ -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)