mirror of
https://github.com/golang/go
synced 2024-11-22 20:50:05 -07:00
[dev.typeparams] cmd/compile: handle dictionaries for top-level instantiations
There's no outer function in these cases, so we won't be reading the dictionary as a subdictionary from the outer scope's dictionary. It will always be a compile-time constant. Change-Id: I754b126652a6ffb62255734d53fcec29d77cfa9e Reviewed-on: https://go-review.googlesource.com/c/go/+/324949 Trust: Keith Randall <khr@golang.org> Trust: Dan Scales <danscales@google.com> Reviewed-by: Dan Scales <danscales@google.com>
This commit is contained in:
parent
de61465156
commit
bad388744b
@ -144,13 +144,19 @@ func (g *irgen) stencil() {
|
|||||||
// call.
|
// call.
|
||||||
if closureRequired {
|
if closureRequired {
|
||||||
var edit func(ir.Node) ir.Node
|
var edit func(ir.Node) ir.Node
|
||||||
|
var outer *ir.Func
|
||||||
|
if f, ok := decl.(*ir.Func); ok {
|
||||||
|
outer = f
|
||||||
|
}
|
||||||
edit = func(x ir.Node) ir.Node {
|
edit = func(x ir.Node) ir.Node {
|
||||||
ir.EditChildren(x, edit)
|
ir.EditChildren(x, edit)
|
||||||
switch {
|
switch {
|
||||||
case x.Op() == ir.OFUNCINST:
|
case x.Op() == ir.OFUNCINST:
|
||||||
return g.buildClosure(decl.(*ir.Func), x)
|
// TODO: only set outer!=nil if this instantiation uses
|
||||||
|
// a type parameter from outer. See comment in buildClosure.
|
||||||
|
return g.buildClosure(outer, x)
|
||||||
case x.Op() == ir.OMETHEXPR && len(deref(x.(*ir.SelectorExpr).X.Type()).RParams()) > 0: // TODO: test for ptr-to-method case
|
case x.Op() == ir.OMETHEXPR && len(deref(x.(*ir.SelectorExpr).X.Type()).RParams()) > 0: // TODO: test for ptr-to-method case
|
||||||
return g.buildClosure(decl.(*ir.Func), x)
|
return g.buildClosure(outer, x)
|
||||||
}
|
}
|
||||||
return x
|
return x
|
||||||
}
|
}
|
||||||
@ -170,7 +176,8 @@ func (g *irgen) stencil() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// buildClosure makes a closure to implement x, a OFUNCINST or OMETHEXPR
|
// buildClosure makes a closure to implement x, a OFUNCINST or OMETHEXPR
|
||||||
// of generic type. outer is the containing function.
|
// of generic type. outer is the containing function (or nil if closure is
|
||||||
|
// in a global assignment instead of a function).
|
||||||
func (g *irgen) buildClosure(outer *ir.Func, x ir.Node) ir.Node {
|
func (g *irgen) buildClosure(outer *ir.Func, x ir.Node) ir.Node {
|
||||||
pos := x.Pos()
|
pos := x.Pos()
|
||||||
var target *ir.Func // target instantiated function/method
|
var target *ir.Func // target instantiated function/method
|
||||||
@ -276,19 +283,25 @@ func (g *irgen) buildClosure(outer *ir.Func, x ir.Node) ir.Node {
|
|||||||
fn.SetIsHiddenClosure(true)
|
fn.SetIsHiddenClosure(true)
|
||||||
|
|
||||||
// This is the dictionary we want to use.
|
// This is the dictionary we want to use.
|
||||||
// Note: for now this is a compile-time constant, so we don't really need a closure
|
// It may be a constant, or it may be a dictionary acquired from the outer function's dictionary.
|
||||||
// to capture it (a wrapper function would work just as well). But eventually it
|
// For the latter, dictVar is a variable in the outer function's scope, set to the subdictionary
|
||||||
// will be a read of a subdictionary from the parent dictionary.
|
// read from the outer function's dictionary.
|
||||||
dictVar := ir.NewNameAt(pos, typecheck.LookupNum(".dict", g.dnum))
|
var dictVar *ir.Name
|
||||||
g.dnum++
|
var dictAssign *ir.AssignStmt
|
||||||
dictVar.Class = ir.PAUTO
|
if outer != nil {
|
||||||
typed(types.Types[types.TUINTPTR], dictVar)
|
// Note: for now this is a compile-time constant, so we don't really need a closure
|
||||||
dictVar.Curfn = outer
|
// to capture it (a wrapper function would work just as well). But eventually it
|
||||||
dictAssign := ir.NewAssignStmt(pos, dictVar, dictValue)
|
// will be a read of a subdictionary from the parent dictionary.
|
||||||
dictAssign.SetTypecheck(1)
|
dictVar = ir.NewNameAt(pos, typecheck.LookupNum(".dict", g.dnum))
|
||||||
dictVar.Defn = dictAssign
|
g.dnum++
|
||||||
outer.Dcl = append(outer.Dcl, dictVar)
|
dictVar.Class = ir.PAUTO
|
||||||
|
typed(types.Types[types.TUINTPTR], dictVar)
|
||||||
|
dictVar.Curfn = outer
|
||||||
|
dictAssign = ir.NewAssignStmt(pos, dictVar, dictValue)
|
||||||
|
dictAssign.SetTypecheck(1)
|
||||||
|
dictVar.Defn = dictAssign
|
||||||
|
outer.Dcl = append(outer.Dcl, dictVar)
|
||||||
|
}
|
||||||
// assign the receiver to a temporary.
|
// assign the receiver to a temporary.
|
||||||
var rcvrVar *ir.Name
|
var rcvrVar *ir.Name
|
||||||
var rcvrAssign ir.Node
|
var rcvrAssign ir.Node
|
||||||
@ -335,6 +348,7 @@ func (g *irgen) buildClosure(outer *ir.Func, x ir.Node) ir.Node {
|
|||||||
sym := typecheck.ClosureName(outer)
|
sym := typecheck.ClosureName(outer)
|
||||||
sym.SetFunc(true)
|
sym.SetFunc(true)
|
||||||
fn.Nname = ir.NewNameAt(pos, sym)
|
fn.Nname = ir.NewNameAt(pos, sym)
|
||||||
|
fn.Nname.Class = ir.PFUNC
|
||||||
fn.Nname.Func = fn
|
fn.Nname.Func = fn
|
||||||
fn.Nname.Defn = fn
|
fn.Nname.Defn = fn
|
||||||
typed(closureType, fn.Nname)
|
typed(closureType, fn.Nname)
|
||||||
@ -343,8 +357,18 @@ func (g *irgen) buildClosure(outer *ir.Func, x ir.Node) ir.Node {
|
|||||||
// Build body of closure. This involves just calling the wrapped function directly
|
// Build body of closure. This involves just calling the wrapped function directly
|
||||||
// with the additional dictionary argument.
|
// with the additional dictionary argument.
|
||||||
|
|
||||||
// First, capture the dictionary variable for use in the closure.
|
// First, figure out the dictionary argument.
|
||||||
dict2Var := ir.CaptureName(pos, fn, dictVar)
|
var dict2Var ir.Node
|
||||||
|
if outer != nil {
|
||||||
|
// If there's an outer function, the dictionary value will be read from
|
||||||
|
// the dictionary of the outer function.
|
||||||
|
// TODO: only use a subdictionary if any of the instantiating types
|
||||||
|
// depend on the type params of the outer function.
|
||||||
|
dict2Var = ir.CaptureName(pos, fn, dictVar)
|
||||||
|
} else {
|
||||||
|
// No outer function, instantiating types are known concrete types.
|
||||||
|
dict2Var = dictValue
|
||||||
|
}
|
||||||
// Also capture the receiver variable.
|
// Also capture the receiver variable.
|
||||||
var rcvr2Var *ir.Name
|
var rcvr2Var *ir.Name
|
||||||
if rcvrValue != nil {
|
if rcvrValue != nil {
|
||||||
@ -376,13 +400,19 @@ func (g *irgen) buildClosure(outer *ir.Func, x ir.Node) ir.Node {
|
|||||||
typecheck.Stmt(innerCall)
|
typecheck.Stmt(innerCall)
|
||||||
ir.CurFunc = nil
|
ir.CurFunc = nil
|
||||||
fn.Body = []ir.Node{innerCall}
|
fn.Body = []ir.Node{innerCall}
|
||||||
|
if outer == nil {
|
||||||
|
g.target.Decls = append(g.target.Decls, fn)
|
||||||
|
}
|
||||||
|
|
||||||
// We're all done with the captured dictionary (and receiver, for method values).
|
// We're all done with the captured dictionary (and receiver, for method values).
|
||||||
ir.FinishCaptureNames(pos, outer, fn)
|
ir.FinishCaptureNames(pos, outer, fn)
|
||||||
|
|
||||||
// Make a closure referencing our new internal function.
|
// Make a closure referencing our new internal function.
|
||||||
c := ir.NewClosureExpr(pos, fn)
|
c := ir.NewClosureExpr(pos, fn)
|
||||||
init := []ir.Node{dictAssign}
|
var init []ir.Node
|
||||||
|
if outer != nil {
|
||||||
|
init = append(init, dictAssign)
|
||||||
|
}
|
||||||
if rcvrValue != nil {
|
if rcvrValue != nil {
|
||||||
init = append(init, rcvrAssign)
|
init = append(init, rcvrAssign)
|
||||||
}
|
}
|
||||||
|
@ -17,6 +17,7 @@ func main() {
|
|||||||
methodExpressions()
|
methodExpressions()
|
||||||
methodValues()
|
methodValues()
|
||||||
interfaceMethods()
|
interfaceMethods()
|
||||||
|
globals()
|
||||||
}
|
}
|
||||||
|
|
||||||
func g0[T any](x T) {
|
func g0[T any](x T) {
|
||||||
@ -98,3 +99,30 @@ func interfaceMethods() {
|
|||||||
is7(y.(interface{g1()int}).g1())
|
is7(y.(interface{g1()int}).g1())
|
||||||
is77(y.(interface{g2()(int,int)}).g2())
|
is77(y.(interface{g2()(int,int)}).g2())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Also check for instantiations outside functions.
|
||||||
|
var gg0 = g0[int]
|
||||||
|
var gg1 = g1[int]
|
||||||
|
var gg2 = g2[int]
|
||||||
|
|
||||||
|
var hh0 = s[int].g0
|
||||||
|
var hh1 = s[int].g1
|
||||||
|
var hh2 = s[int].g2
|
||||||
|
|
||||||
|
var xtop = s[int]{a:7}
|
||||||
|
var ii0 = x.g0
|
||||||
|
var ii1 = x.g1
|
||||||
|
var ii2 = x.g2
|
||||||
|
|
||||||
|
func globals() {
|
||||||
|
gg0(7)
|
||||||
|
is7(gg1(7))
|
||||||
|
is77(gg2(7))
|
||||||
|
x := s[int]{a:7}
|
||||||
|
hh0(x)
|
||||||
|
is7(hh1(x))
|
||||||
|
is77(hh2(x))
|
||||||
|
ii0()
|
||||||
|
is7(ii1())
|
||||||
|
is77(ii2())
|
||||||
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user