Skip to content

Cargo 1.100's new build-dir layout leaves every new profile unrecognised by both Rust rows #570

Open

Description

@BootBlock

What is missing

CargoTargetLayout recognises a profile directory (debug, release, a custom profile) only when it
holds both a .cargo-lock file and a .fingerprint directory
(CargoTargetLayout.cs:216-217):

private static bool IsProfile(string path) =>
    IsFile(Path.Combine(path, ".cargo-lock")) && IsDirectory(Path.Combine(path, ".fingerprint"));

Cargo 1.100, due for release on 2026-11-12, makes the new build-dir layout the default. In that layout the
profile directory no longer has a .fingerprint directory: each build unit keeps its own
fingerprint folder under build/<package>/<hash>/. So a profile that Cargo 1.100 or later creates
fails IsProfile, and falls through to "Not something Cargo is recognised to have written". Both
rows that read the survey lose it:

  • Rust build output (CargoTargetProvider) offers nothing from that profile.
  • Rust incremental caches (CargoIncrementalProvider) offers nothing either, although
    incremental is still at <profile>\incremental in the new layout, because it reaches
    incremental only through a recognised profile (AddProfile).

Nothing is deleted wrongly. The profile is named as left alone, so the failure is the largest
directory in a Rust developer's source tree silently stopping being offered. A target directory that
an older Cargo built keeps its .fingerprint until it is cleaned, so the loss grows as projects are
cleaned, cloned or created.

Evidence

Researched from source, not measured. No Rust toolchain is installed on the workstation this was
written on.

  • The Cargo changelog for 1.100 (scheduled for 2026-11-12), under Changed: "Cargo now uses a new directory layout
    for intermediate build artifacts. ... The layout is not a stable interface and is subject to change."
    (Cargo changelog, PR
    rust-lang/cargo#17354, "Re-stabilize build-dir
    layout v2", merged 2026-08-18).
  • Cargo's feature table makes the layout the default unless a temporary opt-out variable is set:
    unstable.build_dir_new_layout = !is_new_build_dir_layout_opt_out();, and the old -Z flag now
    warns "build.build-dir-new-layout is now always enabled." with version "1.100"
    (features.rs, lines 847,
    1029 and 1412). The opt-out is __CARGO_TEMPORARY_BUILD_DIR_NEW_LAYOUT_OPT_OUT=1 (line 1629).
  • Cargo's own layout documentation
    (layout.rs, module docs) gives
    the new build-dir profile as .cargo-lock, incremental/ and build/$pkgname/$META/ holding out/,
    fingerprint/ and run/. The old layout's <profile>/.fingerprint/ and <profile>/deps/ are not
    part of it. The artifact directory's profile, when build.build-dir moves the build directory
    elsewhere, holds only .cargo-lock, examples/ and the final artefacts.
  • The build cache reference says the
    build-dir layout "is considered internal to Cargo, and is subject to change", so a rule keyed on any
    one internal folder name will break again.

Proposed scope

  • Tier and route unchanged. Rust build output stays Tier 2 and the incremental cache Tier 1.
    cargo clean stays declined for the reasons in CargoTargetProvider.
  • Recognise a profile by what every Cargo layout writes. .cargo-lock is common to the old layout,
    the new build-dir layout and the artifact directory. Accept a profile with .cargo-lock and at least
    one of: .fingerprint (old layout), or a build directory whose <package>\<hash> children hold a
    fingerprint folder (new layout). Probe one child rather than walking build. Decide whether a
    profile holding .cargo-lock alone (the artifact-directory half when build.build-dir is set) is
    enough evidence beside a manifest and Cargo's cache tag; if not, name it as left alone with a reason
    that says why.
  • Incremental row. Keep reaching incremental through the recognised profile, so it works for both
    layouts once recognition does.
  • Mixed trees. A target that both an old and a new Cargo built holds .fingerprint, deps and
    build/<pkg>/<hash> side by side. All of it is Cargo's, and the profile is removed whole except
    incremental, so no new survivor appears.
  • §5.6 negative. The survivors stay as they are: src and Cargo.lock beside target, and every
    unrecognised child of target (a build script's dist-check, shots, toolchains).
  • Docs. Update the Rust build output section of cache-locations.md and the CargoTargetLayout
    summary to describe both layouts.
  • Tests (CargoTargetLayoutTests): a new-layout profile (.cargo-lock, incremental,
    build\foo\0123abcd\fingerprint) is offered on the build output row and its incremental on the
    incremental row; a mixed profile is offered once; a folder with build\x\y\fingerprint but no
    .cargo-lock stays unrecognised; an unrecognised sibling in target is still named and asserted.
    Prove each by reverting the recognition change and watching the new-layout test fail.

Open questions / blocker

  • A relocated build directory (build.build-dir, CARGO_BUILD_BUILD_DIR, with templates such as
    {cargo-cache-home} and {workspace-path-hash},
    config reference) is not
    found by either row. A template under CARGO_HOME puts it in a child the Cargo crate cache row already
    leaves alone and names, which is safe. Reaching it is a separate design question, because Cargo has
    said it is "considering changing the default location of the build-dir in the future" (Cargo 1.91
    changelog). This issue covers recognition only.

Sources: Cargo changelog;
rust-lang/cargo#17354;
features.rs;
layout.rs;
build cache reference;
config reference;
RELEASES.md (1.99.1 is the current stable, 2026-10-15).

Related: #578.


This issue was opened by an agent on behalf of @BootBlock.

Activity

  1. added
    type: bugSomething is broken, or behaves differently from what the spec describes
    area: coreThe safety model, the providers, the planner and execution in Deguffer.Core
    safetyTouches what gets deleted, the tier model, or the §5.6 negative assertion
    area: providersAn individual ICleanupProvider: npm, NuGet, pip, Gradle, uv, PlatformIO, Playwright and the rest
    area: docsThe spec, the plan documents under docs/todo, and the README
    status: readyScoped and understood; ready for someone to pick up
    effort: large1 to 2 hours of agent time: several areas, and a plan of its own before starting
    priority: highShould be picked up ahead of other work
    on Nov 8, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    area: coreThe safety model, the providers, the planner and execution in Deguffer.Corearea: docsThe spec, the plan documents under docs/todo, and the READMEarea: providersAn individual ICleanupProvider: npm, NuGet, pip, Gradle, uv, PlatformIO, Playwright and the resteffort: large1 to 2 hours of agent time: several areas, and a plan of its own before startingpriority: highShould be picked up ahead of other worksafetyTouches what gets deleted, the tier model, or the §5.6 negative assertionstatus: readyScoped and understood; ready for someone to pick uptype: bugSomething is broken, or behaves differently from what the spec describes

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions