ir.ClosureExpr implements ir.InitNode, so ir.InitExpr can prepend init
statements to it. However, CalleeEffects wasn't aware of this and
could cause the init statements to get dropped when inlining a call to
a closure.
This isn't an issue today, because we don't create closures with init
statements. But I ran into this within unified IR.
Easy and robust solution: just take advantage that ir.TakeInit can
handle any node.
Fixes #54917.
Change-Id: Ica05fbf6a8c5be4b11927daf84491a1140da5431
Reviewed-on: https://go-review.googlesource.com/c/go/+/422196
Reviewed-by: Than McIntosh <thanm@google.com>
Run-TryBot: Matthew Dempsky <mdempsky@google.com>
TryBot-Result: Gopher Robot <gobot@golang.org>
Reviewed-by: Cuong Manh Le <cuong.manhle.vn@gmail.com>
Reviewed-on: https://go-review.googlesource.com/c/go/+/429896
Reviewed-by: Michael Knyszek <mknyszek@google.com>
// CalleeEffects appends any side effects from evaluating callee to init.
func CalleeEffects(init *ir.Nodes, callee ir.Node) {
for {
+ init.Append(ir.TakeInit(callee)...)
+
switch callee.Op() {
case ir.ONAME, ir.OCLOSURE, ir.OMETHEXPR:
return // done
case ir.OCONVNOP:
conv := callee.(*ir.ConvExpr)
- init.Append(ir.TakeInit(conv)...)
callee = conv.X
case ir.OINLCALL:
ic := callee.(*ir.InlinedCallExpr)
- init.Append(ir.TakeInit(ic)...)
init.Append(ic.Body.Take()...)
callee = ic.SingleResult()
--- /dev/null
+// compile
+
+// 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 main
+
+type Set[T comparable] map[T]struct{}
+
+func (s Set[T]) Add() Set[T] {
+ return s
+}
+
+func (s Set[T]) Copy() Set[T] {
+ return Set[T].Add(s)
+}
+
+func main() {
+ _ = Set[int]{42: {}}
+}