]> Cypherpunks repositories - gostls13.git/commitdiff
[dev.typeparams] Get dictionaryCapture.go working.
authorDan Scales <danscales@google.com>
Sun, 18 Jul 2021 18:09:12 +0000 (11:09 -0700)
committerDan Scales <danscales@google.com>
Thu, 22 Jul 2021 04:44:48 +0000 (04:44 +0000)
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>

src/cmd/compile/internal/noder/stencil.go
test/run.go

index d1527c5d5c7af7f502439e24d0c5749eea060853..71edc82deab8a23e14e0b749f12e6bd869388af9 100644 (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,
index 6e0c12d46b30dedecfa679b7335ece5a34be18c4..55c508dd4237c70cd4e2524a0c8276bb4ee73b3c 100644 (file)
@@ -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(