Keyboard shortcuts

Press ← or → to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

Relink Don’t Rebuild

Metadata
ContactMatyas Susits
StatusAccepted
What and whyMassive speedup of rebuilds in large multi-crate projects
RoadmapFast Builds
Tracking issuerust-lang/goals#843
Other tracking issuesrust-lang/rust#158844
Zulip channelt-compiler/relink-dont-rebuild
compiler championVadim Petrochenkov
Teamscargo, compiler
Task ownersVadim Petrochenkov, Matyas Susits

Summary

Implement the MCP Relink Don’t Rebuild, which can give large speedups on certain edits when rebuilding large projects with many crates.

There is an existing implementation (#156940) waiting for review. The first goal is to get that through the review process, integrate with cargo, and get it to nightly users.

Motivation

The status quo

For a long time, the preferred method for speeding up compilation of large projects was to split them into smaller crates. Today, large projects consist of many crates with a complex dependency graph. When a crate is edited, it causes all dependents to recompile, leading to slow compile times even when the edited crate is small.

What we propose to do about it

Calculate the public API hash of crates and only recompile dependents when it changes, greatly improving iteration speed for edits not changing the public API of a crate. This is similar to how C compilers only recompile the edited .c file then relink the final binary. Other code will not get recompiled unless the header file changes.

The largest concern of adding such public API hash is maintainability: adding new language features should automatically get added to the public API hash, otherwise RDR can quickly become riddled with silent miscompiles. The proposed implementation solves this problem by building on the metadata (“header”) files produced by rustc, automatically integrating any new data added to it.

One more concern is the second order effect of implementing RDR without going to the extra mile with how it handles line information. Considering all public item line info changes as public API changes encourages people to write “header style” code. Instead of

#![allow(unused)]
fn main() {
pub fn foo() {
    do_something();
}
}

writing

#![allow(unused)]
fn main() {
pub fn foo() {
    foo_private()
}

fn foo_private() {
    do_something();
}
}

can make the public API more resilient to change. Adding do_something_else() to foo_private does not change the public API, while adding it to foo changes it, which can lead to considerable difference in recompilation speed in a large project, encouraging people to write these “header” functions and make lints for enforcing it. It remains to be discussed whether combating this is desired in the future. There are no plans to do special handling for line info only changes in the first version of RDR.

Work items over the next year

TaskOwner(s)Notes
Split up the existing implementation into smaller PRs, reviewMatyas Susits, Vadim Petrochenkov2 months
Cargo integrationMatyas Susits1 month
Metadata
Timespan2027
TaskOwner(s)Notes
Restore compiler diagnosticsMatyas Susits1 month
Optimize the implementationMatyas Susits2 months
Integrate with rustdocMatyas Susits1 month

Team asks

TeamSupport levelNotes
cargoSmallreview cargo integration
compilerMediumdedicated reviewer

Funding

The duration of the project is 7 months. The two subgoals can be funded independently.

  • Month 1-3 (Usable implementation in nightly)
    • This stage could already provide benefits for nightly users, at the cost of possibly incorrect line info in diagnostics and debuginfo of dependents. This would greatly help cargo check runs in IDE-s, since debuginfo is not a concern there.
    • Some diagnostics will not be available
    • Lot of the work is already done, needs review.
  • Month 4-7 (Prepare for stabilization)
    • Performance optimizations
    • Rustdoc integration
    • Restoring diagnostics
PurposeCostFundedSponsor(s)
Contributor - Nightly implementation$30,000No
Contributor - Prepare for stabilization$40,000No

Frequently asked questions

How does RDR help agentic coding?

Compilation speed directly affects how quickly coding agents can work. Running cargo check and cargo build can take a significant amount of time relative to the time an agent spends actually writing code. Faster compilation therefore translates directly into faster iteration and more productive agents.

The many-worktrees problem

In agentic workflows, different agents typically work in separate Git worktrees. Each worktree can have its own build directory, but duplicating build artifacts for every agent can quickly become prohibitive in terms of disk space.

An alternative is to share a single build directory between agents. However, Cargo locks the build directory during compilation, effectively serializing build operations. The time each compilation takes therefore limits how many agents can efficiently share the same build directory without spending significant time waiting for the lock. This becomes particularly problematic in large projects, where incremental rebuilds can still take considerable time.

RDR can significantly alleviate this bottleneck. When applicable (currently estimated at 50–90% of rebuilds, potentially even more when agents are instructed to write RDR-compatible code), it can make rebuilds an order of magnitude faster. This means less time spent holding the build-directory lock and potentially an order of magnitude more agents sharing the same build directory efficiently.