]> Cypherpunks repositories - gostls13.git/commitdiff
cmd/compile: fix nongeneric closures in generic functions
authorKeith Randall <khr@golang.org>
Mon, 26 Apr 2021 21:13:19 +0000 (14:13 -0700)
committerKeith Randall <khr@golang.org>
Tue, 27 Apr 2021 19:30:11 +0000 (19:30 +0000)
Ensure that formal parameter Names are correctly copied and marked
with the correct Curfn. We need to ensure this even when the underlying
closure has no type parameters.

(Aside: it is strange that the types of things contain formal
parameter names that need to be copied. Maybe that's an underlying
larger problem that needs to be fixed.)

Fixes #45738

Change-Id: Ia13d69eea992ff7080bd44065115bc52eb624e73
Reviewed-on: https://go-review.googlesource.com/c/go/+/313652
Trust: Keith Randall <khr@golang.org>
Trust: Dan Scales <danscales@google.com>
Run-TryBot: Keith Randall <khr@golang.org>
TryBot-Result: Go Bot <gobot@golang.org>
Reviewed-by: Dan Scales <danscales@google.com>
src/cmd/compile/internal/escape/escape.go
src/cmd/compile/internal/noder/stencil.go
test/typeparam/issue45738.go [new file with mode: 0644]

index b706d7d2c8cd1ce722430b712262e5dbdc76be7a..05bd44c35de5e58a52069bb3a637f54f52c27197 100644 (file)
@@ -1295,7 +1295,7 @@ func (e *escape) newLoc(n ir.Node, transient bool) *location {
                if n.Op() == ir.ONAME {
                        n := n.(*ir.Name)
                        if n.Curfn != e.curfn {
-                               base.Fatalf("curfn mismatch: %v != %v", n.Curfn, e.curfn)
+                               base.Fatalf("curfn mismatch: %v != %v for %v", n.Curfn, e.curfn, n)
                        }
 
                        if n.Opt != nil {
@@ -1308,6 +1308,9 @@ func (e *escape) newLoc(n ir.Node, transient bool) *location {
 }
 
 func (b *batch) oldLoc(n *ir.Name) *location {
+       if n.Canonical().Opt == nil {
+               base.Fatalf("%v has no location", n)
+       }
        return n.Canonical().Opt.(*location)
 }
 
index d60f0af548f11680e6ef1c047d056b0cab3eb922..3ebc8dff6d84322d2d5c2379e9497a87ebb1d73b 100644 (file)
@@ -667,7 +667,10 @@ func instTypeName(name string, targs []*types.Type) string {
 // result is t; otherwise the result is a new type. It deals with recursive types
 // by using TFORW types and finding partially or fully created types via sym.Def.
 func (subst *subster) typ(t *types.Type) *types.Type {
-       if !t.HasTParam() {
+       if !t.HasTParam() && t.Kind() != types.TFUNC {
+               // Note: function types need to be copied regardless, as the
+               // types of closures may contain declarations that need
+               // to be copied. See #45738.
                return t
        }
 
diff --git a/test/typeparam/issue45738.go b/test/typeparam/issue45738.go
new file mode 100644 (file)
index 0000000..9f03e79
--- /dev/null
@@ -0,0 +1,18 @@
+// compile -G=3
+
+// Copyright 2021 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package main
+
+//go:noinline
+func f[T any]() {
+       x := 5
+       g := func() int { return x }
+       g()
+}
+
+func main() {
+       f[int]()
+}