diff --git a/go/analysis/passes/buildssa/buildssa.go b/go/analysis/passes/buildssa/buildssa.go
index 37c878e..017415f 100644
--- a/go/analysis/passes/buildssa/buildssa.go
+++ b/go/analysis/passes/buildssa/buildssa.go
@@ -16,9 +16,7 @@
"golang.org/x/tools/go/analysis"
"golang.org/x/tools/go/analysis/passes/ctrlflow"
- "golang.org/x/tools/go/analysis/passes/internal/ctrlflowinternal"
"golang.org/x/tools/go/ssa"
- "golang.org/x/tools/internal/ssainternal"
)
var Analyzer = &analysis.Analyzer{
@@ -62,9 +60,7 @@
prog := ssa.NewProgram(pass.Fset, mode)
// Use the result of the ctrlflow analysis to improve the SSA CFG.
- ssainternal.SetNoReturn(prog, func(fn *types.Func) bool {
- return ctrlflowinternal.NoReturn(cfgs, fn)
- })
+ prog.SetNoReturn(cfgs.NoReturn)
// Create SSA packages for direct imports.
for _, p := range pass.Pkg.Imports() {
diff --git a/go/analysis/passes/ctrlflow/ctrlflow.go b/go/analysis/passes/ctrlflow/ctrlflow.go
index b84c8d6..577c1d4 100644
--- a/go/analysis/passes/ctrlflow/ctrlflow.go
+++ b/go/analysis/passes/ctrlflow/ctrlflow.go
@@ -16,11 +16,9 @@
"golang.org/x/tools/go/analysis"
"golang.org/x/tools/go/analysis/passes/inspect"
- "golang.org/x/tools/go/analysis/passes/internal/ctrlflowinternal"
"golang.org/x/tools/go/ast/inspector"
"golang.org/x/tools/go/cfg"
"golang.org/x/tools/go/types/typeutil"
- "golang.org/x/tools/internal/cfginternal"
"golang.org/x/tools/internal/typesinternal"
)
@@ -51,18 +49,10 @@
pass *analysis.Pass // transient; nil after construction
}
-// TODO(adonovan): add (*CFGs).NoReturn to public API.
-func (c *CFGs) isNoReturn(fn *types.Func) bool {
+func (c *CFGs) NoReturn(fn *types.Func) bool {
return c.noReturn[fn]
}
-func init() {
- // Expose the hidden method to callers in x/tools.
- ctrlflowinternal.NoReturn = func(c any, fn *types.Func) bool {
- return c.(*CFGs).isNoReturn(fn)
- }
-}
-
// CFGs has two maps: funcDecls for named functions and funcLits for
// unnamed ones. Unlike funcLits, the funcDecls map is not keyed by its
// syntax node, *ast.FuncDecl, because callMayReturn needs to do a
@@ -154,7 +144,7 @@
li := funcLits[lit]
if li.cfg == nil {
li.cfg = cfg.New(lit.Body, c.callMayReturn)
- if cfginternal.IsNoReturn(li.cfg) {
+ if li.cfg.NoReturn() {
li.noReturn = true
}
}
@@ -183,7 +173,7 @@
if !known {
if di.decl.Body != nil {
di.cfg = cfg.New(di.decl.Body, c.callMayReturn)
- if cfginternal.IsNoReturn(di.cfg) {
+ if di.cfg.NoReturn() {
noreturn = true
}
}
diff --git a/go/cfg/cfg.go b/go/cfg/cfg.go
index 38aba77..f69912c 100644
--- a/go/cfg/cfg.go
+++ b/go/cfg/cfg.go
@@ -47,8 +47,6 @@
"go/ast"
"go/format"
"go/token"
-
- "golang.org/x/tools/internal/cfginternal"
)
// A CFG represents the control-flow graph of a single function.
@@ -59,6 +57,9 @@
noreturn bool // function body lacks a reachable return statement
}
+// NoReturn reports whether the function has no reachable return.
+func (cfg *CFG) NoReturn() bool { return cfg.noreturn }
+
// A Block represents a basic block: a list of statements and
// expressions that are always evaluated sequentially.
//
@@ -184,14 +185,6 @@
return &CFG{Blocks: b.blocks, noreturn: noreturn}
}
-// isNoReturn reports whether the function has no reachable return.
-// TODO(adonovan): add (*CFG).NoReturn to public API.
-func isNoReturn(_cfg any) bool { return _cfg.(*CFG).noreturn }
-
-func init() {
- cfginternal.IsNoReturn = isNoReturn // expose to ctrlflow analyzer
-}
-
func (b *Block) String() string {
return fmt.Sprintf("block %d (%s)", b.Index, b.comment(nil))
}
diff --git a/go/ssa/create.go b/go/ssa/create.go
index bbf8856..b3e4bef 100644
--- a/go/ssa/create.go
+++ b/go/ssa/create.go
@@ -15,7 +15,6 @@
"os"
"sync"
- "golang.org/x/tools/internal/ssainternal"
"golang.org/x/tools/internal/versions"
)
@@ -314,19 +313,10 @@
return prog.imported[path]
}
-// setNoReturn sets the predicate used by the SSA builder to decide
-// whether a call to the specified named function cannot return,
-// allowing the builder to prune control-flow edges following the
-// call, thus improving the precision of downstream analysis.
-//
-// TODO(adonovan): add (*Program).SetNoReturn to the public API.
-func (prog *Program) setNoReturn(noReturn func(*types.Func) bool) {
+// SetNoReturn sets the predicate used when building the ssa.Program
+// prog that reports whether a given function cannot return.
+// This may be used to prune spurious control flow edges
+// after (e.g.) log.Fatal, improving the precision of analyses.
+func (prog *Program) SetNoReturn(noReturn func(*types.Func) bool) {
prog.noReturn = noReturn
}
-
-func init() {
- // SetNoReturn exposes Program.setNoReturn to the buildssa analyzer.
- ssainternal.SetNoReturn = func(prog any, noReturn func(*types.Func) bool) {
- prog.(*Program).setNoReturn(noReturn)
- }
-}
diff --git a/internal/cfginternal/cfginternal.go b/internal/cfginternal/cfginternal.go
deleted file mode 100644
index a9b6236..0000000
--- a/internal/cfginternal/cfginternal.go
+++ /dev/null
@@ -1,16 +0,0 @@
-// 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 cfginternal exposes internals of go/cfg.
-// It cannot actually depend on symbols from go/cfg.
-package cfginternal
-
-// IsNoReturn exposes (*cfg.CFG).noReturn to the ctrlflow analyzer.
-// TODO(adonovan): add CFG.NoReturn to the public API.
-//
-// You must link [golang.org/x/tools/go/cfg] into your application for
-// this function to be non-nil.
-var IsNoReturn = func(cfg any) bool {
- panic("golang.org/x/tools/go/cfg not linked into application")
-}
diff --git a/internal/ssainternal/ssainternal.go b/internal/ssainternal/ssainternal.go
deleted file mode 100644
index 686c5d9..0000000
--- a/internal/ssainternal/ssainternal.go
+++ /dev/null
@@ -1,22 +0,0 @@
-// 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 ssainternal exposes setters for internals of go/ssa.
-// It cannot actually depend on symbols from go/ssa.
-package ssainternal
-
-import "go/types"
-
-// SetNoReturn sets the predicate used when building the ssa.Program
-// prog that reports whether a given function cannot return.
-// This may be used to prune spurious control flow edges
-// after (e.g.) log.Fatal, improving the precision of analyses.
-//
-// You must link [golang.org/x/tools/go/ssa] into your application for
-// this function to be non-nil.
-//
-// TODO(adonovan): add (*ssa.Program).SetNoReturn to the public API.
-var SetNoReturn = func(prog any, noreturn func(*types.Func) bool) {
- panic("golang.org/x/tools/go/ssa not linked into application")
-}