]> Cypherpunks.ru repositories - gostls13.git/commitdiff
go/types: define Identical for instances
authorRobert Findley <rfindley@google.com>
Mon, 16 Aug 2021 17:15:47 +0000 (13:15 -0400)
committerRobert Findley <rfindley@google.com>
Mon, 16 Aug 2021 18:44:38 +0000 (18:44 +0000)
This is a port of CL 341856 to go/types. It is adjusted to use the
NumTArgs/TArg API of go/types, which has not yet been ported to types2.

Change-Id: I6faeec027f4ae08634267001f473263703e80c5b
Reviewed-on: https://go-review.googlesource.com/c/go/+/342478
Trust: Robert Findley <rfindley@google.com>
Run-TryBot: Robert Findley <rfindley@google.com>
Reviewed-by: Robert Griesemer <gri@golang.org>
TryBot-Result: Go Bot <gobot@golang.org>

src/go/types/api_test.go
src/go/types/predicates.go
src/go/types/unify.go

index 52c9e5afe8f3beb5f5803e44a7da5b79e5abe9b1..1631215d15bf3fe681cefca5c7fb3a2c1a4e73e5 100644 (file)
@@ -1861,3 +1861,29 @@ 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) {
+               fset := token.NewFileSet()
+               f, err := parser.ParseFile(fset, "", src, 0)
+               if err != nil {
+                       t.Fatal(err)
+               }
+               name := f.Name.Name
+               pkg, err := conf.Check(name, fset, []*ast.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 bd9e53d2bb406a18589a0a5494cbe3d619ad175d..0945dac722908aca36373dc5267207bd1e61dfd4 100644 (file)
@@ -304,6 +304,30 @@ 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 x.NumTArgs() != y.NumTArgs() {
+                               return false
+                       }
+
+                       if nargs := x.NumTArgs(); nargs > 0 {
+                               // Instances are identical if their original type and type arguments
+                               // are identical.
+                               if !Identical(x.orig, y.orig) {
+                                       return false
+                               }
+                               for i := 0; i < nargs; i++ {
+                                       xa := x.TArg(i)
+                                       ya := y.TArg(i)
+                                       if !Identical(xa, ya) {
+                                               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 20cada2e691f8128cda7d8899744442e9c780d42..de87466fe8beb0e71bdc211b1e4b3a338da475b8 100644 (file)
@@ -423,11 +423,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)