From f432d3fc41b8f6b01131023aabcf935ebea172cb Mon Sep 17 00:00:00 2001 From: Keith Randall Date: Mon, 26 Apr 2021 14:13:19 -0700 Subject: [PATCH] cmd/compile: fix nongeneric closures in generic functions 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 Trust: Dan Scales Run-TryBot: Keith Randall TryBot-Result: Go Bot Reviewed-by: Dan Scales --- src/cmd/compile/internal/escape/escape.go | 5 ++++- src/cmd/compile/internal/noder/stencil.go | 5 ++++- test/typeparam/issue45738.go | 18 ++++++++++++++++++ 3 files changed, 26 insertions(+), 2 deletions(-) create mode 100644 test/typeparam/issue45738.go diff --git a/src/cmd/compile/internal/escape/escape.go b/src/cmd/compile/internal/escape/escape.go index b706d7d2c8..05bd44c35d 100644 --- a/src/cmd/compile/internal/escape/escape.go +++ b/src/cmd/compile/internal/escape/escape.go @@ -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) } diff --git a/src/cmd/compile/internal/noder/stencil.go b/src/cmd/compile/internal/noder/stencil.go index d60f0af548..3ebc8dff6d 100644 --- a/src/cmd/compile/internal/noder/stencil.go +++ b/src/cmd/compile/internal/noder/stencil.go @@ -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 index 0000000000..9f03e796a3 --- /dev/null +++ b/test/typeparam/issue45738.go @@ -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]() +}