From ee20dff27debb738ca3a89a7a30113771c1c078f Mon Sep 17 00:00:00 2001 From: Dan Scales Date: Sun, 18 Jul 2021 11:09:12 -0700 Subject: [PATCH] [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 Trust: Dan Scales Run-TryBot: Dan Scales TryBot-Result: Go Bot --- src/cmd/compile/internal/noder/stencil.go | 26 ++++++++++++++++++----- test/run.go | 7 +++--- 2 files changed, 24 insertions(+), 9 deletions(-) diff --git a/src/cmd/compile/internal/noder/stencil.go b/src/cmd/compile/internal/noder/stencil.go index d1527c5d5c..71edc82dea 100644 --- a/src/cmd/compile/internal/noder/stencil.go +++ b/src/cmd/compile/internal/noder/stencil.go @@ -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, diff --git a/test/run.go b/test/run.go index 6e0c12d46b..55c508dd42 100644 --- a/test/run.go +++ b/test/run.go @@ -2174,10 +2174,9 @@ 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 + "typeparam/cons.go", // causes an unreachable method + "typeparam/issue44688.go", // interface conversion fails due to missing method + "typeparam/mdempsky/14.go", // interface comparison failure ) var unifiedFailures = setOf( -- 2.50.0