Thinking really blue-sky:

I'm imagining the refactoring rules as something that could perhaps ship alongside the library as part of its development release. Like, let's say we've released the latest version of our library which renames A to B. The release could include a refactoring rule that describes how to update from previous versions of the library to the latest version: a rule that identifies all references to A and replaces them with B. References that tooling cannot identify and fix can also still work for a time via the alias feature.

To make these rules easy to author, perhaps we could provide some form of assistance at the source control layer -- perhaps we could infer and propose refactorings based on the diffs that we see. If we see a diff renaming the method A to B, then we could see that and offer to construct a refactoring rule for all consuming code. Or with full IDE support, the IDE refactoring tool could call into the language service refactoring function to construct the rule.

To refactor in this language and platform, you'd rename your method, stage the commit, and then ask the language to analyze the change. It would detect the rename, offer to create a refactoring rule, and then you could accept that rule and apply it to your own code base (internal usage). You could have the option to save that refactoring rule as part of the package release. It could say: when consuming code upgrades from version 7 of this library to version 8 (or commit hash xxx to yyy), apply these refactorings. Indeed, even if the library does not ship refactoring rules -- or as an alternative to that model -- users could run the inference tool on the diff of changes to the library source. Shipping refactoring rules in the release would allow this scheme to work even if users don't have access to library source, though.

Imagine our library has hundreds of consumers on GitHub. When they next pick up a version of our library, and try to build the source, our build system could inform the user that refactorings are available and offer to apply them. The user clicks "accept", reviews the changes, and hopefully the package builds and its tests pass after that.

If we make this system really reliable, then we could apply these changes as the default course of action. Ideally the user would apply the refactorings and commit the changes to their source code, but even if the user doesn't, we could apply the changes to a temporary copy every time they build. Or the compiler could do it semantically for them, depending on how the rules work. This way even users who aren't willing to actively participate can still benefit from the capability. If your consuming package falls far behind the latest library, then the set of refactorings you need to apply to your code in order to build it could grow quite large and brittle, but it may still work (A changes to B today, and is moved into another package tomorrow). Like a rebase of many commits, you'd apply the rules one by one.

The goal would be to make it really easy to ship these refactoring rules as part of releases as a library vendor, and really easy to apply the rules as a consumer. The typical change would be small quality of life changes like renames and moves.

I wonder how a capability like this could transform the way we release software. Today, releasing a breaking change is anathema. It's anathema because we know it causes massive pain for users. If we had the ability to ease that pain, and make the upgrade process really easy or even automatic, then it could perhaps significantly change the way in which we think about interface contracts. Everyone who builds libraries is familiar with a time where you got the interface wrong, and really wish you could change it, but it's too late now because the library is too entrenched. This kind of system would make it possible for us to dig ourselves out of those problems and continuously improve even codebases that are widely used. Of course I have my head in the stars at this point, but I believe that all of this is plausible.

[I'm not a Go user, but these concepts have been something I've wanted to explore as features of a pet programming language I've been designing off-and-on.]