Why cargo-warm forks build state instead of sharing one target directory.

The problem

A new Git worktree can start from exactly the same revision as a warm checkout and still have a different Cargo build directory. The source is nearly identical, but the first check may behave like a cold build.

Sharing one writable Cargo directory across active worktrees is not the solution. It introduces build locks, contention, path-bearing state, and cross-checkout invalidation.

The seed model

warm checkout build state
          |
          | filesystem COW clone / reflink
          v
new worktree private build state
          |
          +-- Cargo and rustc validate normally

cargo-warm asks cargo metadata for the resolved build_directory and target_directory. It does not duplicate Cargo’s workspace hashing rules.

On modern Cargo versions, build_directory contains the expensive intermediate compiler state and is seeded by default. target_directory is left alone unless --include-target is requested.

Correctness boundary

The copied state is never trusted as the answer. After seeding, ordinary Cargo and rustc freshness and incremental logic runs exactly as it would for any other build directory.

This makes a seed a hint about where to start, not a replacement build system.

That distinction matters for worktree relocation. It is tempting to restore destination source mtimes to the warm checkout so Cargo considers copied local artifacts fresh. cargo-warm deliberately does not do that. Rust code can observe checkout-local compiler inputs such as env!("CARGO_MANIFEST_DIR"); bypassing rustc after relocation can therefore reuse an artifact containing the old checkout path.

What can still miss

Even an exact-base worktree can invalidate state because of:

  • source or build-script mtimes;
  • build-script outputs that contain checkout-local absolute paths;
  • changed environment/configuration;
  • feature or target differences;
  • changed source;
  • rustc incremental query invalidation.

Use cargo warm doctor to separate these failure classes. For an exact clean worktree it identifies mtime skew and build-script boundaries without compiling. cargo warm doctor --probe runs cargo check under Cargo’s fingerprint logger and classifies the actual dirty reasons.

The deeper compiler goal is not to make Cargo blindly accept relocated local artifacts. It is to let Cargo invoke rustc in the destination checkout while rustc starts from a nearby incremental state whose source identities are portable enough that unchanged queries can remain green. Path-sensitive inputs must still be recomputed normally.