Skip to content

Commit 6ba68a0

Browse files
committed
cmd/compile: don't inline fn with no shape params, but passed a shape arg
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 <[email protected]> Run-TryBot: Dan Scales <[email protected]> TryBot-Result: Go Bot <[email protected]> Reviewed-by: Keith Randall <[email protected]> Reviewed-by: Cuong Manh Le <[email protected]>
1 parent 00d6d20 commit 6ba68a0

File tree

2 files changed

+46
-0
lines changed

2 files changed

+46
-0
lines changed

src/cmd/compile/internal/inline/inl.go

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -685,6 +685,27 @@ func mkinlcall(n *ir.CallExpr, fn *ir.Func, maxCost int32, inlMap map[*ir.Func]b
685685
return n
686686
}
687687

688+
// Don't inline a function fn that has no shape parameters, but is passed at
689+
// least one shape arg. This means we must be inlining a non-generic function
690+
// fn that was passed into a generic function, and can be called with a shape
691+
// arg because it matches an appropriate type parameters. But fn may include
692+
// an interface conversion (that may be applied to a shape arg) that was not
693+
// apparent when we first created the instantiation of the generic function.
694+
// We can't handle this if we actually do the inlining, since we want to know
695+
// all interface conversions immediately after stenciling. So, we avoid
696+
// inlining in this case. See #49309.
697+
if !fn.Type().HasShape() {
698+
for _, arg := range n.Args {
699+
if arg.Type().HasShape() {
700+
if logopt.Enabled() {
701+
logopt.LogOpt(n.Pos(), "cannotInlineCall", "inline", ir.FuncName(ir.CurFunc),
702+
fmt.Sprintf("inlining non-shape function %v with shape args", ir.FuncName(fn)))
703+
}
704+
return n
705+
}
706+
}
707+
}
708+
688709
if base.Flag.Cfg.Instrumenting && types.IsRuntimePkg(fn.Sym().Pkg) {
689710
// Runtime package must not be instrumented.
690711
// Instrument skips runtime package. However, some runtime code can be

test/typeparam/issue49309.go

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
// run -gcflags=-G=3
2+
3+
// Copyright 2021 The Go Authors. All rights reserved.
4+
// Use of this source code is governed by a BSD-style
5+
// license that can be found in the LICENSE file.
6+
7+
package main
8+
9+
func genfunc[T any](f func(c T)) {
10+
var r T
11+
12+
f(r)
13+
}
14+
15+
func myfunc(c string) {
16+
test2(c)
17+
}
18+
19+
//go:noinline
20+
func test2(a interface{}) {
21+
}
22+
23+
func main() {
24+
genfunc(myfunc)
25+
}

0 commit comments

Comments
 (0)