]> Cypherpunks repositories - gostls13.git/commitdiff
[dev.typeparams] cmd/compile/internal/types2: use correct type parameter list in...
authorRobert Griesemer <gri@golang.org>
Wed, 19 May 2021 23:25:31 +0000 (16:25 -0700)
committerRobert Griesemer <gri@golang.org>
Wed, 19 May 2021 23:43:30 +0000 (23:43 +0000)
For #46275

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

index 78299502e9c00d9ab176733912a31c60d2602a50..eb2b17dd4debd1f7043cf385a1044f131e88691a 100644 (file)
@@ -333,6 +333,9 @@ func (check *Checker) missingMethod(V Type, T *Interface, static bool) (method,
                        if len(ftyp.tparams) != len(mtyp.tparams) {
                                return m, f
                        }
+                       if !acceptMethodTypeParams && len(ftyp.tparams) > 0 {
+                               panic("internal error: method with type parameters")
+                       }
 
                        // If the methods have type parameters we don't care whether they
                        // are the same or not, as long as they match up. Use unification
@@ -386,6 +389,9 @@ func (check *Checker) missingMethod(V Type, T *Interface, static bool) (method,
                if len(ftyp.tparams) != len(mtyp.tparams) {
                        return m, f
                }
+               if !acceptMethodTypeParams && len(ftyp.tparams) > 0 {
+                       panic("internal error: method with type parameters")
+               }
 
                // If V is a (instantiated) generic type, its methods are still
                // parameterized using the original (declaration) receiver type
@@ -413,7 +419,20 @@ func (check *Checker) missingMethod(V Type, T *Interface, static bool) (method,
                // TODO(gri) is this always correct? what about type bounds?
                // (Alternative is to rename/subst type parameters and compare.)
                u := newUnifier(check, true)
-               u.x.init(ftyp.tparams)
+               if len(ftyp.tparams) > 0 {
+                       // We reach here only if we accept method type parameters.
+                       // In this case, unification must consider any receiver
+                       // and method type parameters as "free" type parameters.
+                       assert(acceptMethodTypeParams)
+                       // We don't have a test case for this at the moment since
+                       // we can't parse method type parameters. Keeping the
+                       // unimplemented call so that we test this code if we
+                       // enable method type parameters.
+                       unimplemented()
+                       u.x.init(append(ftyp.rparams, ftyp.tparams...))
+               } else {
+                       u.x.init(ftyp.rparams)
+               }
                if !u.unify(ftyp, mtyp) {
                        return m, f
                }
diff --git a/src/cmd/compile/internal/types2/testdata/fixedbugs/issue46275.go2 b/src/cmd/compile/internal/types2/testdata/fixedbugs/issue46275.go2
new file mode 100644 (file)
index 0000000..f41ae26
--- /dev/null
@@ -0,0 +1,26 @@
+// Copyright 2021 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.
+
+package issue46275
+
+type N[T any] struct {
+        *N[T]
+        t T
+}
+
+func (n *N[T]) Elem() T {
+        return n.t
+}
+
+type I interface {
+        Elem() string
+}
+
+func _() {
+        var n1 *N[string]
+        var _ I = n1
+        type NS N[string]
+        var n2 *NS
+        var _ I = n2
+}