[dev.go2go] go/types: fix unification issue when looking up generic methods

If enabled in types.Config, the type checker can handle generic
methods (methods that have their own type parameter list).
This CL fixes an issue with method lookup (missing method test)
that caused some assignments to fail.

Note that this does not affect the go2go tool - we don't have any
plans to support such generic methods. Type-checking them is
fairly straight-forward. Translating them into code is not.

Change-Id: I8b8a6b814417277c728732bd5a9421c99440a47a
Reviewed-on: https://go-review.googlesource.com/c/go/+/238627
Reviewed-by: Robert Griesemer <gri@golang.org>
This commit is contained in:
Robert Griesemer 2020-06-17 22:50:21 -07:00
parent 2c4c09e4ff
commit 5e754162cd
5 changed files with 54 additions and 3 deletions

View File

@ -13,6 +13,8 @@ TODO (implementation issues)
----------------------------------------------------------------------------------------------------
KNOWN ISSUES
- type parameter constraints are ignored when checking if a parameterized method implements the
matching method in an interface
- iteration over generic variables doesn't report certain channel errors (see TODOs in code)
- cannot handle mutually recursive parameterized interfaces using themselves as type bounds
example: type B(type P B(P)) interface{ m() } (need to delay all checking after seting up declarations)

View File

@ -104,6 +104,7 @@ var tests = [][]string{
{"testdata/tmp.go2"}, // used for ad-hoc tests - file contents transient
{"testdata/typeargs.go2"},
{"testdata/typeparams.go2"},
{"testdata/mtypeparams.go2"},
{"testdata/typeinst.go2"},
{"testdata/typeinst2.go2"},
{"testdata/issues.go2"},

View File

@ -341,7 +341,7 @@ 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 := check.newUnifier(true)
u.x.init(mtyp.tparams)
u.x.init(ftyp.tparams)
if !u.unify(ftyp, mtyp) {
return m, f
}
@ -414,7 +414,7 @@ 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 := check.newUnifier(true)
u.x.init(mtyp.tparams)
u.x.init(ftyp.tparams)
if !u.unify(ftyp, mtyp) {
return m, f
}

48
src/go/types/testdata/mtypeparams.go2 vendored Normal file
View File

@ -0,0 +1,48 @@
// Copyright 2020 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.
// If types.Config.AcceptMethodTypeParams is set,
// the type checker accepts methods that have their
// own type parameter list.
package p
type S struct{}
func (S) m(type T)(v T)
type I interface {
m(type T)(v T)
}
type J interface {
m(type T)(v T)
}
var _ I = S{}
var _ I = J(nil)
type C interface{ n() }
type Sc struct{}
func (Sc) m(type T C)(v T)
type Ic interface {
m(type T C)(v T)
}
type Jc interface {
m(type T C)(v T)
}
var _ Ic = Sc{}
var _ Ic = Jc(nil)
// TODO(gri) These should fail because the constraints don't match.
var _ I = Sc{}
var _ I = Jc(nil)
var _ Ic = S{}
var _ Ic = J(nil)

View File

@ -218,7 +218,7 @@ func init(/* ERROR func init must have no type parameters */ type P)() {}
type T struct {}
func (T) m1() {}
// Experimental: We allow method type parameters.
// The type checker accepts method type parameters if configured accordingly.
func (T) m2(type)() {}
func (T) m3(type P)() {}