]> Cypherpunks repositories - gostls13.git/commitdiff
go/types, types2: fix unification code for defined types
authorRobert Griesemer <gri@golang.org>
Mon, 31 Jan 2022 20:51:45 +0000 (12:51 -0800)
committerRobert Griesemer <gri@golang.org>
Mon, 31 Jan 2022 23:15:54 +0000 (23:15 +0000)
Fixes #50929.

Change-Id: I65b8eaf5e4b423839bc53c7b1db3679961498c8a
Reviewed-on: https://go-review.googlesource.com/c/go/+/382076
Trust: Robert Griesemer <gri@golang.org>
Reviewed-by: Robert Findley <rfindley@google.com>
src/cmd/compile/internal/types2/testdata/fixedbugs/issue50929.go2 [new file with mode: 0644]
src/cmd/compile/internal/types2/unify.go
src/go/types/testdata/fixedbugs/issue50929.go2 [new file with mode: 0644]
src/go/types/unify.go

diff --git a/src/cmd/compile/internal/types2/testdata/fixedbugs/issue50929.go2 b/src/cmd/compile/internal/types2/testdata/fixedbugs/issue50929.go2
new file mode 100644 (file)
index 0000000..941dbaa
--- /dev/null
@@ -0,0 +1,68 @@
+// Copyright 2022 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// This file is tested when running "go test -run Manual"
+// without source arguments. Use for one-off debugging.
+
+package p
+
+import "fmt"
+
+type F[A, B any] int
+
+func G[A, B any](F[A, B]) {
+}
+
+func _() {
+       // TODO(gri) only report one error below (issue #50932)
+       var x F /* ERROR cannot infer B */ /* ERROR got 1 arguments but 2 type parameters */ [int]
+       G(x /* ERROR does not match */)
+}
+
+// test case from issue
+// (lots of errors but doesn't crash anymore)
+
+type RC[G any, RG any] interface {
+       ~[]RG
+}
+
+type RG[G any] struct{}
+
+type RSC[G any] []*RG[G]
+
+type M[Rc RC[G, RG], G any, RG any] struct {
+       Fn func(Rc)
+}
+
+type NFn[Rc RC[G, RG], G any, RG any] func(Rc)
+
+func NC[Rc RC[G, RG], G any, RG any](nFn NFn[Rc, G, RG]) {
+       var empty Rc
+       nFn(empty)
+}
+
+func NSG[G any](c RSC[G]) {
+       fmt.Println(c)
+}
+
+func MMD[Rc RC /* ERROR cannot infer RG */ /* ERROR got 1 arguments */ [RG], RG any, G any]() M /* ERROR got 2 arguments */ /* ERROR Rc does not match */ [Rc, RG] {
+
+       var nFn NFn /* ERROR got 2 arguments */ /* ERROR Rc does not match */ [Rc, RG]
+
+       var empty Rc
+       switch any(empty).(type) {
+       case BC /* ERROR undeclared name: BC */ :
+
+       case RSC[G]:
+               nFn = NSG /* ERROR cannot use NSG\[G\] */ [G]
+       }
+
+       return M /* ERROR got 2 arguments */ [Rc, RG]{
+               Fn: func(rc Rc) {
+                       NC(nFn /* ERROR does not match */ )
+               },
+       }
+
+       return M /* ERROR got 2 arguments */ [Rc, RG]{}
+}
index b844fb22b6ce6726bfae478026de768f6d9c0694..13d5af671ed1c8a857ec99729cd90d47e0c5c5b7 100644 (file)
@@ -457,11 +457,14 @@ func (u *unifier) nify(x, y Type, p *ifacePair) bool {
                        xargs := x.targs.list()
                        yargs := y.targs.list()
 
+                       if len(xargs) != len(yargs) {
+                               return false
+                       }
+
                        // TODO(gri) This is not always correct: two types may have the same names
                        //           in the same package if one of them is nested in a function.
                        //           Extremely unlikely but we need an always correct solution.
                        if x.obj.pkg == y.obj.pkg && x.obj.name == y.obj.name {
-                               assert(len(xargs) == len(yargs))
                                for i, x := range xargs {
                                        if !u.nify(x, yargs[i], p) {
                                                return false
diff --git a/src/go/types/testdata/fixedbugs/issue50929.go2 b/src/go/types/testdata/fixedbugs/issue50929.go2
new file mode 100644 (file)
index 0000000..941dbaa
--- /dev/null
@@ -0,0 +1,68 @@
+// Copyright 2022 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// This file is tested when running "go test -run Manual"
+// without source arguments. Use for one-off debugging.
+
+package p
+
+import "fmt"
+
+type F[A, B any] int
+
+func G[A, B any](F[A, B]) {
+}
+
+func _() {
+       // TODO(gri) only report one error below (issue #50932)
+       var x F /* ERROR cannot infer B */ /* ERROR got 1 arguments but 2 type parameters */ [int]
+       G(x /* ERROR does not match */)
+}
+
+// test case from issue
+// (lots of errors but doesn't crash anymore)
+
+type RC[G any, RG any] interface {
+       ~[]RG
+}
+
+type RG[G any] struct{}
+
+type RSC[G any] []*RG[G]
+
+type M[Rc RC[G, RG], G any, RG any] struct {
+       Fn func(Rc)
+}
+
+type NFn[Rc RC[G, RG], G any, RG any] func(Rc)
+
+func NC[Rc RC[G, RG], G any, RG any](nFn NFn[Rc, G, RG]) {
+       var empty Rc
+       nFn(empty)
+}
+
+func NSG[G any](c RSC[G]) {
+       fmt.Println(c)
+}
+
+func MMD[Rc RC /* ERROR cannot infer RG */ /* ERROR got 1 arguments */ [RG], RG any, G any]() M /* ERROR got 2 arguments */ /* ERROR Rc does not match */ [Rc, RG] {
+
+       var nFn NFn /* ERROR got 2 arguments */ /* ERROR Rc does not match */ [Rc, RG]
+
+       var empty Rc
+       switch any(empty).(type) {
+       case BC /* ERROR undeclared name: BC */ :
+
+       case RSC[G]:
+               nFn = NSG /* ERROR cannot use NSG\[G\] */ [G]
+       }
+
+       return M /* ERROR got 2 arguments */ [Rc, RG]{
+               Fn: func(rc Rc) {
+                       NC(nFn /* ERROR does not match */ )
+               },
+       }
+
+       return M /* ERROR got 2 arguments */ [Rc, RG]{}
+}
index 085048f7970bb32bf0ccfb293d7ec4ebc4e82625..5d6d78bff042edda09c6c5c4ec1ba3be2c02d4aa 100644 (file)
@@ -164,7 +164,7 @@ func (d *tparamsList) index(typ Type) int {
 }
 
 // If tpar is a type parameter in list, tparamIndex returns the type parameter index.
-// Otherwise, the result is < 0. tpar must not be nil.j
+// Otherwise, the result is < 0. tpar must not be nil.
 func tparamIndex(list []*TypeParam, tpar *TypeParam) int {
        // Once a type parameter is bound its index is >= 0. However, there are some
        // code paths (namely tracing and type hashing) by which it is possible to
@@ -457,11 +457,14 @@ func (u *unifier) nify(x, y Type, p *ifacePair) bool {
                        xargs := x.targs.list()
                        yargs := y.targs.list()
 
+                       if len(xargs) != len(yargs) {
+                               return false
+                       }
+
                        // TODO(gri) This is not always correct: two types may have the same names
                        //           in the same package if one of them is nested in a function.
                        //           Extremely unlikely but we need an always correct solution.
                        if x.obj.pkg == y.obj.pkg && x.obj.name == y.obj.name {
-                               assert(len(xargs) == len(yargs))
                                for i, x := range xargs {
                                        if !u.nify(x, yargs[i], p) {
                                                return false