src/cmd/compile/internal/typecheck/func.go | 38 +++++++++++--------------------------- src/cmd/compile/internal/types/fmt.go | 3 --- test/fixedbugs/issue62498.dir/a.go | 13 +++++++++++++ test/fixedbugs/issue62498.dir/main.go | 18 ++++++++++++++++++ test/fixedbugs/issue62498.go | 7 +++++++ diff --git a/src/cmd/compile/internal/typecheck/func.go b/src/cmd/compile/internal/typecheck/func.go index 1d1de5bf942c68ea0ea8249259fdb8e6b813a419..47d6c1e09a010f38d82670554193524059c4cbbd 100644 --- a/src/cmd/compile/internal/typecheck/func.go +++ b/src/cmd/compile/internal/typecheck/func.go @@ -94,40 +94,24 @@ // supposing the closure captures an int i and a string s // and has one float64 argument and no results, // the generated code looks like: // - // clos = &struct{.F uintptr; i *int; s *string}{func.1, &i, &s} + // clos = &struct{F uintptr; X0 *int; X1 *string}{func.1, &i, &s} // // The use of the struct provides type information to the garbage - // collector so that it can walk the closure. We could use (in this case) - // [3]unsafe.Pointer instead, but that would leave the gc in the dark. - // The information appears in the binary in the form of type descriptors; - // the struct is unnamed so that closures in multiple packages with the - // same struct type can share the descriptor. - - // Make sure the .F field is in the same package as the rest of the - // fields. This deals with closures in instantiated functions, which are - // compiled as if from the source package of the generic function. - var pkg *types.Pkg - if len(clo.Func.ClosureVars) == 0 { - pkg = types.LocalPkg - } else { - for _, v := range clo.Func.ClosureVars { - if pkg == nil { - pkg = v.Sym().Pkg - } else if pkg != v.Sym().Pkg { - base.Fatalf("Closure variables from multiple packages: %+v", clo) - } - } - } + // collector so that it can walk the closure. We could use (in this + // case) [3]unsafe.Pointer instead, but that would leave the gc in + // the dark. The information appears in the binary in the form of + // type descriptors; the struct is unnamed and uses exported field + // names so that closures in multiple packages with the same struct + // type can share the descriptor. - fields := []*types.Field{ - types.NewField(base.Pos, pkg.Lookup(".F"), types.Types[types.TUINTPTR]), - } - for _, v := range clo.Func.ClosureVars { + fields := make([]*types.Field, 1+len(clo.Func.ClosureVars)) + fields[0] = types.NewField(base.AutogeneratedPos, types.LocalPkg.Lookup("F"), types.Types[types.TUINTPTR]) + for i, v := range clo.Func.ClosureVars { typ := v.Type() if !v.Byval() { typ = types.NewPtr(typ) } - fields = append(fields, types.NewField(base.Pos, v.Sym(), typ)) + fields[1+i] = types.NewField(base.AutogeneratedPos, types.LocalPkg.LookupNum("X", i), typ) } typ := types.NewStruct(fields) typ.SetNoalg(true) diff --git a/src/cmd/compile/internal/types/fmt.go b/src/cmd/compile/internal/types/fmt.go index 0016fb960620148cc5a0d6353e27bc5381e7150e..c5d9941cfd7d7774191e15aed3213a57fada6c2a 100644 --- a/src/cmd/compile/internal/types/fmt.go +++ b/src/cmd/compile/internal/types/fmt.go @@ -642,9 +642,6 @@ if funarg != FunargNone { name = fmt.Sprint(f.Nname) } else if verb == 'L' { name = s.Name - if name == ".F" { - name = "F" // Hack for toolstash -cmp. - } if !IsExported(name) && mode != fmtTypeIDName { name = sconv(s, 0, mode) // qualify non-exported names (used on structs, not on funarg) } diff --git a/test/fixedbugs/issue62498.dir/a.go b/test/fixedbugs/issue62498.dir/a.go new file mode 100644 index 0000000000000000000000000000000000000000..68f97475ab62c58f432a2a4593b77d8fce94b4ce --- /dev/null +++ b/test/fixedbugs/issue62498.dir/a.go @@ -0,0 +1,13 @@ +// Copyright 2023 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 a + +func One(L any) { + func() { + defer F(L) + }() +} + +func F(any) {} diff --git a/test/fixedbugs/issue62498.dir/main.go b/test/fixedbugs/issue62498.dir/main.go new file mode 100644 index 0000000000000000000000000000000000000000..e55a24fb3a081ef9ffb15a4439a052a2998e4c07 --- /dev/null +++ b/test/fixedbugs/issue62498.dir/main.go @@ -0,0 +1,18 @@ +// Copyright 2023 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 + +import "./a" + +func main() { + a.One(nil) + Two(nil) +} + +func Two(L any) { + func() { + defer a.F(L) + }() +} diff --git a/test/fixedbugs/issue62498.go b/test/fixedbugs/issue62498.go new file mode 100644 index 0000000000000000000000000000000000000000..8fe8d8783fbc8efbcc76d7bb88b3fec5068e2896 --- /dev/null +++ b/test/fixedbugs/issue62498.go @@ -0,0 +1,7 @@ +// rundir + +// Copyright 2023 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 ignored