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(