mirror of
https://github.com/golang/go.git
synced 2025-10-24 05:23:20 +00:00
[dev.typeparams] cmd/compile: support generic types (with stenciling of method calls)
A type may now have a type param in it, either because it has been composed from a function type param, or it has been declared as or derived from a reference to a generic type. No objects or types with type params can be exported yet. No generic type has a runtime descriptor (but will likely eventually be associated with a dictionary). types.Type now has an RParam field, which for a Named type can specify the type params (in order) that must be supplied to fully instantiate the type. Also, there is a new flag HasTParam to indicate if there is a type param (TTYPEPARAM) anywhere in the type. An instantiated generic type (whether fully instantiated or re-instantiated to new type params) is a defined type, even though there was no explicit declaration. This allows us to handle recursive instantiated types (and improves printing of types). To avoid the need to transform later in the compiler, an instantiation of a method of a generic type is immediately represented as a function with the method as the first argument. Added 5 tests on generic types to test/typeparams, including list.go, which tests recursive generic types. Change-Id: Ib7ff27abd369a06d1c8ea84edc6ca1fd74bbb7c2 Reviewed-on: https://go-review.googlesource.com/c/go/+/292652 Trust: Dan Scales <danscales@google.com> Trust: Robert Griesemer <gri@golang.org> Run-TryBot: Dan Scales <danscales@google.com> Reviewed-by: Robert Griesemer <gri@golang.org>
This commit is contained in:
parent
2ff1e05a4c
commit
20050a15fe
14 changed files with 582 additions and 32 deletions
|
|
@ -209,7 +209,7 @@ func (g *irgen) selectorExpr(pos src.XPos, typ types2.Type, expr *syntax.Selecto
|
|||
// interface embedding).
|
||||
|
||||
var n ir.Node
|
||||
method := selinfo.Obj().(*types2.Func)
|
||||
method2 := selinfo.Obj().(*types2.Func)
|
||||
|
||||
if kind == types2.MethodExpr {
|
||||
// OMETHEXPR is unusual in using directly the node and type of the
|
||||
|
|
@ -221,9 +221,11 @@ func (g *irgen) selectorExpr(pos src.XPos, typ types2.Type, expr *syntax.Selecto
|
|||
n = MethodExpr(pos, origx, x.Type(), last)
|
||||
} else {
|
||||
// Add implicit addr/deref for method values, if needed.
|
||||
if !x.Type().IsInterface() {
|
||||
recvTyp := method.Type().(*types2.Signature).Recv().Type()
|
||||
_, wantPtr := recvTyp.(*types2.Pointer)
|
||||
if x.Type().IsInterface() {
|
||||
n = DotMethod(pos, x, last)
|
||||
} else {
|
||||
recvType2 := method2.Type().(*types2.Signature).Recv().Type()
|
||||
_, wantPtr := recvType2.(*types2.Pointer)
|
||||
havePtr := x.Type().IsPtr()
|
||||
|
||||
if havePtr != wantPtr {
|
||||
|
|
@ -233,13 +235,45 @@ func (g *irgen) selectorExpr(pos src.XPos, typ types2.Type, expr *syntax.Selecto
|
|||
x = Implicit(Addr(pos, x))
|
||||
}
|
||||
}
|
||||
if !g.match(x.Type(), recvTyp, false) {
|
||||
base.FatalfAt(pos, "expected %L to have type %v", x, recvTyp)
|
||||
recvType2Base := recvType2
|
||||
if wantPtr {
|
||||
recvType2Base = recvType2.Pointer().Elem()
|
||||
}
|
||||
if len(recvType2Base.Named().TParams()) > 0 {
|
||||
// recvType2 is the original generic type that is
|
||||
// instantiated for this method call.
|
||||
// selinfo.Recv() is the instantiated type
|
||||
recvType2 = recvType2Base
|
||||
// method is the generic method associated with the gen type
|
||||
method := g.obj(recvType2.Named().Method(last))
|
||||
n = ir.NewSelectorExpr(pos, ir.OCALLPART, x, method.Sym())
|
||||
n.(*ir.SelectorExpr).Selection = types.NewField(pos, method.Sym(), method.Type())
|
||||
n.(*ir.SelectorExpr).Selection.Nname = method
|
||||
typed(method.Type(), n)
|
||||
|
||||
// selinfo.Targs() are the types used to
|
||||
// instantiate the type of receiver
|
||||
targs2 := selinfo.TArgs()
|
||||
targs := make([]ir.Node, len(targs2))
|
||||
for i, targ2 := range targs2 {
|
||||
targs[i] = ir.TypeNode(g.typ(targ2))
|
||||
}
|
||||
|
||||
// Create function instantiation with the type
|
||||
// args for the receiver type for the method call.
|
||||
n = ir.NewInstExpr(pos, ir.OFUNCINST, n, targs)
|
||||
typed(g.typ(typ), n)
|
||||
return n
|
||||
}
|
||||
|
||||
if !g.match(x.Type(), recvType2, false) {
|
||||
base.FatalfAt(pos, "expected %L to have type %v", x, recvType2)
|
||||
} else {
|
||||
n = DotMethod(pos, x, last)
|
||||
}
|
||||
}
|
||||
n = DotMethod(pos, x, last)
|
||||
}
|
||||
if have, want := n.Sym(), g.selector(method); have != want {
|
||||
if have, want := n.Sym(), g.selector(method2); have != want {
|
||||
base.FatalfAt(pos, "bad Sym: have %v, want %v", have, want)
|
||||
}
|
||||
return n
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue