"cmd/compile/internal/types"
"cmd/internal/obj"
"cmd/internal/pgo"
+ "cmd/internal/src"
)
// Inlining budget parameters, gathered in one place
return true, 0, metric, hot
}
+// parsePos returns all the inlining positions and the innermost position.
+func parsePos(pos src.XPos, posTmp []src.Pos) ([]src.Pos, src.Pos) {
+ ctxt := base.Ctxt
+ ctxt.AllPos(pos, func(p src.Pos) {
+ posTmp = append(posTmp, p)
+ })
+ l := len(posTmp) - 1
+ return posTmp[:l], posTmp[l]
+}
+
// canInlineCallExpr returns true if the call n from caller to callee
// can be inlined, plus the score computed for the call expr in question,
// and whether the callee is hot according to PGO.
return false, 0, false
}
+ callees, calleeInner := parsePos(n.Pos(), make([]src.Pos, 0, 10))
+
+ for _, p := range callees {
+ if p.Line() == calleeInner.Line() && p.Col() == calleeInner.Col() && p.AbsFilename() == calleeInner.AbsFilename() {
+ if log && logopt.Enabled() {
+ logopt.LogOpt(n.Pos(), "cannotInlineCall", "inline", fmt.Sprintf("recursive call to %s", ir.FuncName(callerfn)))
+ }
+ return false, 0, false
+ }
+ }
+
if callee == callerfn {
// Can't recursively inline a function into itself.
if log && logopt.Enabled() {
--- /dev/null
+// build
+
+// 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 (
+ "iter"
+)
+
+type leafSet map[rune]struct{}
+
+type branchMap map[rune]*node
+
+func (bm branchMap) findOrCreateBranch(r rune) *node {
+ if _, ok := bm[r]; !ok {
+ bm[r] = newNode()
+ }
+ return bm[r]
+}
+
+func (bm branchMap) allSuffixes() iter.Seq[string] {
+ return func(yield func(string) bool) {
+ for r, n := range bm {
+ for s := range n.allStrings() {
+ if !yield(string(r) + s) {
+ return
+ }
+ }
+ }
+ }
+}
+
+type node struct {
+ leafSet
+ branchMap
+}
+
+func newNode() *node {
+ return &node{make(leafSet), make(branchMap)}
+}
+
+func (n *node) add(s []rune) {
+ switch len(s) {
+ case 0:
+ return
+ case 1:
+ n.leafSet[s[0]] = struct{}{}
+ default:
+ n.branchMap.findOrCreateBranch(s[0]).add(s[1:])
+ }
+}
+
+func (n *node) addString(s string) {
+ n.add([]rune(s))
+}
+
+func (n *node) allStrings() iter.Seq[string] {
+ return func(yield func(string) bool) {
+ for s := range n.leafSet {
+ if !yield(string(s)) {
+ return
+ }
+ }
+ for r, n := range n.branchMap {
+ for s := range n.allSuffixes() {
+ if !yield(string(r) + s) {
+ return
+ }
+ }
+ }
+ }
+}
+
+func main() {
+ root := newNode()
+ for _, s := range []string{"foo", "bar", "baz", "a", "b", "c", "hello", "world"} {
+ root.addString(s)
+ }
+ for s := range root.allStrings() {
+ println(s)
+ }
+}