]> Cypherpunks repositories - gostls13.git/commitdiff
cmd/compile: don't inline fn with no shape params, but passed a shape arg
authorDan Scales <danscales@google.com>
Wed, 3 Nov 2021 21:47:04 +0000 (14:47 -0700)
committerDan Scales <danscales@google.com>
Thu, 4 Nov 2021 15:43:59 +0000 (15:43 +0000)
Don't inline a function fn that has no shape parameters, but is passed
at least one shape arg. This means we must be inlining a non-generic
function fn that was passed into a generic function, and can be called
with a shape arg because it matches an appropriate type parameter. But
fn may include an interface conversion (that may be applied to a shape
arg) that was not apparent when we first created the instantiation of
the generic function. We can't handle this if we actually do the
inlining, since we want to know all interface conversions immediately
after stenciling.  So, we avoid inlining in this case.

Fixes #49309.

Change-Id: I7b8ab7b13e58fdb0111db91bc92a91d313f7c2c3
Reviewed-on: https://go-review.googlesource.com/c/go/+/361260
Trust: Dan Scales <danscales@google.com>
Run-TryBot: Dan Scales <danscales@google.com>
TryBot-Result: Go Bot <gobot@golang.org>
Reviewed-by: Keith Randall <khr@golang.org>
Reviewed-by: Cuong Manh Le <cuong.manhle.vn@gmail.com>
src/cmd/compile/internal/inline/inl.go
test/typeparam/issue49309.go [new file with mode: 0644]

index da905bd627fcd2c3f477baeb7fc434809651b9da..b764aed534db7ffcf93aa18e1dad1a6c23e1036b 100644 (file)
@@ -685,6 +685,27 @@ func mkinlcall(n *ir.CallExpr, fn *ir.Func, maxCost int32, inlMap map[*ir.Func]b
                return n
        }
 
+       // Don't inline a function fn that has no shape parameters, but is passed at
+       // least one shape arg. This means we must be inlining a non-generic function
+       // fn that was passed into a generic function, and can be called with a shape
+       // arg because it matches an appropriate type parameters. But fn may include
+       // an interface conversion (that may be applied to a shape arg) that was not
+       // apparent when we first created the instantiation of the generic function.
+       // We can't handle this if we actually do the inlining, since we want to know
+       // all interface conversions immediately after stenciling. So, we avoid
+       // inlining in this case. See #49309.
+       if !fn.Type().HasShape() {
+               for _, arg := range n.Args {
+                       if arg.Type().HasShape() {
+                               if logopt.Enabled() {
+                                       logopt.LogOpt(n.Pos(), "cannotInlineCall", "inline", ir.FuncName(ir.CurFunc),
+                                               fmt.Sprintf("inlining non-shape function %v with shape args", ir.FuncName(fn)))
+                               }
+                               return n
+                       }
+               }
+       }
+
        if base.Flag.Cfg.Instrumenting && types.IsRuntimePkg(fn.Sym().Pkg) {
                // Runtime package must not be instrumented.
                // Instrument skips runtime package. However, some runtime code can be
diff --git a/test/typeparam/issue49309.go b/test/typeparam/issue49309.go
new file mode 100644 (file)
index 0000000..36da86a
--- /dev/null
@@ -0,0 +1,25 @@
+// run -gcflags=-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
+
+func genfunc[T any](f func(c T)) {
+       var r T
+
+       f(r)
+}
+
+func myfunc(c string) {
+       test2(c)
+}
+
+//go:noinline
+func test2(a interface{}) {
+}
+
+func main() {
+       genfunc(myfunc)
+}