return false, 0, false
}
}
+ do := func(fn *ir.Func) bool {
+ // Can't recursively inline a function if the function body contains
+ // a call to a function f, which the function f is one of the call arguments.
+ return ir.Any(fn, func(node ir.Node) bool {
+ if call, ok := node.(*ir.CallExpr); ok {
+ for _, arg := range call.Args {
+ if call.Fun == arg {
+ return true
+ }
+ }
+ }
+ return false
+ })
+ }
+ for _, fn := range []*ir.Func{callerfn, callee} {
+ if do(fn) {
+ if log && logopt.Enabled() {
+ logopt.LogOpt(n.Pos(), "cannotInlineCall", "inline", fmt.Sprintf("recursive call to function: %s", ir.FuncName(fn)))
+ }
+ return false, 0, false
+ }
+ }
if base.Flag.Cfg.Instrumenting && types.IsNoInstrumentPkg(callee.Sym().Pkg) {
// Runtime package must not be instrumented.
--- /dev/null
+// run
+
+// Copyright 2025 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"
+
+// Y is the Y-combinator based on https://dreamsongs.com/Files/WhyOfY.pdf
+func Y[Endo ~func(RecFct) RecFct, RecFct ~func(T) R, T, R any](f Endo) RecFct {
+
+ type internal[RecFct ~func(T) R, T, R any] func(internal[RecFct, T, R]) RecFct
+
+ g := func(h internal[RecFct, T, R]) RecFct {
+ return func(t T) R {
+ return f(h(h))(t)
+ }
+ }
+ return g(g)
+}
+
+func main() {
+
+ fct := Y(func(r func(int) int) func(int) int {
+ return func(n int) int {
+ if n <= 0 {
+ return 1
+ }
+ return n * r(n-1)
+ }
+ })
+
+ want := 3628800
+ if got := fct(10); got != want {
+ msg := fmt.Sprintf("unexpected result, got: %d, want: %d", got, want)
+ panic(msg)
+ }
+}