Understanding Go's Source-Level Inliner and //go:fix inline
Go 1.26 introduces a revamped go fix command that helps developers modernize their codebases. One standout feature is the source-level inliner, a powerful tool that enables package authors to define simple, safe API migrations using //go:fix inline directives. This Q&A explains how the inliner works, how it differs from compiler inlining, and how you can leverage it to keep your Go code up-to-date.
What is the //go:fix inline directive and the source-level inliner?
The //go:fix inline directive is a comment that package authors add to function declarations to tell the go fix tool to replace calls to that function with its body. This is performed by the source-level inliner—a transformation that durably modifies your source code, as opposed to the compiler’s inliner which only works on internal intermediate representations. The directive enables self-service API migrations: for example, if you rename a function or change its signature, you can keep the old function with //go:fix inline so that go fix automatically updates all callers to use the new version.

How does source-level inlining differ from compiler inlining?
Compiler inlining is an optimization that happens during compilation: the compiler replaces a call site with a copy of the called function’s body to produce more efficient machine code. This transformation is ephemeral and never touches your source files. In contrast, the source-level inliner performs the same expansion but writes the result back to your .go files. It is a durable refactoring that permanently replaces the function call with the expanded code. This makes it ideal for API migrations where you want to eliminate calls to deprecated functions without manually editing every caller.
How is the source-level inliner used in gopls?
The Go language server, gopls, has long used the source-level inliner for interactive refactorings. For example, the “Inline call” code action allows you to select a function call and replace it with its body. This is particularly useful when you want to simplify code or remove a layer of abstraction. Additionally, refactorings like “Change signature” and “Remove unused parameter” rely on the inliner to handle complex case—such as variadic arguments or closures—safely. The same algorithm now powers go fix, making these transformations available at the command line.
How can package authors use the source-level inliner for API migration?
Package authors can mark an old function with a //go:fix inline comment directly above its declaration. When users run go fix on their projects, the tool detects all calls to that function and replaces each call site with an inlined copy of the function body, substituting arguments for parameters. This allows authors to safely remove deprecated APIs and migrate users to new versions automatically. For example, if you replace a function OldFunc(x, y int) with a new version NewFunc(x, y int), you can define OldFunc to call NewFunc and add //go:fix inline—then go fix will replace all OldFunc calls with direct calls to NewFunc.

What kinds of subtle issues does the source-level inliner handle?
Inlining a function call is not always a simple text replacement. The inliner must correctly manage scoping, variable naming, and side effects. For instance, if the function’s body uses a variable name that clashes with a name in the caller’s scope, the inliner renames variables to avoid collisions. It also handles return statements (converted to assignments or blocks), defer and recover semantics (which cannot be inlined if they appear in the body), and varargs. The gopls team has thoroughly tested these edge cases, making the transformation safe even for complex functions.
Can the source-level inliner be used for custom analyzers or fix rules?
Yes, the source-level inliner is part of Go’s new self-service modernization framework. While go fix ships with built‑in modernizers for new language features, the inliner allows any developer to write their own migration rules using the //go:fix inline comment. In the future, the Go team may expose more APIs to let third‑party tools define their own fix patterns. For now, adding a //go:fix inline directive to a function declaration is the simplest way to automate cross‑package refactoring without writing a custom analyzer.
What is the future of source-level inlining in Go?
The source-level inliner is a foundational building block for many transformation tools. In Go 1.26, it powers parts of the new go fix and is already used by gopls. The Go team plans to expand the set of directives beyond //go:fix inline to cover more complex migration scenarios. Additionally, we can expect the inliner to support more Go language constructs over time. For now, it handles a wide range of functions safely, and its availability in go fix makes it easy for every Go developer to keep their code modern with minimal effort.