]> Cypherpunks repositories - gostls13.git/commitdiff
cmd/compile/internal/types2: define Identical for instances
authorRob Findley <rfindley@google.com>
Wed, 11 Aug 2021 15:45:11 +0000 (11:45 -0400)
committerRobert Findley <rfindley@google.com>
Sat, 14 Aug 2021 15:14:43 +0000 (15:14 +0000)
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>
src/cmd/compile/internal/types2/api_test.go
src/cmd/compile/internal/types2/predicates.go
src/cmd/compile/internal/types2/unify.go

index dfa4de11750c5f7e93f647c1cd4439907331afb1..be05d06fd0acec9ce58d9f5aec2469c87458e24b 100644 (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())
+       }
+}
index 070a0b3932028e9a6d31f3a9e98dfa31a2578648..3c883e1ab5c062d9488042b4068412dbd1646c74 100644 (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.
index 28f9cf751c0ac9c0e98e19fec4f882a8cba43ab2..710fc51b53fe3bfbd0a3a165ba7bc800f4237648 100644 (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)