Alan Donovan
10 March 2026
Go 1.26 contains an all-new implementation of the go fix subcommand, designed to help you keep your Go code up-to-date and modern. For an introduction, start by reading our recent post on the topic. In this post, we’ll look at one particular feature, the source-level inliner.
While go fix has several bespoke modernizers for specific new language and library features, the source-level inliner is the first fruit of our efforts to provide “self-service” modernizers and analyzers. It enables any package author to express simple API migrations and updates in a straightforward and safe way. We’ll first explain what the source-level inliner is and how you can use it, then we’ll dive into some aspects of the problem and the technology behind it.
Source-level inlining
In 2023, we built an algorithm for source-level inlining of function calls in Go. To “inline” a call means to replace the call by a copy of the body of the called function, substituting arguments for parameters. We call it “source-level” inlining because it durably modifies the source code. By contrast, the inlining algorithm found in a typical compiler, including Go’s, applies a similar transformation, but to the compiler’s ephemeral intermediate representation, to generate more efficient code.
If you’ve ever invoked gopls’ “Inline call” interactive refactoring, you’ve used the source-level inliner. (In VS Code, this code action can be found on the “Source Action…” menu.) The before-and-after screenshots below show the effect of inlining the call to sum from the function named six .
The inliner is a crucial building block for a number of source transformation tools. For example, gopls uses it for the “Change signature” and “Remove unused parameter” refactorings because, as we’ll see below, it takes care of many subtle correctness issues that arise when refactoring function calls.
This same inliner is also one of the analyzers in the all-new go fix command. In go fix , it enables self-service API migration and upgrades using a new //go:fix inline directive comment. Let’s take a look at a few examples of how this works and what it can be used for.
Example: renaming ioutil.ReadFile
... continue reading