From 249e51e5d9aac5124628d524499ea9c067bc37d5 Mon Sep 17 00:00:00 2001 From: Cuong Manh Le Date: Thu, 17 Nov 2022 19:21:45 +0700 Subject: [PATCH] cmd/compile: fix static init for inlined calls CL 450136 made the compiler to be able to handle simple inlined calls in staticinit. However, it's missed a condition when checking substituting arg for param. If there's any non-trivial closures, it has captured one of the param, so the substitution could not happen. Fixes #56778 Change-Id: I427c9134e333e2f9af136c1a124da4d37d326f10 Reviewed-on: https://go-review.googlesource.com/c/go/+/451555 Run-TryBot: Cuong Manh Le Auto-Submit: Cuong Manh Le TryBot-Result: Gopher Robot Reviewed-by: Keith Randall Reviewed-by: Keith Randall Reviewed-by: David Chase --- src/cmd/compile/internal/staticinit/sched.go | 12 ++++++++++++ test/fixedbugs/issue56778.dir/a.go | 18 ++++++++++++++++++ test/fixedbugs/issue56778.dir/b.go | 9 +++++++++ test/fixedbugs/issue56778.go | 7 +++++++ 4 files changed, 46 insertions(+) create mode 100644 test/fixedbugs/issue56778.dir/a.go create mode 100644 test/fixedbugs/issue56778.dir/b.go create mode 100644 test/fixedbugs/issue56778.go diff --git a/src/cmd/compile/internal/staticinit/sched.go b/src/cmd/compile/internal/staticinit/sched.go index 8e73e54f53..0f037d5467 100644 --- a/src/cmd/compile/internal/staticinit/sched.go +++ b/src/cmd/compile/internal/staticinit/sched.go @@ -570,13 +570,25 @@ func (s *Schedule) staticAssignInlinedCall(l *ir.Name, loff int64, call *ir.Inli for _, x := range as2init.Lhs { count[x.(*ir.Name)] = 0 } + + hasNonTrivialClosure := false ir.Visit(as2body.Rhs[0], func(n ir.Node) { if name, ok := n.(*ir.Name); ok { if c, ok := count[name]; ok { count[name] = c + 1 } } + if clo, ok := n.(*ir.ClosureExpr); ok { + hasNonTrivialClosure = hasNonTrivialClosure || !ir.IsTrivialClosure(clo) + } }) + + // If there's a non-trivial closure, it has captured the param, + // so we can't substitute arg for param. + if hasNonTrivialClosure { + return false + } + for name, c := range count { if c > 1 { // Check whether corresponding initializer can be repeated. diff --git a/test/fixedbugs/issue56778.dir/a.go b/test/fixedbugs/issue56778.dir/a.go new file mode 100644 index 0000000000..d01aea4d14 --- /dev/null +++ b/test/fixedbugs/issue56778.dir/a.go @@ -0,0 +1,18 @@ +// Copyright 2022 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 + +type A struct { + New func() any +} + +func NewA(i int) *A { + return &A{ + New: func() any { + _ = i + return nil + }, + } +} diff --git a/test/fixedbugs/issue56778.dir/b.go b/test/fixedbugs/issue56778.dir/b.go new file mode 100644 index 0000000000..d49f7e5708 --- /dev/null +++ b/test/fixedbugs/issue56778.dir/b.go @@ -0,0 +1,9 @@ +// Copyright 2022 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 b + +import "./a" + +var _ = a.NewA(0) diff --git a/test/fixedbugs/issue56778.go b/test/fixedbugs/issue56778.go new file mode 100644 index 0000000000..8bb5c3e213 --- /dev/null +++ b/test/fixedbugs/issue56778.go @@ -0,0 +1,7 @@ +// compiledir + +// Copyright 2022 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 -- 2.50.0