[dev.typeparams] Get dictionaryCapture.go working.

METHVALUE in a generic function (that is not called) was not causing
buildClosure() to be called and therefore not using dictionaries. Also,
had to add an extra check to make sure that if we have a FUNCINST
node above a METHVALUE, we only call buildClosure once.

Change-Id: I49756152fc343e5ac1c449e697960fc2a0f482ae
Reviewed-on: https://go-review.googlesource.com/c/go/+/336429
Reviewed-by: Keith Randall <khr@golang.org>
Trust: Dan Scales <danscales@google.com>
Run-TryBot: Dan Scales <danscales@google.com>
TryBot-Result: Go Bot <gobot@golang.org>
This commit is contained in:
Dan Scales 2021-07-18 11:09:12 -07:00
parent 4e6836e82c
commit ee20dff27d
2 changed files with 24 additions and 9 deletions

View file

@ -92,8 +92,8 @@ func (g *irgen) stencil() {
// generic F, not immediately called
closureRequired = true
}
if n.Op() == ir.OMETHEXPR && len(deref(n.(*ir.SelectorExpr).X.Type()).RParams()) > 0 && !types.IsInterfaceMethod(n.(*ir.SelectorExpr).Selection.Type) {
// T.M, T a type which is generic, not immediately
if (n.Op() == ir.OMETHEXPR || n.Op() == ir.OMETHVALUE) && len(deref(n.(*ir.SelectorExpr).X.Type()).RParams()) > 0 && !types.IsInterfaceMethod(n.(*ir.SelectorExpr).Selection.Type) {
// T.M or x.M, where T or x is generic, but not immediately
// called. Not necessary if the method selected is
// actually for an embedded interface field.
closureRequired = true
@ -180,18 +180,31 @@ func (g *irgen) stencil() {
// in the infrequent case of an OFUNCINST without a corresponding
// call.
if closureRequired {
modified = true
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 {
if x.Op() == ir.OFUNCINST {
child := x.(*ir.InstExpr).X
if child.Op() == ir.OMETHEXPR || child.Op() == ir.OMETHVALUE {
// Call EditChildren on child (x.X),
// not x, so that we don't do
// buildClosure() on the
// METHEXPR/METHVALUE nodes as well.
ir.EditChildren(child, edit)
return g.buildClosure(outer, x)
}
}
ir.EditChildren(x, edit)
switch {
case x.Op() == ir.OFUNCINST:
return g.buildClosure(outer, x)
case x.Op() == ir.OMETHEXPR && len(deref(x.(*ir.SelectorExpr).X.Type()).RParams()) > 0 &&
!types.IsInterfaceMethod(x.(*ir.SelectorExpr).Selection.Type): // TODO: test for ptr-to-method case
case (x.Op() == ir.OMETHEXPR || x.Op() == ir.OMETHVALUE) &&
len(deref(x.(*ir.SelectorExpr).X.Type()).RParams()) > 0 &&
!types.IsInterfaceMethod(x.(*ir.SelectorExpr).Selection.Type):
return g.buildClosure(outer, x)
}
return x
@ -264,13 +277,16 @@ func (g *irgen) buildClosure(outer *ir.Func, x ir.Node) ir.Node {
fmt.Printf("%s in %v for generic method value %v\n", dictkind, outer, inst.X)
}
}
} else { // ir.OMETHEXPR
} else { // ir.OMETHEXPR or ir.METHVALUE
// Method expression T.M where T is a generic type.
se := x.(*ir.SelectorExpr)
targs := deref(se.X.Type()).RParams()
if len(targs) == 0 {
panic("bad")
}
if x.Op() == ir.OMETHVALUE {
rcvrValue = se.X
}
// se.X.Type() is the top-level type of the method expression. To
// correctly handle method expressions involving embedded fields,

View file

@ -2175,7 +2175,6 @@ var g3Failures = setOf(
"typeparam/mdempsky/4.go", // -G=3 can't export functions with labeled breaks in loops
"typeparam/cons.go", // causes an unreachable method
"typeparam/dictionaryCapture.go", // segv, dictionary access failure?
"typeparam/issue44688.go", // interface conversion fails due to missing method
"typeparam/mdempsky/14.go", // interface comparison failure
)