diff --git a/src/cmd/compile/internal/inline/inl.go b/src/cmd/compile/internal/inline/inl.go index 7ec007e922..7c45f1443b 100644 --- a/src/cmd/compile/internal/inline/inl.go +++ b/src/cmd/compile/internal/inline/inl.go @@ -701,7 +701,7 @@ func mkinlcall(n *ir.CallExpr, fn *ir.Func, maxCost int32, inlMap map[*ir.Func]b // 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. + // inlining in this case. See #49309. (1) if !fn.Type().HasShape() { for _, arg := range n.Args { if arg.Type().HasShape() { @@ -712,6 +712,23 @@ func mkinlcall(n *ir.CallExpr, fn *ir.Func, maxCost int32, inlMap map[*ir.Func]b return n } } + } else { + // Don't inline a function fn that has shape parameters, but is passed no shape arg. + // See comments (1) above, and issue #51909 + inlineable := false + for _, arg := range n.Args { + if arg.Type().HasShape() { + inlineable = true + break + } + } + if !inlineable { + if logopt.Enabled() { + logopt.LogOpt(n.Pos(), "cannotInlineCall", "inline", ir.FuncName(ir.CurFunc), + fmt.Sprintf("inlining shape function %v with no shape args", ir.FuncName(fn))) + } + return n + } } if base.Flag.Cfg.Instrumenting && types.IsRuntimePkg(fn.Sym().Pkg) { diff --git a/test/typeparam/issue51909.go b/test/typeparam/issue51909.go new file mode 100644 index 0000000000..5fe39ca2b3 --- /dev/null +++ b/test/typeparam/issue51909.go @@ -0,0 +1,30 @@ +// 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 None struct{} + +type Response interface { + send(ctx *struct{}) +} + +type HandlerFunc[Input any] func(Input) Response + +func Operation[Input any](method, path string, h HandlerFunc[Input]) { + var input Input + h(input) +} + +func Get[Body any](path string, h HandlerFunc[struct{ Body Body }]) { + Operation("GET", path, h) +} + +func main() { + Get("/", func(req struct{ Body None }) Response { + return nil + }) +} diff --git a/test/typeparam/issue51925.go b/test/typeparam/issue51925.go new file mode 100644 index 0000000000..0a385acd17 --- /dev/null +++ b/test/typeparam/issue51925.go @@ -0,0 +1,52 @@ +// 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 + +import "fmt" + +type IntLike interface { + ~int | ~int64 | ~int32 | ~int16 | ~int8 +} + +func Reduce[T any, U any, Uslice ~[]U](function func(T, U) T, sequence Uslice, initial T) T { + result := initial + for _, x := range sequence { + result = function(result, x) + } + return result +} + +func min[T IntLike](x, y T) T { + if x < y { + return x + } + return y + +} + +// Min returns the minimum element of `nums`. +func Min[T IntLike, NumSlice ~[]T](nums NumSlice) T { + if len(nums) == 0 { + return T(0) + } + return Reduce(min[T], nums, nums[0]) +} + +// VarMin is the variadic version of Min. +func VarMin[T IntLike](nums ...T) T { + return Min(nums) +} + +type myInt int + +func main() { + fmt.Println(VarMin(myInt(1), myInt(2))) + + seq := []myInt{1, 2} + fmt.Println(Min(seq)) + fmt.Println(VarMin(seq...)) +}