Public in private manifest errors (#16002)

### What does this PR try to resolve?

This is a stab at #13096, adding Cargo.toml context to public-in-private
errors. It intercepts public-in-private warnings from rustc and modifies
them by adding a little context.

I had a bit of difficulty with renamed crates (like, `foo_renamed = {
version = "0.1.0", package = "foo" }`). Surprisingly for me, rustc's
errors mention the original package name (foo) and not the renamed one
(foo_renamed), even though the renamed one is that one that's guaranteed
unique. This PR does its best to figure out which package is the one
being referred to, but if there's non-uniqueness involved then it just
gives up and doesn't provide context.
diff --git a/.github/workflows/audit.yml b/.github/workflows/audit.yml
index ea126fc..cb18330 100644
--- a/.github/workflows/audit.yml
+++ b/.github/workflows/audit.yml
@@ -21,7 +21,7 @@
           - advisories
           - bans licenses sources
     steps:
-    - uses: actions/checkout@v4
+    - uses: actions/checkout@v5
     - uses: EmbarkStudios/cargo-deny-action@v2
       # Prevent sudden announcement of a new advisory from failing ci:
       continue-on-error: ${{ matrix.checks == 'advisories' }}
diff --git a/.github/workflows/contrib.yml b/.github/workflows/contrib.yml
index 15f6e76..fbf9105 100644
--- a/.github/workflows/contrib.yml
+++ b/.github/workflows/contrib.yml
@@ -17,7 +17,7 @@
       contents: write  # for Git to git push
     runs-on: ubuntu-latest
     steps:
-    - uses: actions/checkout@v4
+    - uses: actions/checkout@v5
       with:
         fetch-depth: 0
     - name: Install mdbook
diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml
index 3845469..5ced196 100644
--- a/.github/workflows/main.yml
+++ b/.github/workflows/main.yml
@@ -53,7 +53,7 @@
   rustfmt:
     runs-on: ubuntu-latest
     steps:
-    - uses: actions/checkout@v4
+    - uses: actions/checkout@v5
     - run: rustup update stable && rustup default stable
     - run: rustup component add rustfmt
     - run: cargo fmt --all --check
@@ -62,7 +62,7 @@
   clippy:
     runs-on: ubuntu-latest
     steps:
-      - uses: actions/checkout@v4
+      - uses: actions/checkout@v5
       - run: rustup update stable && rustup default stable
       - run: rustup component add clippy
       - run: cargo clippy --workspace --all-targets --no-deps -- -D warnings
@@ -70,14 +70,14 @@
   stale-label:
     runs-on: ubuntu-latest
     steps:
-      - uses: actions/checkout@v4
+      - uses: actions/checkout@v5
       - run: rustup update stable && rustup default stable
       - run: cargo stale-label
 
   lint-docs:
     runs-on: ubuntu-latest
     steps:
-      - uses: actions/checkout@v4
+      - uses: actions/checkout@v5
       - run: rustup update stable && rustup default stable
       - run: cargo lint-docs --check
 
@@ -85,7 +85,7 @@
   lockfile:
     runs-on: ubuntu-latest
     steps:
-      - uses: actions/checkout@v4
+      - uses: actions/checkout@v5
       - run: rustup update stable && rustup default stable
       - run: cargo update -p cargo --locked
 
@@ -96,7 +96,7 @@
       BASE_SHA: ${{ github.event.pull_request.base.sha }}
       HEAD_SHA: ${{ github.event.pull_request.head.sha != '' && github.event.pull_request.head.sha || github.sha  }}
     steps:
-      - uses: actions/checkout@v4
+      - uses: actions/checkout@v5
         with:
           fetch-depth: 0
       - run: rustup update stable && rustup default stable
@@ -170,7 +170,7 @@
           other: i686-pc-windows-gnu
     name: Tests ${{ matrix.name }}
     steps:
-    - uses: actions/checkout@v4
+    - uses: actions/checkout@v5
     - name: Dump Environment
       run: ci/dump-environment.sh
     # Some tests require stable. Make sure it is set to the most recent stable
@@ -236,21 +236,21 @@
   schema:
     runs-on: ubuntu-latest
     steps:
-    - uses: actions/checkout@v4
+    - uses: actions/checkout@v5
     - run: rustup update stable && rustup default stable
     - run: cargo test -p cargo-util-schemas -F unstable-schema
 
   resolver:
     runs-on: ubuntu-latest
     steps:
-    - uses: actions/checkout@v4
+    - uses: actions/checkout@v5
     - run: rustup update stable && rustup default stable
     - run: cargo test -p resolver-tests
 
   test_gitoxide:
     runs-on: ubuntu-latest
     steps:
-      - uses: actions/checkout@v4
+      - uses: actions/checkout@v5
       - run: rustup update --no-self-update stable && rustup default stable
       - run: rustup target add i686-unknown-linux-gnu
       - run: rustup target add wasm32-unknown-unknown
@@ -263,7 +263,7 @@
   build_std:
     runs-on: ubuntu-latest
     steps:
-    - uses: actions/checkout@v4
+    - uses: actions/checkout@v5
     - run: rustup update nightly && rustup default nightly
     - run: rustup component add rust-src
     - run: cargo build
@@ -273,10 +273,11 @@
   docs:
     runs-on: ubuntu-latest
     steps:
-    - uses: actions/checkout@v4
+    - uses: actions/checkout@v5
     - run: rustup update nightly && rustup default nightly
     - run: rustup update stable
     - run: rustup component add rust-docs
+    - run: rustup component add rustfmt --toolchain stable
     - run: ci/validate-man.sh
     # This requires rustfmt, use stable.
     - name: Run semver-check
@@ -300,6 +301,6 @@
   msrv:
     runs-on: ubuntu-latest
     steps:
-    - uses: actions/checkout@v4
+    - uses: actions/checkout@v5
     - uses: taiki-e/install-action@cargo-hack
     - run: cargo hack check --all-targets --rust-version --workspace --ignore-private --locked
diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml
index 0b31b6a..b329e71 100644
--- a/.github/workflows/release.yml
+++ b/.github/workflows/release.yml
@@ -25,7 +25,7 @@
 
     steps:
       - name: Checkout the source code
-        uses: actions/checkout@v4
+        uses: actions/checkout@v5
 
       - name: Publish Cargo to crates.io
         run: ./publish.py
diff --git a/Cargo.lock b/Cargo.lock
index 95fae29..1e812c1 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -319,7 +319,7 @@
 
 [[package]]
 name = "cargo"
-version = "0.92.0"
+version = "0.93.0"
 dependencies = [
  "annotate-snippets",
  "anstream",
@@ -331,7 +331,7 @@
  "cargo-credential-libsecret",
  "cargo-credential-macos-keychain",
  "cargo-credential-wincred",
- "cargo-platform 0.3.1",
+ "cargo-platform 0.3.2",
  "cargo-test-support",
  "cargo-util",
  "cargo-util-schemas 0.10.2",
@@ -461,9 +461,10 @@
 
 [[package]]
 name = "cargo-platform"
-version = "0.3.1"
+version = "0.3.2"
 dependencies = [
  "serde",
+ "serde_core",
 ]
 
 [[package]]
@@ -472,7 +473,7 @@
 
 [[package]]
 name = "cargo-test-support"
-version = "0.8.2"
+version = "0.9.0"
 dependencies = [
  "anstream",
  "anstyle",
@@ -3710,7 +3711,7 @@
 version = "0.0.0"
 dependencies = [
  "cargo",
- "cargo-platform 0.3.1",
+ "cargo-platform 0.3.2",
  "cargo-util",
  "cargo-util-schemas 0.10.2",
  "proptest",
@@ -3970,10 +3971,11 @@
 
 [[package]]
 name = "serde"
-version = "1.0.219"
+version = "1.0.226"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "5f0e2c6ed6606019b4e29e69dbaba95b11854410e5347d525002456dbbb786b6"
+checksum = "0dca6411025b24b60bfa7ec1fe1f8e710ac09782dca409ee8237ba74b51295fd"
 dependencies = [
+ "serde_core",
  "serde_derive",
 ]
 
@@ -3999,10 +4001,19 @@
 ]
 
 [[package]]
-name = "serde_derive"
-version = "1.0.219"
+name = "serde_core"
+version = "1.0.226"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "5b0276cf7f2c73365f7157c8123c21cd9a50fbbd844757af28ca1f5925fc2a00"
+checksum = "ba2ba63999edb9dac981fb34b3e5c0d111a69b0924e253ed29d83f7c99e966a4"
+dependencies = [
+ "serde_derive",
+]
+
+[[package]]
+name = "serde_derive"
+version = "1.0.226"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "8db53ae22f34573731bafa1db20f04027b2d25e02d8205921b569171699cdb33"
 dependencies = [
  "proc-macro2",
  "quote",
diff --git a/Cargo.toml b/Cargo.toml
index 132360d..802a767 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -32,7 +32,7 @@
 cargo-credential-wincred = { version = "0.4.18", path = "credential/cargo-credential-wincred" }
 cargo-platform = { path = "crates/cargo-platform", version = "0.3.0" }
 cargo-test-macro = { version = "0.4.7", path = "crates/cargo-test-macro" }
-cargo-test-support = { version = "0.8.2", path = "crates/cargo-test-support" }
+cargo-test-support = { version = "0.9.0", path = "crates/cargo-test-support" }
 cargo-util = { version = "0.2.25", path = "crates/cargo-util" }
 cargo-util-schemas = { version = "0.10.1", path = "crates/cargo-util-schemas" }
 cargo_metadata = "0.21.0"
@@ -89,7 +89,8 @@
 schemars = "1.0.4"
 security-framework = "3.3.0"
 semver = { version = "1.0.26", features = ["serde"] }
-serde = "1.0.219"
+serde = "1.0.220"
+serde_core = "1.0.220"
 serde-untagged = "0.1.7"
 serde-value = "0.7.0"
 serde_ignored = "0.1.12"
@@ -137,7 +138,7 @@
 
 [package]
 name = "cargo"
-version = "0.92.0"
+version = "0.93.0"
 edition.workspace = true
 license.workspace = true
 rust-version = "1.90"  # MSRV:1
diff --git a/crates/cargo-platform/Cargo.toml b/crates/cargo-platform/Cargo.toml
index 48f1387..f2a530d 100644
--- a/crates/cargo-platform/Cargo.toml
+++ b/crates/cargo-platform/Cargo.toml
@@ -1,6 +1,6 @@
 [package]
 name = "cargo-platform"
-version = "0.3.1"
+version = "0.3.2"
 edition.workspace = true
 license.workspace = true
 rust-version.workspace = true
@@ -10,6 +10,11 @@
 description = "Cargo's representation of a target platform."
 
 [dependencies]
+serde_core.workspace = true
+
+# serde v1.0.220 is the first version that released with `serde_core`.
+# This is required to avoid conflict with other `serde` users which may require an older version.
+[target.'cfg(any())'.dependencies]
 serde.workspace = true
 
 [lints]
diff --git a/crates/cargo-platform/src/lib.rs b/crates/cargo-platform/src/lib.rs
index 96b2485..9585e2e 100644
--- a/crates/cargo-platform/src/lib.rs
+++ b/crates/cargo-platform/src/lib.rs
@@ -140,22 +140,22 @@
     }
 }
 
-impl serde::Serialize for Platform {
+impl serde_core::Serialize for Platform {
     fn serialize<S>(&self, s: S) -> Result<S::Ok, S::Error>
     where
-        S: serde::Serializer,
+        S: serde_core::Serializer,
     {
         self.to_string().serialize(s)
     }
 }
 
-impl<'de> serde::Deserialize<'de> for Platform {
+impl<'de> serde_core::Deserialize<'de> for Platform {
     fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
     where
-        D: serde::Deserializer<'de>,
+        D: serde_core::Deserializer<'de>,
     {
         let s = String::deserialize(deserializer)?;
-        FromStr::from_str(&s).map_err(serde::de::Error::custom)
+        FromStr::from_str(&s).map_err(serde_core::de::Error::custom)
     }
 }
 
diff --git a/crates/cargo-test-support/Cargo.toml b/crates/cargo-test-support/Cargo.toml
index 13d086b..e9e6406 100644
--- a/crates/cargo-test-support/Cargo.toml
+++ b/crates/cargo-test-support/Cargo.toml
@@ -1,6 +1,6 @@
 [package]
 name = "cargo-test-support"
-version = "0.8.2"
+version = "0.9.0"
 edition.workspace = true
 rust-version = "1.90"  # MSRV:1
 license.workspace = true
diff --git a/crates/cargo-test-support/containers/sshd/Dockerfile b/crates/cargo-test-support/containers/sshd/Dockerfile
index 14c1f42..294533f 100644
--- a/crates/cargo-test-support/containers/sshd/Dockerfile
+++ b/crates/cargo-test-support/containers/sshd/Dockerfile
@@ -1,6 +1,7 @@
 FROM alpine:3.22
 
 RUN apk add --no-cache openssh git
+RUN apk upgrade --no-cache libcrypto3
 RUN ssh-keygen -A
 
 RUN addgroup -S testuser && adduser -S testuser -G testuser -s /bin/ash
diff --git a/crates/cargo-test-support/src/compare.rs b/crates/cargo-test-support/src/compare.rs
index f1f3e4c..2338d81 100644
--- a/crates/cargo-test-support/src/compare.rs
+++ b/crates/cargo-test-support/src/compare.rs
@@ -229,6 +229,12 @@
     .unwrap();
     subs.insert("[HASH]", regex!(r"/[a-z0-9\-_]+-(?<redacted>[0-9a-f]{16})"))
         .unwrap();
+    // Match multi-part hashes like `06/b451d0d6f88b1d` used in directory paths
+    subs.insert("[HASH]", regex!(r"/(?<redacted>[a-f0-9]{2}\/[0-9a-f]{14})"))
+        .unwrap();
+    // Match file name hashes like `foo-06b451d0d6f88b1d`
+    subs.insert("[HASH]", regex!(r"[a-z0-9]+-(?<redacted>[a-f0-9]{16})"))
+        .unwrap();
     subs.insert(
         "[AVG_ELAPSED]",
         regex!(r"(?<redacted>[0-9]+(\.[0-9]+)?) ns/iter"),
diff --git a/crates/cargo-test-support/src/paths.rs b/crates/cargo-test-support/src/paths.rs
index cc6119b..10a0283 100644
--- a/crates/cargo-test-support/src/paths.rs
+++ b/crates/cargo-test-support/src/paths.rs
@@ -1,6 +1,8 @@
 //! Access common paths and manipulate the filesystem
 
 use filetime::FileTime;
+use itertools::Itertools;
+use walkdir::WalkDir;
 
 use std::cell::RefCell;
 use std::env;
@@ -12,6 +14,9 @@
 use std::sync::OnceLock;
 use std::sync::atomic::{AtomicUsize, Ordering};
 
+use crate::compare::assert_e2e;
+use crate::compare::match_contains;
+
 static CARGO_INTEGRATION_TEST_DIR: &str = "cit";
 
 static GLOBAL_ROOT: OnceLock<Mutex<Option<PathBuf>>> = OnceLock::new();
@@ -152,6 +157,10 @@
     fn move_in_time<F>(&self, travel_amount: F)
     where
         F: Fn(i64, u32) -> (i64, u32);
+
+    fn assert_build_dir_layout(&self, expected: impl snapbox::IntoData);
+
+    fn assert_dir_layout(&self, expected: impl snapbox::IntoData, ignored_path_patterns: &[String]);
 }
 
 impl CargoPathExt for Path {
@@ -236,6 +245,43 @@
             });
         }
     }
+
+    #[track_caller]
+    fn assert_build_dir_layout(&self, expected: impl snapbox::IntoData) {
+        // We call `unordered()` here to because the build-dir has some scenarios that make
+        // consistent ordering not possible.
+        // Notably:
+        // 1. Binaries with `.exe` on Windows causing the ordering to change with the dep-info `.d`
+        //    file.
+        // 2. Directories with hashes are often reordered differently by platform.
+        self.assert_dir_layout(expected.unordered(), &build_dir_ignored_path_patterns());
+    }
+
+    #[track_caller]
+    fn assert_dir_layout(
+        &self,
+        expected: impl snapbox::IntoData,
+        ignored_path_patterns: &[String],
+    ) {
+        let assert = assert_e2e();
+        let actual = WalkDir::new(self)
+            .sort_by_file_name()
+            .into_iter()
+            .filter_map(|e| e.ok())
+            .filter(|e| e.file_type().is_file())
+            .map(|e| e.path().to_string_lossy().into_owned())
+            .filter(|file| {
+                for ignored in ignored_path_patterns {
+                    if match_contains(&ignored, file, &assert.redactions()).is_ok() {
+                        return false;
+                    }
+                }
+                return true;
+            })
+            .join("\n");
+
+        assert.eq(format!("{actual}\n"), expected);
+    }
 }
 
 impl CargoPathExt for PathBuf {
@@ -260,6 +306,21 @@
     {
         self.as_path().move_in_time(travel_amount)
     }
+
+    #[track_caller]
+    fn assert_build_dir_layout(&self, expected: impl snapbox::IntoData) {
+        self.as_path().assert_build_dir_layout(expected);
+    }
+
+    #[track_caller]
+    fn assert_dir_layout(
+        &self,
+        expected: impl snapbox::IntoData,
+        ignored_path_patterns: &[String],
+    ) {
+        self.as_path()
+            .assert_dir_layout(expected, ignored_path_patterns);
+    }
 }
 
 fn do_op<F>(path: &Path, desc: &str, mut f: F)
@@ -290,6 +351,20 @@
     }
 }
 
+/// The paths to ignore when [`CargoPathExt::assert_build_dir_layout`] is called
+fn build_dir_ignored_path_patterns() -> Vec<String> {
+    vec![
+        // Ignore MacOS debug symbols as there are many files/directories that would clutter up
+        // tests few not a lot of benefit.
+        "[..].dSYM/[..]",
+        // Ignore Windows debub symbols files (.pdb)
+        "[..].pdb",
+    ]
+    .into_iter()
+    .map(ToString::to_string)
+    .collect()
+}
+
 /// Get the filename for a library.
 ///
 /// `kind` should be one of:
diff --git a/crates/cargo-util-schemas/src/lockfile.rs b/crates/cargo-util-schemas/src/lockfile.rs
index c953c79..9213e12 100644
--- a/crates/cargo-util-schemas/src/lockfile.rs
+++ b/crates/cargo-util-schemas/src/lockfile.rs
@@ -109,9 +109,13 @@
             EncodableSourceIdError(EncodableSourceIdErrorKind::InvalidSource(source.clone()).into())
         })?;
 
-        let url = Url::parse(url).map_err(|msg| EncodableSourceIdErrorKind::InvalidUrl {
-            url: url.to_string(),
-            msg: msg.to_string(),
+        // Sparse URLs store the kind prefix (sparse+) in the URL. Therefore, for sparse kinds, we
+        // want to use the raw `source` instead of the splitted `url`.
+        let url = Url::parse(if kind == "sparse" { &source } else { url }).map_err(|msg| {
+            EncodableSourceIdErrorKind::InvalidUrl {
+                url: url.to_string(),
+                msg: msg.to_string(),
+            }
         })?;
 
         let kind = match kind {
@@ -317,3 +321,83 @@
     let dump = serde_json::to_string_pretty(&schema).unwrap();
     snapbox::assert_data_eq!(dump, snapbox::file!("../lockfile.schema.json").raw());
 }
+
+#[cfg(test)]
+mod tests {
+    use crate::core::{GitReference, SourceKind};
+    use crate::lockfile::{EncodableSourceIdErrorKind, TomlLockfileSourceId};
+
+    #[track_caller]
+    fn ok(source_str: &str, source_kind: SourceKind, url: &str) {
+        let source_str = source_str.to_owned();
+        let source_id = TomlLockfileSourceId::new(source_str).unwrap();
+        assert_eq!(source_id.kind, source_kind);
+        assert_eq!(source_id.url().to_string(), url);
+    }
+
+    macro_rules! err {
+        ($src:expr, $expected:pat) => {
+            let kind = TomlLockfileSourceId::new($src.to_owned()).unwrap_err().0;
+            assert!(
+                matches!(kind, $expected),
+                "`{}` parse error mismatch, got {kind:?}",
+                $src,
+            );
+        };
+    }
+
+    #[test]
+    fn good_sources() {
+        ok(
+            "sparse+https://my-crates.io",
+            SourceKind::SparseRegistry,
+            "sparse+https://my-crates.io",
+        );
+        ok(
+            "registry+https://github.com/rust-lang/crates.io-index",
+            SourceKind::Registry,
+            "https://github.com/rust-lang/crates.io-index",
+        );
+        ok(
+            "git+https://github.com/rust-lang/cargo",
+            SourceKind::Git(GitReference::DefaultBranch),
+            "https://github.com/rust-lang/cargo",
+        );
+        ok(
+            "git+https://github.com/rust-lang/cargo?branch=dev",
+            SourceKind::Git(GitReference::Branch("dev".to_owned())),
+            "https://github.com/rust-lang/cargo?branch=dev",
+        );
+        ok(
+            "git+https://github.com/rust-lang/cargo?tag=v1.0",
+            SourceKind::Git(GitReference::Tag("v1.0".to_owned())),
+            "https://github.com/rust-lang/cargo?tag=v1.0",
+        );
+        ok(
+            "git+https://github.com/rust-lang/cargo?rev=refs/pull/493/head",
+            SourceKind::Git(GitReference::Rev("refs/pull/493/head".to_owned())),
+            "https://github.com/rust-lang/cargo?rev=refs/pull/493/head",
+        );
+        ok(
+            "path+file:///path/to/root",
+            SourceKind::Path,
+            "file:///path/to/root",
+        );
+    }
+
+    #[test]
+    fn bad_sources() {
+        err!(
+            "unknown+https://my-crates.io",
+            EncodableSourceIdErrorKind::UnsupportedSource(..)
+        );
+        err!(
+            "registry+https//github.com/rust-lang/crates.io-index",
+            EncodableSourceIdErrorKind::InvalidUrl { .. }
+        );
+        err!(
+            "https//github.com/rust-lang/crates.io-index",
+            EncodableSourceIdErrorKind::InvalidSource(..)
+        );
+    }
+}
diff --git a/src/cargo/core/compiler/compile_kind.rs b/src/cargo/core/compiler/compile_kind.rs
index e9fe546..36b41c9 100644
--- a/src/cargo/core/compiler/compile_kind.rs
+++ b/src/cargo/core/compiler/compile_kind.rs
@@ -87,10 +87,10 @@
             let deduplicated_targets = targets
                 .iter()
                 .map(|value| {
-                    // This neatly substitutes the manually-specified `host` target directive
+                    // This neatly substitutes the manually-specified `host-tuple` target directive
                     // with the compiling machine's target triple.
 
-                    if value.as_str() == "host" {
+                    if value.as_str() == "host-tuple" {
                         let host_triple = env!("RUST_HOST_TARGET");
                         Ok(CompileKind::Target(CompileTarget::new(host_triple)?))
                     } else {
diff --git a/src/cargo/core/registry.rs b/src/cargo/core/registry.rs
index d116c1e..9bc4d82 100644
--- a/src/cargo/core/registry.rs
+++ b/src/cargo/core/registry.rs
@@ -800,11 +800,9 @@
 
     #[tracing::instrument(skip_all)]
     fn block_until_ready(&mut self) -> CargoResult<()> {
-        if cfg!(debug_assertions) {
-            // Force borrow to catch invalid borrows, regardless of which source is used and how it
-            // happens to behave this time
-            self.gctx.shell().verbosity();
-        }
+        // Ensure `shell` is not already in use,
+        // regardless of which source is used and how it happens to behave this time
+        self.gctx.debug_assert_shell_not_borrowed();
         for (source_id, source) in self.sources.sources_mut() {
             source
                 .block_until_ready()
diff --git a/src/cargo/core/shell.rs b/src/cargo/core/shell.rs
index 8ac6e6f..6a5077d 100644
--- a/src/cargo/core/shell.rs
+++ b/src/cargo/core/shell.rs
@@ -65,7 +65,7 @@
     }
 
     /// Creates a shell from a plain writable object, with no color, and max verbosity.
-    pub fn from_write(out: Box<dyn Write>) -> Shell {
+    pub fn from_write(out: Box<dyn Write + Send + Sync>) -> Shell {
         Shell {
             output: ShellOut::Write(AutoStream::never(out)), // strip all formatting on write
             verbosity: Verbosity::Verbose,
@@ -168,11 +168,11 @@
         self.print(&status, Some(&message), &HEADER, true)
     }
 
-    pub fn status_header<T>(&mut self, status: T) -> CargoResult<()>
+    pub fn transient_status<T>(&mut self, status: T) -> CargoResult<()>
     where
         T: fmt::Display,
     {
-        self.print(&status, None, &NOTE, true)
+        self.print(&status, None, &TRANSIENT, true)
     }
 
     /// Shortcut to right-align a status message.
@@ -227,7 +227,10 @@
 
     /// Prints a cyan 'note' message.
     pub fn note<T: fmt::Display>(&mut self, message: T) -> CargoResult<()> {
-        self.print(&"note", Some(&message), &NOTE, false)
+        let report = &[annotate_snippets::Group::with_title(
+            annotate_snippets::Level::NOTE.secondary_title(message.to_string()),
+        )];
+        self.print_report(report, false)
     }
 
     /// Updates the verbosity of the shell.
@@ -432,7 +435,7 @@
 /// A `Write`able object, either with or without color support
 enum ShellOut {
     /// A plain write object without color support
-    Write(AutoStream<Box<dyn Write>>),
+    Write(AutoStream<Box<dyn Write + Send + Sync>>),
     /// Color-enabled stdio, with information on whether color should be used
     Stream {
         stdout: AutoStream<std::io::Stdout>,
diff --git a/src/cargo/core/workspace.rs b/src/cargo/core/workspace.rs
index 1db728d..fc20aa2 100644
--- a/src/cargo/core/workspace.rs
+++ b/src/cargo/core/workspace.rs
@@ -25,7 +25,9 @@
 use crate::util::edit_distance;
 use crate::util::errors::{CargoResult, ManifestError};
 use crate::util::interning::InternedString;
-use crate::util::lints::{analyze_cargo_lints_table, check_im_a_teapot};
+use crate::util::lints::{
+    analyze_cargo_lints_table, blanket_hint_mostly_unused, check_im_a_teapot,
+};
 use crate::util::toml::{InheritableFields, read_manifest};
 use crate::util::{
     Filesystem, GlobalContext, IntoUrl, context::CargoResolverConfig, context::ConfigRelativePath,
@@ -409,10 +411,7 @@
     }
 
     pub fn profiles(&self) -> Option<&TomlProfiles> {
-        match self.root_maybe() {
-            MaybePackage::Package(p) => p.manifest().profiles(),
-            MaybePackage::Virtual(vm) => vm.profiles(),
-        }
+        self.root_maybe().profiles()
     }
 
     /// Returns the root path of this workspace.
@@ -907,10 +906,7 @@
 
     /// Returns the unstable nightly-only features enabled via `cargo-features` in the manifest.
     pub fn unstable_features(&self) -> &Features {
-        match self.root_maybe() {
-            MaybePackage::Package(p) => p.manifest().unstable_features(),
-            MaybePackage::Virtual(vm) => vm.unstable_features(),
-        }
+        self.root_maybe().unstable_features()
     }
 
     pub fn resolve_behavior(&self) -> ResolveBehavior {
@@ -1206,14 +1202,17 @@
 
     pub fn emit_warnings(&self) -> CargoResult<()> {
         let mut first_emitted_error = None;
+
+        if let Err(e) = self.emit_ws_lints() {
+            first_emitted_error = Some(e);
+        }
+
         for (path, maybe_pkg) in &self.packages.packages {
             if let MaybePackage::Package(pkg) = maybe_pkg {
-                if self.gctx.cli_unstable().cargo_lints {
-                    if let Err(e) = self.emit_lints(pkg, &path)
-                        && first_emitted_error.is_none()
-                    {
-                        first_emitted_error = Some(e);
-                    }
+                if let Err(e) = self.emit_pkg_lints(pkg, &path)
+                    && first_emitted_error.is_none()
+                {
+                    first_emitted_error = Some(e);
                 }
             }
             let warnings = match maybe_pkg {
@@ -1248,7 +1247,7 @@
         }
     }
 
-    pub fn emit_lints(&self, pkg: &Package, path: &Path) -> CargoResult<()> {
+    pub fn emit_pkg_lints(&self, pkg: &Package, path: &Path) -> CargoResult<()> {
         let mut error_count = 0;
         let toml_lints = pkg
             .manifest()
@@ -1262,26 +1261,74 @@
             .cloned()
             .unwrap_or(manifest::TomlToolLints::default());
 
-        let ws_contents = match self.root_maybe() {
-            MaybePackage::Package(pkg) => pkg.manifest().contents(),
-            MaybePackage::Virtual(v) => v.contents(),
-        };
+        let ws_contents = self.root_maybe().contents();
 
-        let ws_document = match self.root_maybe() {
-            MaybePackage::Package(pkg) => pkg.manifest().document(),
-            MaybePackage::Virtual(v) => v.document(),
-        };
+        let ws_document = self.root_maybe().document();
 
-        analyze_cargo_lints_table(
-            pkg,
-            &path,
-            &cargo_lints,
-            ws_contents,
-            ws_document,
-            self.root_manifest(),
-            self.gctx,
-        )?;
-        check_im_a_teapot(pkg, &path, &cargo_lints, &mut error_count, self.gctx)?;
+        if self.gctx.cli_unstable().cargo_lints {
+            analyze_cargo_lints_table(
+                pkg,
+                &path,
+                &cargo_lints,
+                ws_contents,
+                ws_document,
+                self.root_manifest(),
+                self.gctx,
+            )?;
+            check_im_a_teapot(pkg, &path, &cargo_lints, &mut error_count, self.gctx)?;
+        }
+
+        if error_count > 0 {
+            Err(crate::util::errors::AlreadyPrintedError::new(anyhow!(
+                "encountered {error_count} errors(s) while running lints"
+            ))
+            .into())
+        } else {
+            Ok(())
+        }
+    }
+
+    pub fn emit_ws_lints(&self) -> CargoResult<()> {
+        let mut error_count = 0;
+
+        let cargo_lints = match self.root_maybe() {
+            MaybePackage::Package(pkg) => {
+                let toml = pkg.manifest().normalized_toml();
+                if let Some(ws) = &toml.workspace {
+                    ws.lints.as_ref()
+                } else {
+                    toml.lints.as_ref().map(|l| &l.lints)
+                }
+            }
+            MaybePackage::Virtual(vm) => vm
+                .normalized_toml()
+                .workspace
+                .as_ref()
+                .unwrap()
+                .lints
+                .as_ref(),
+        }
+        .and_then(|t| t.get("cargo"))
+        .cloned()
+        .unwrap_or(manifest::TomlToolLints::default());
+
+        if self.gctx.cli_unstable().cargo_lints {
+            // Calls to lint functions go in here
+        }
+
+        // This is a short term hack to allow `blanket_hint_mostly_unused`
+        // to run without requiring `-Zcargo-lints`, which should hopefully
+        // improve the testing expierience while we are collecting feedback
+        if self.gctx.cli_unstable().profile_hint_mostly_unused {
+            blanket_hint_mostly_unused(
+                self.root_maybe(),
+                self.root_manifest(),
+                &cargo_lints,
+                &mut error_count,
+                self.gctx,
+            )?;
+        }
+
         if error_count > 0 {
             Err(crate::util::errors::AlreadyPrintedError::new(anyhow!(
                 "encountered {error_count} errors(s) while running lints"
@@ -1888,6 +1935,41 @@
             MaybePackage::Virtual(_) => false,
         }
     }
+
+    pub fn contents(&self) -> &str {
+        match self {
+            MaybePackage::Package(p) => p.manifest().contents(),
+            MaybePackage::Virtual(v) => v.contents(),
+        }
+    }
+
+    pub fn document(&self) -> &toml::Spanned<toml::de::DeTable<'static>> {
+        match self {
+            MaybePackage::Package(p) => p.manifest().document(),
+            MaybePackage::Virtual(v) => v.document(),
+        }
+    }
+
+    pub fn edition(&self) -> Edition {
+        match self {
+            MaybePackage::Package(p) => p.manifest().edition(),
+            MaybePackage::Virtual(_) => Edition::default(),
+        }
+    }
+
+    pub fn profiles(&self) -> Option<&TomlProfiles> {
+        match self {
+            MaybePackage::Package(p) => p.manifest().profiles(),
+            MaybePackage::Virtual(v) => v.profiles(),
+        }
+    }
+
+    pub fn unstable_features(&self) -> &Features {
+        match self {
+            MaybePackage::Package(p) => p.manifest().unstable_features(),
+            MaybePackage::Virtual(vm) => vm.unstable_features(),
+        }
+    }
 }
 
 impl WorkspaceRootConfig {
@@ -2037,7 +2119,7 @@
 ) -> CargoResult<Option<PathBuf>> {
     // Check if there are any workspace roots that have already been found that would work
     {
-        let roots = gctx.ws_roots.borrow();
+        let roots = gctx.ws_roots();
         // Iterate through the manifests parent directories until we find a workspace
         // root. Note we skip the first item since that is just the path itself
         for current in manifest_path.ancestors().skip(1) {
diff --git a/src/cargo/sources/git/utils.rs b/src/cargo/sources/git/utils.rs
index e0346aa..e9c8dbd 100644
--- a/src/cargo/sources/git/utils.rs
+++ b/src/cargo/sources/git/utils.rs
@@ -6,7 +6,7 @@
 use crate::sources::git::oxide;
 use crate::sources::git::oxide::cargo_config_to_gitoxide_overrides;
 use crate::util::HumanBytes;
-use crate::util::errors::CargoResult;
+use crate::util::errors::{CargoResult, GitCliError};
 use crate::util::{GlobalContext, IntoUrl, MetricsCounter, Progress, network};
 use anyhow::{Context as _, anyhow};
 use cargo_util::{ProcessBuilder, paths};
@@ -1110,7 +1110,11 @@
         .cwd(repo.path());
     gctx.shell()
         .verbose(|s| s.status("Running", &cmd.to_string()))?;
-    cmd.exec()?;
+    network::retry::with_retry(gctx, || {
+        cmd.exec()
+            .map_err(|error| GitCliError::new(error, true).into())
+    })?;
+
     Ok(())
 }
 
@@ -1528,7 +1532,7 @@
         "https://api.github.com/repos/{}/{}/commits/{}",
         username, repository, github_branch_name,
     );
-    let mut handle = gctx.http()?.borrow_mut();
+    let mut handle = gctx.http()?.lock().unwrap();
     debug!("attempting GitHub fast path for {}", url);
     handle.get(true)?;
     handle.url(&url)?;
diff --git a/src/cargo/util/cache_lock.rs b/src/cargo/util/cache_lock.rs
index afd06c9..068e1bb 100644
--- a/src/cargo/util/cache_lock.rs
+++ b/src/cargo/util/cache_lock.rs
@@ -91,8 +91,8 @@
 use crate::CargoResult;
 use crate::GlobalContext;
 use anyhow::Context as _;
-use std::cell::RefCell;
 use std::io;
+use std::sync::Mutex;
 
 /// The style of lock to acquire.
 #[derive(Copy, Clone, Debug, PartialEq)]
@@ -435,7 +435,11 @@
 impl Drop for CacheLock<'_> {
     fn drop(&mut self) {
         use CacheLockMode::*;
-        let mut state = self.locker.state.borrow_mut();
+        let mut state = match self.locker.state.lock() {
+            Ok(result) => result,
+            // we should release the cache even if a thread panicked while holding a lock
+            Err(poison) => poison.into_inner(),
+        };
         match self.mode {
             Shared => {
                 state.mutate_lock.decrement();
@@ -472,24 +476,25 @@
     ///
     /// [`CacheLocker`] uses interior mutability because it is stuffed inside
     /// [`GlobalContext`], which does not allow mutation.
-    state: RefCell<CacheState>,
+    state: Mutex<CacheState>,
 }
 
 impl CacheLocker {
     /// Creates a new `CacheLocker`.
     pub fn new() -> CacheLocker {
         CacheLocker {
-            state: RefCell::new(CacheState {
+            state: CacheState {
                 cache_lock: RecursiveLock::new(CACHE_LOCK_NAME),
                 mutate_lock: RecursiveLock::new(MUTATE_NAME),
-            }),
+            }
+            .into(),
         }
     }
 
     /// Acquires a lock with the given mode, possibly blocking if another
     /// cargo is holding the lock.
     pub fn lock(&self, gctx: &GlobalContext, mode: CacheLockMode) -> CargoResult<CacheLock<'_>> {
-        let mut state = self.state.borrow_mut();
+        let mut state = self.state.lock().unwrap();
         let _ = state.lock(gctx, mode, Blocking)?;
         Ok(CacheLock { mode, locker: self })
     }
@@ -501,7 +506,7 @@
         gctx: &GlobalContext,
         mode: CacheLockMode,
     ) -> CargoResult<Option<CacheLock<'_>>> {
-        let mut state = self.state.borrow_mut();
+        let mut state = self.state.lock().unwrap();
         if state.lock(gctx, mode, NonBlocking)? == LockAcquired {
             Ok(Some(CacheLock { mode, locker: self }))
         } else {
@@ -519,7 +524,7 @@
     /// `DownloadExclusive` will return true if a `MutateExclusive` lock is
     /// held since they overlap.
     pub fn is_locked(&self, mode: CacheLockMode) -> bool {
-        let state = self.state.borrow();
+        let state = self.state.lock().unwrap();
         match (
             mode,
             state.cache_lock.count,
diff --git a/src/cargo/util/command_prelude.rs b/src/cargo/util/command_prelude.rs
index b70caa1..31e3a50 100644
--- a/src/cargo/util/command_prelude.rs
+++ b/src/cargo/util/command_prelude.rs
@@ -1263,10 +1263,12 @@
         }
     }
 
-    // Allow tab-completion for `host` as the desired target.
-    candidates.push(clap_complete::CompletionCandidate::new("host").help(Some(
-        concat!("alias for: ", env!("RUST_HOST_TARGET")).into(),
-    )));
+    // Allow tab-completion for `host-tuple` as the desired target.
+    candidates.push(
+        clap_complete::CompletionCandidate::new("host-tuple").help(Some(
+            concat!("alias for: ", env!("RUST_HOST_TARGET")).into(),
+        )),
+    );
 
     candidates
 }
diff --git a/src/cargo/util/context/key.rs b/src/cargo/util/context/key.rs
index 66d12c8..048b595 100644
--- a/src/cargo/util/context/key.rs
+++ b/src/cargo/util/context/key.rs
@@ -112,7 +112,7 @@
     }
 }
 
-fn escape_key_part<'a>(part: &'a str) -> Cow<'a, str> {
+pub(super) fn escape_key_part<'a>(part: &'a str) -> Cow<'a, str> {
     let ok = part.chars().all(|c| {
         matches!(c,
         'a'..='z' | 'A'..='Z' | '0'..='9' | '-' | '_')
diff --git a/src/cargo/util/context/mod.rs b/src/cargo/util/context/mod.rs
index 62b0411..0062018 100644
--- a/src/cargo/util/context/mod.rs
+++ b/src/cargo/util/context/mod.rs
@@ -51,7 +51,6 @@
 
 use crate::util::cache_lock::{CacheLock, CacheLockMode, CacheLocker};
 use std::borrow::Cow;
-use std::cell::{RefCell, RefMut};
 use std::collections::hash_map::Entry::{Occupied, Vacant};
 use std::collections::{HashMap, HashSet};
 use std::env;
@@ -63,7 +62,7 @@
 use std::mem;
 use std::path::{Path, PathBuf};
 use std::str::FromStr;
-use std::sync::{Arc, Once};
+use std::sync::{Arc, Mutex, MutexGuard, Once, OnceLock};
 use std::time::Instant;
 
 use self::ConfigValue as CV;
@@ -74,6 +73,7 @@
 use crate::ops::RegistryCredentialConfig;
 use crate::sources::CRATES_IO_INDEX;
 use crate::sources::CRATES_IO_REGISTRY;
+use crate::util::OnceExt as _;
 use crate::util::errors::CargoResult;
 use crate::util::network::http::configure_http_handle;
 use crate::util::network::http::http_handle;
@@ -85,7 +85,6 @@
 use cargo_util_schemas::manifest::RegistryName;
 use curl::easy::Easy;
 use itertools::Itertools;
-use lazycell::LazyCell;
 use serde::Deserialize;
 use serde::de::IntoDeserializer as _;
 use serde_untagged::UntaggedEnumVisitor;
@@ -166,11 +165,11 @@
     /// The location of the user's Cargo home directory. OS-dependent.
     home_path: Filesystem,
     /// Information about how to write messages to the shell
-    shell: RefCell<Shell>,
+    shell: Mutex<Shell>,
     /// A collection of configuration options
-    values: LazyCell<HashMap<String, ConfigValue>>,
+    values: OnceLock<HashMap<String, ConfigValue>>,
     /// A collection of configuration options from the credentials file
-    credential_values: LazyCell<HashMap<String, ConfigValue>>,
+    credential_values: OnceLock<HashMap<String, ConfigValue>>,
     /// CLI config values, passed in via `configure`.
     cli_config: Option<Vec<String>>,
     /// The current working directory of cargo
@@ -178,9 +177,9 @@
     /// Directory where config file searching should stop (inclusive).
     search_stop_path: Option<PathBuf>,
     /// The location of the cargo executable (path to current process)
-    cargo_exe: LazyCell<PathBuf>,
+    cargo_exe: OnceLock<PathBuf>,
     /// The location of the rustdoc executable
-    rustdoc: LazyCell<PathBuf>,
+    rustdoc: OnceLock<PathBuf>,
     /// Whether we are printing extra verbose messages
     extra_verbose: bool,
     /// `frozen` is the same as `locked`, but additionally will not access the
@@ -199,9 +198,9 @@
     /// Cli flags of the form "-Z something"
     unstable_flags_cli: Option<Vec<String>>,
     /// A handle on curl easy mode for http calls
-    easy: LazyCell<RefCell<Easy>>,
+    easy: OnceLock<Mutex<Easy>>,
     /// Cache of the `SourceId` for crates.io
-    crates_io_source_id: LazyCell<SourceId>,
+    crates_io_source_id: OnceLock<SourceId>,
     /// If false, don't cache `rustc --version --verbose` invocations
     cache_rustc_info: bool,
     /// Creation time of this config, used to output the total build time
@@ -211,23 +210,23 @@
     /// Environment variable snapshot.
     env: Env,
     /// Tracks which sources have been updated to avoid multiple updates.
-    updated_sources: LazyCell<RefCell<HashSet<SourceId>>>,
+    updated_sources: Mutex<HashSet<SourceId>>,
     /// Cache of credentials from configuration or credential providers.
     /// Maps from url to credential value.
-    credential_cache: LazyCell<RefCell<HashMap<CanonicalUrl, CredentialCacheValue>>>,
+    credential_cache: Mutex<HashMap<CanonicalUrl, CredentialCacheValue>>,
     /// Cache of registry config from the `[registries]` table.
-    registry_config: LazyCell<RefCell<HashMap<SourceId, Option<RegistryConfig>>>>,
+    registry_config: Mutex<HashMap<SourceId, Option<RegistryConfig>>>,
     /// Locks on the package and index caches.
     package_cache_lock: CacheLocker,
     /// Cached configuration parsed by Cargo
-    http_config: LazyCell<CargoHttpConfig>,
-    future_incompat_config: LazyCell<CargoFutureIncompatConfig>,
-    net_config: LazyCell<CargoNetConfig>,
-    build_config: LazyCell<CargoBuildConfig>,
-    target_cfgs: LazyCell<Vec<(String, TargetCfgConfig)>>,
-    doc_extern_map: LazyCell<RustdocExternMap>,
+    http_config: OnceLock<CargoHttpConfig>,
+    future_incompat_config: OnceLock<CargoFutureIncompatConfig>,
+    net_config: OnceLock<CargoNetConfig>,
+    build_config: OnceLock<CargoBuildConfig>,
+    target_cfgs: OnceLock<Vec<(String, TargetCfgConfig)>>,
+    doc_extern_map: OnceLock<RustdocExternMap>,
     progress_config: ProgressConfig,
-    env_config: LazyCell<Arc<HashMap<String, OsString>>>,
+    env_config: OnceLock<Arc<HashMap<String, OsString>>>,
     /// This should be false if:
     /// - this is an artifact of the rustc distribution process for "stable" or for "beta"
     /// - this is an `#[test]` that does not opt in with `enable_nightly_features`
@@ -245,12 +244,12 @@
     /// consider using `ConfigBuilder::enable_nightly_features` instead.
     pub nightly_features_allowed: bool,
     /// `WorkspaceRootConfigs` that have been found
-    pub ws_roots: RefCell<HashMap<PathBuf, WorkspaceRootConfig>>,
+    ws_roots: Mutex<HashMap<PathBuf, WorkspaceRootConfig>>,
     /// The global cache tracker is a database used to track disk cache usage.
-    global_cache_tracker: LazyCell<RefCell<GlobalCacheTracker>>,
+    global_cache_tracker: OnceLock<Mutex<GlobalCacheTracker>>,
     /// A cache of modifications to make to [`GlobalContext::global_cache_tracker`],
     /// saved to disk in a batch to improve performance.
-    deferred_global_last_use: LazyCell<RefCell<DeferredGlobalLastUse>>,
+    deferred_global_last_use: OnceLock<Mutex<DeferredGlobalLastUse>>,
 }
 
 impl GlobalContext {
@@ -283,14 +282,14 @@
 
         GlobalContext {
             home_path: Filesystem::new(homedir),
-            shell: RefCell::new(shell),
+            shell: Mutex::new(shell),
             cwd,
             search_stop_path: None,
-            values: LazyCell::new(),
-            credential_values: LazyCell::new(),
+            values: Default::default(),
+            credential_values: Default::default(),
             cli_config: None,
-            cargo_exe: LazyCell::new(),
-            rustdoc: LazyCell::new(),
+            cargo_exe: Default::default(),
+            rustdoc: Default::default(),
             extra_verbose: false,
             frozen: false,
             locked: false,
@@ -304,28 +303,28 @@
             },
             unstable_flags: CliUnstable::default(),
             unstable_flags_cli: None,
-            easy: LazyCell::new(),
-            crates_io_source_id: LazyCell::new(),
+            easy: Default::default(),
+            crates_io_source_id: Default::default(),
             cache_rustc_info,
             creation_time: Instant::now(),
             target_dir: None,
             env,
-            updated_sources: LazyCell::new(),
-            credential_cache: LazyCell::new(),
-            registry_config: LazyCell::new(),
+            updated_sources: Default::default(),
+            credential_cache: Default::default(),
+            registry_config: Default::default(),
             package_cache_lock: CacheLocker::new(),
-            http_config: LazyCell::new(),
-            future_incompat_config: LazyCell::new(),
-            net_config: LazyCell::new(),
-            build_config: LazyCell::new(),
-            target_cfgs: LazyCell::new(),
-            doc_extern_map: LazyCell::new(),
+            http_config: Default::default(),
+            future_incompat_config: Default::default(),
+            net_config: Default::default(),
+            build_config: Default::default(),
+            target_cfgs: Default::default(),
+            doc_extern_map: Default::default(),
             progress_config: ProgressConfig::default(),
-            env_config: LazyCell::new(),
+            env_config: Default::default(),
             nightly_features_allowed: matches!(&*features::channel(), "nightly" | "dev"),
-            ws_roots: RefCell::new(HashMap::new()),
-            global_cache_tracker: LazyCell::new(),
-            deferred_global_last_use: LazyCell::new(),
+            ws_roots: Default::default(),
+            global_cache_tracker: Default::default(),
+            deferred_global_last_use: Default::default(),
         }
     }
 
@@ -408,8 +407,22 @@
     }
 
     /// Gets a reference to the shell, e.g., for writing error messages.
-    pub fn shell(&self) -> RefMut<'_, Shell> {
-        self.shell.borrow_mut()
+    pub fn shell(&self) -> MutexGuard<'_, Shell> {
+        self.shell.lock().unwrap()
+    }
+
+    /// Assert [`Self::shell`] is not in use
+    ///
+    /// Testing might not identify bugs with two accesses to `shell` at once
+    /// due to conditional logic,
+    /// so place this outside of the conditions to catch these bugs in more situations.
+    pub fn debug_assert_shell_not_borrowed(&self) {
+        if cfg!(debug_assertions) {
+            match self.shell.try_lock() {
+                Ok(_) | Err(std::sync::TryLockError::Poisoned(_)) => (),
+                Err(std::sync::TryLockError::WouldBlock) => panic!("shell is borrowed!"),
+            }
+        }
     }
 
     /// Gets the path to the `rustdoc` executable.
@@ -513,24 +526,20 @@
     }
 
     /// Which package sources have been updated, used to ensure it is only done once.
-    pub fn updated_sources(&self) -> RefMut<'_, HashSet<SourceId>> {
-        self.updated_sources
-            .borrow_with(|| RefCell::new(HashSet::new()))
-            .borrow_mut()
+    pub fn updated_sources(&self) -> MutexGuard<'_, HashSet<SourceId>> {
+        self.updated_sources.lock().unwrap()
     }
 
     /// Cached credentials from credential providers or configuration.
-    pub fn credential_cache(&self) -> RefMut<'_, HashMap<CanonicalUrl, CredentialCacheValue>> {
-        self.credential_cache
-            .borrow_with(|| RefCell::new(HashMap::new()))
-            .borrow_mut()
+    pub fn credential_cache(&self) -> MutexGuard<'_, HashMap<CanonicalUrl, CredentialCacheValue>> {
+        self.credential_cache.lock().unwrap()
     }
 
     /// Cache of already parsed registries from the `[registries]` table.
-    pub(crate) fn registry_config(&self) -> RefMut<'_, HashMap<SourceId, Option<RegistryConfig>>> {
-        self.registry_config
-            .borrow_with(|| RefCell::new(HashMap::new()))
-            .borrow_mut()
+    pub(crate) fn registry_config(
+        &self,
+    ) -> MutexGuard<'_, HashMap<SourceId, Option<RegistryConfig>>> {
+        self.registry_config.lock().unwrap()
     }
 
     /// Gets all config values from disk.
@@ -550,18 +559,15 @@
     /// using this if possible.
     pub fn values_mut(&mut self) -> CargoResult<&mut HashMap<String, ConfigValue>> {
         let _ = self.values()?;
-        Ok(self
-            .values
-            .borrow_mut()
-            .expect("already loaded config values"))
+        Ok(self.values.get_mut().expect("already loaded config values"))
     }
 
     // Note: this is used by RLS, not Cargo.
     pub fn set_values(&self, values: HashMap<String, ConfigValue>) -> CargoResult<()> {
-        if self.values.borrow().is_some() {
+        if self.values.get().is_some() {
             bail!("config values already found")
         }
-        match self.values.fill(values) {
+        match self.values.set(values.into()) {
             Ok(()) => Ok(()),
             Err(_) => bail!("could not fill values"),
         }
@@ -730,13 +736,13 @@
     /// This does NOT look at environment variables. See `get_cv_with_env` for
     /// a variant that supports environment variables.
     fn get_cv(&self, key: &ConfigKey) -> CargoResult<Option<ConfigValue>> {
-        if let Some(vals) = self.credential_values.borrow() {
+        if let Some(vals) = self.credential_values.get() {
             let val = self.get_cv_helper(key, vals)?;
             if val.is_some() {
                 return Ok(val);
             }
         }
-        self.get_cv_helper(key, self.values()?)
+        self.get_cv_helper(key, &*self.values()?)
     }
 
     fn get_cv_helper(
@@ -1463,98 +1469,20 @@
                 self._load_file(&self.cwd().join(&str_path), &mut seen, true, WhyLoad::Cli)
                     .with_context(|| format!("failed to load config from `{}`", str_path))?
             } else {
-                // We only want to allow "dotted key" (see https://toml.io/en/v1.0.0#keys)
-                // expressions followed by a value that's not an "inline table"
-                // (https://toml.io/en/v1.0.0#inline-table). Easiest way to check for that is to
-                // parse the value as a toml_edit::DocumentMut, and check that the (single)
-                // inner-most table is set via dotted keys.
-                let doc: toml_edit::DocumentMut = arg.parse().with_context(|| {
-                    format!("failed to parse value from --config argument `{arg}` as a dotted key expression")
-                })?;
-                fn non_empty(d: Option<&toml_edit::RawString>) -> bool {
-                    d.map_or(false, |p| !p.as_str().unwrap_or_default().trim().is_empty())
-                }
-                fn non_empty_decor(d: &toml_edit::Decor) -> bool {
-                    non_empty(d.prefix()) || non_empty(d.suffix())
-                }
-                fn non_empty_key_decor(k: &toml_edit::Key) -> bool {
-                    non_empty_decor(k.leaf_decor()) || non_empty_decor(k.dotted_decor())
-                }
-                let ok = {
-                    let mut got_to_value = false;
-                    let mut table = doc.as_table();
-                    let mut is_root = true;
-                    while table.is_dotted() || is_root {
-                        is_root = false;
-                        if table.len() != 1 {
-                            break;
-                        }
-                        let (k, n) = table.iter().next().expect("len() == 1 above");
-                        match n {
-                            Item::Table(nt) => {
-                                if table.key(k).map_or(false, non_empty_key_decor)
-                                    || non_empty_decor(nt.decor())
-                                {
-                                    bail!(
-                                        "--config argument `{arg}` \
-                                            includes non-whitespace decoration"
-                                    )
-                                }
-                                table = nt;
-                            }
-                            Item::Value(v) if v.is_inline_table() => {
-                                bail!(
-                                    "--config argument `{arg}` \
-                                    sets a value to an inline table, which is not accepted"
-                                );
-                            }
-                            Item::Value(v) => {
-                                if table
-                                    .key(k)
-                                    .map_or(false, |k| non_empty(k.leaf_decor().prefix()))
-                                    || non_empty_decor(v.decor())
-                                {
-                                    bail!(
-                                        "--config argument `{arg}` \
-                                            includes non-whitespace decoration"
-                                    )
-                                }
-                                got_to_value = true;
-                                break;
-                            }
-                            Item::ArrayOfTables(_) => {
-                                bail!(
-                                    "--config argument `{arg}` \
-                                    sets a value to an array of tables, which is not accepted"
-                                );
-                            }
-
-                            Item::None => {
-                                bail!("--config argument `{arg}` doesn't provide a value")
-                            }
-                        }
-                    }
-                    got_to_value
-                };
-                if !ok {
-                    bail!(
-                        "--config argument `{arg}` was not a TOML dotted key expression (such as `build.jobs = 2`)"
-                    );
-                }
-
-                let toml_v: toml::Value = toml::Value::deserialize(doc.into_deserializer())
+                let doc = toml_dotted_keys(arg)?;
+                let doc: toml::Value = toml::Value::deserialize(doc.into_deserializer())
                     .with_context(|| {
                         format!("failed to parse value from --config argument `{arg}`")
                     })?;
 
-                if toml_v
+                if doc
                     .get("registry")
                     .and_then(|v| v.as_table())
                     .and_then(|t| t.get("token"))
                     .is_some()
                 {
                     bail!("registry.token cannot be set through --config for security reasons");
-                } else if let Some((k, _)) = toml_v
+                } else if let Some((k, _)) = doc
                     .get("registries")
                     .and_then(|v| v.as_table())
                     .and_then(|t| t.iter().find(|(_, v)| v.get("token").is_some()))
@@ -1565,7 +1493,7 @@
                     );
                 }
 
-                if toml_v
+                if doc
                     .get("registry")
                     .and_then(|v| v.as_table())
                     .and_then(|t| t.get("secret-key"))
@@ -1574,7 +1502,7 @@
                     bail!(
                         "registry.secret-key cannot be set through --config for security reasons"
                     );
-                } else if let Some((k, _)) = toml_v
+                } else if let Some((k, _)) = doc
                     .get("registries")
                     .and_then(|v| v.as_table())
                     .and_then(|t| t.iter().find(|(_, v)| v.get("secret-key").is_some()))
@@ -1585,7 +1513,7 @@
                     );
                 }
 
-                CV::from_toml(Definition::Cli(None), toml_v)
+                CV::from_toml(Definition::Cli(None), doc)
                     .with_context(|| format!("failed to convert --config argument `{arg}`"))?
             };
             let tmp_table = self
@@ -1791,7 +1719,7 @@
             }
         }
         self.credential_values
-            .fill(credential_values)
+            .set(credential_values)
             .expect("was not filled at beginning of the function");
         Ok(())
     }
@@ -1883,12 +1811,12 @@
         self.jobserver.as_ref()
     }
 
-    pub fn http(&self) -> CargoResult<&RefCell<Easy>> {
+    pub fn http(&self) -> CargoResult<&Mutex<Easy>> {
         let http = self
             .easy
-            .try_borrow_with(|| http_handle(self).map(RefCell::new))?;
+            .try_borrow_with(|| http_handle(self).map(Into::into))?;
         {
-            let mut http = http.borrow_mut();
+            let mut http = http.lock().unwrap();
             http.reset();
             let timeout = configure_http_handle(self, &mut http)?;
             timeout.configure(&mut http)?;
@@ -2099,19 +2027,19 @@
     ///
     /// The package cache lock must be held to call this function (and to use
     /// it in general).
-    pub fn global_cache_tracker(&self) -> CargoResult<RefMut<'_, GlobalCacheTracker>> {
+    pub fn global_cache_tracker(&self) -> CargoResult<MutexGuard<'_, GlobalCacheTracker>> {
         let tracker = self.global_cache_tracker.try_borrow_with(|| {
-            Ok::<_, anyhow::Error>(RefCell::new(GlobalCacheTracker::new(self)?))
+            Ok::<_, anyhow::Error>(Mutex::new(GlobalCacheTracker::new(self)?))
         })?;
-        Ok(tracker.borrow_mut())
+        Ok(tracker.lock().unwrap())
     }
 
     /// Returns a reference to the shared [`DeferredGlobalLastUse`].
-    pub fn deferred_global_last_use(&self) -> CargoResult<RefMut<'_, DeferredGlobalLastUse>> {
-        let deferred = self.deferred_global_last_use.try_borrow_with(|| {
-            Ok::<_, anyhow::Error>(RefCell::new(DeferredGlobalLastUse::new()))
-        })?;
-        Ok(deferred.borrow_mut())
+    pub fn deferred_global_last_use(&self) -> CargoResult<MutexGuard<'_, DeferredGlobalLastUse>> {
+        let deferred = self
+            .deferred_global_last_use
+            .try_borrow_with(|| Ok::<_, anyhow::Error>(Mutex::new(DeferredGlobalLastUse::new())))?;
+        Ok(deferred.lock().unwrap())
     }
 
     /// Get the global [`WarningHandling`] configuration.
@@ -2122,6 +2050,10 @@
             Ok(WarningHandling::default())
         }
     }
+
+    pub fn ws_roots(&self) -> MutexGuard<'_, HashMap<PathBuf, WorkspaceRootConfig>> {
+        self.ws_roots.lock().unwrap()
+    }
 }
 
 /// Internal error for serde errors.
@@ -2223,6 +2155,12 @@
     }
 }
 
+#[derive(Debug)]
+enum KeyOrIdx {
+    Key(String),
+    Idx(usize),
+}
+
 #[derive(Eq, PartialEq, Clone)]
 pub enum ConfigValue {
     Integer(i64, Definition),
@@ -2265,26 +2203,56 @@
     }
 
     fn from_toml(def: Definition, toml: toml::Value) -> CargoResult<ConfigValue> {
+        let mut error_path = Vec::new();
+        Self::from_toml_inner(def, toml, &mut error_path).with_context(|| {
+            let mut it = error_path.iter().rev().peekable();
+            let mut key_path = String::with_capacity(error_path.len() * 3);
+            while let Some(k) = it.next() {
+                match k {
+                    KeyOrIdx::Key(s) => key_path.push_str(&key::escape_key_part(&s)),
+                    KeyOrIdx::Idx(i) => key_path.push_str(&format!("[{i}]")),
+                }
+                if matches!(it.peek(), Some(KeyOrIdx::Key(_))) {
+                    key_path.push('.');
+                }
+            }
+            format!("failed to parse config at `{key_path}`")
+        })
+    }
+
+    fn from_toml_inner(
+        def: Definition,
+        toml: toml::Value,
+        path: &mut Vec<KeyOrIdx>,
+    ) -> CargoResult<ConfigValue> {
         match toml {
             toml::Value::String(val) => Ok(CV::String(val, def)),
             toml::Value::Boolean(b) => Ok(CV::Boolean(b, def)),
             toml::Value::Integer(i) => Ok(CV::Integer(i, def)),
             toml::Value::Array(val) => Ok(CV::List(
                 val.into_iter()
-                    .map(|toml| match toml {
+                    .enumerate()
+                    .map(|(i, toml)| match toml {
                         toml::Value::String(val) => Ok((val, def.clone())),
-                        v => bail!("expected string but found {} in list", v.type_str()),
+                        v => {
+                            path.push(KeyOrIdx::Idx(i));
+                            bail!("expected string but found {} at index {i}", v.type_str())
+                        }
                     })
                     .collect::<CargoResult<_>>()?,
                 def,
             )),
             toml::Value::Table(val) => Ok(CV::Table(
                 val.into_iter()
-                    .map(|(key, value)| {
-                        let value = CV::from_toml(def.clone(), value)
-                            .with_context(|| format!("failed to parse key `{}`", key))?;
-                        Ok((key, value))
-                    })
+                    .map(
+                        |(key, value)| match CV::from_toml_inner(def.clone(), value, path) {
+                            Ok(value) => Ok((key, value)),
+                            Err(e) => {
+                                path.push(KeyOrIdx::Key(key));
+                                Err(e)
+                            }
+                        },
+                    )
                     .collect::<CargoResult<_>>()?,
                 def,
             )),
@@ -3046,6 +3014,88 @@
     toml.parse().map_err(Into::into)
 }
 
+fn toml_dotted_keys(arg: &str) -> CargoResult<toml_edit::DocumentMut> {
+    // We only want to allow "dotted key" (see https://toml.io/en/v1.0.0#keys)
+    // expressions followed by a value that's not an "inline table"
+    // (https://toml.io/en/v1.0.0#inline-table). Easiest way to check for that is to
+    // parse the value as a toml_edit::DocumentMut, and check that the (single)
+    // inner-most table is set via dotted keys.
+    let doc: toml_edit::DocumentMut = arg.parse().with_context(|| {
+        format!("failed to parse value from --config argument `{arg}` as a dotted key expression")
+    })?;
+    fn non_empty(d: Option<&toml_edit::RawString>) -> bool {
+        d.map_or(false, |p| !p.as_str().unwrap_or_default().trim().is_empty())
+    }
+    fn non_empty_decor(d: &toml_edit::Decor) -> bool {
+        non_empty(d.prefix()) || non_empty(d.suffix())
+    }
+    fn non_empty_key_decor(k: &toml_edit::Key) -> bool {
+        non_empty_decor(k.leaf_decor()) || non_empty_decor(k.dotted_decor())
+    }
+    let ok = {
+        let mut got_to_value = false;
+        let mut table = doc.as_table();
+        let mut is_root = true;
+        while table.is_dotted() || is_root {
+            is_root = false;
+            if table.len() != 1 {
+                break;
+            }
+            let (k, n) = table.iter().next().expect("len() == 1 above");
+            match n {
+                Item::Table(nt) => {
+                    if table.key(k).map_or(false, non_empty_key_decor)
+                        || non_empty_decor(nt.decor())
+                    {
+                        bail!(
+                            "--config argument `{arg}` \
+                                includes non-whitespace decoration"
+                        )
+                    }
+                    table = nt;
+                }
+                Item::Value(v) if v.is_inline_table() => {
+                    bail!(
+                        "--config argument `{arg}` \
+                        sets a value to an inline table, which is not accepted"
+                    );
+                }
+                Item::Value(v) => {
+                    if table
+                        .key(k)
+                        .map_or(false, |k| non_empty(k.leaf_decor().prefix()))
+                        || non_empty_decor(v.decor())
+                    {
+                        bail!(
+                            "--config argument `{arg}` \
+                                includes non-whitespace decoration"
+                        )
+                    }
+                    got_to_value = true;
+                    break;
+                }
+                Item::ArrayOfTables(_) => {
+                    bail!(
+                        "--config argument `{arg}` \
+                        sets a value to an array of tables, which is not accepted"
+                    );
+                }
+
+                Item::None => {
+                    bail!("--config argument `{arg}` doesn't provide a value")
+                }
+            }
+        }
+        got_to_value
+    };
+    if !ok {
+        bail!(
+            "--config argument `{arg}` was not a TOML dotted key expression (such as `build.jobs = 2`)"
+        );
+    }
+    Ok(doc)
+}
+
 /// A type to deserialize a list of strings from a toml file.
 ///
 /// Supports deserializing either a whitespace-separated list of arguments in a
@@ -3192,4 +3242,10 @@
             assert_eq!(http.multiplexing, result);
         }
     }
+
+    #[test]
+    fn sync_context() {
+        fn assert_sync<S: Sync>() {}
+        assert_sync::<GlobalContext>();
+    }
 }
diff --git a/src/cargo/util/errors.rs b/src/cargo/util/errors.rs
index 5752f23..254a61b 100644
--- a/src/cargo/util/errors.rs
+++ b/src/cargo/util/errors.rs
@@ -339,6 +339,46 @@
 }
 
 // =============================================================================
+// Git CLI errors
+
+pub type GitCliResult = Result<(), GitCliError>;
+
+/// An error that occurred while invoking the `git` command-line tool.
+///
+/// This is used for errors from Git operations performed via CLI.
+/// It wraps a lower-level error and indicates whether the failure
+/// should be considered *spurious*.
+///
+/// Spurious failures might involve retry mechanism.
+#[derive(Debug)]
+pub struct GitCliError {
+    inner: Error,
+    is_spurious: bool,
+}
+
+impl GitCliError {
+    pub fn new(inner: Error, is_spurious: bool) -> GitCliError {
+        GitCliError { inner, is_spurious }
+    }
+
+    pub fn is_spurious(&self) -> bool {
+        self.is_spurious
+    }
+}
+
+impl std::error::Error for GitCliError {
+    fn source(&self) -> Option<&(dyn std::error::Error + 'static)> {
+        self.inner.source()
+    }
+}
+
+impl fmt::Display for GitCliError {
+    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+        self.inner.fmt(f)
+    }
+}
+
+// =============================================================================
 // Construction helpers
 
 pub fn internal<S: fmt::Display>(error: S) -> anyhow::Error {
diff --git a/src/cargo/util/flock.rs b/src/cargo/util/flock.rs
index 9c929de..e82465e 100644
--- a/src/cargo/util/flock.rs
+++ b/src/cargo/util/flock.rs
@@ -389,10 +389,9 @@
     lock_try: &dyn Fn() -> Result<(), TryLockError>,
     lock_block: &dyn Fn() -> io::Result<()>,
 ) -> CargoResult<()> {
-    if cfg!(debug_assertions) {
-        // Force borrow to catch invalid borrows outside of contention situations
-        gctx.shell().verbosity();
-    }
+    // Ensure `shell` is not already in use,
+    // regardless of whether we hit contention or not
+    gctx.debug_assert_shell_not_borrowed();
     if try_acquire(path, lock_try)? {
         return Ok(());
     }
diff --git a/src/cargo/util/lints.rs b/src/cargo/util/lints.rs
index da833b5..abb705b 100644
--- a/src/cargo/util/lints.rs
+++ b/src/cargo/util/lints.rs
@@ -1,7 +1,7 @@
-use crate::core::{Edition, Feature, Features, Manifest, Package};
+use crate::core::{Edition, Feature, Features, Manifest, MaybePackage, Package};
 use crate::{CargoResult, GlobalContext};
-use annotate_snippets::{AnnotationKind, Group, Level, Snippet};
-use cargo_util_schemas::manifest::{TomlLintLevel, TomlToolLints};
+use annotate_snippets::{AnnotationKind, Group, Level, Patch, Snippet};
+use cargo_util_schemas::manifest::{ProfilePackageSpec, TomlLintLevel, TomlToolLints};
 use pathdiff::diff_paths;
 use std::borrow::Cow;
 use std::fmt::Display;
@@ -9,7 +9,7 @@
 use std::path::Path;
 
 const LINT_GROUPS: &[LintGroup] = &[TEST_DUMMY_UNSTABLE];
-pub const LINTS: &[Lint] = &[IM_A_TEAPOT, UNKNOWN_LINTS];
+pub const LINTS: &[Lint] = &[BLANKET_HINT_MOSTLY_UNUSED, IM_A_TEAPOT, UNKNOWN_LINTS];
 
 pub fn analyze_cargo_lints_table(
     pkg: &Package,
@@ -481,6 +481,158 @@
     Ok(())
 }
 
+const BLANKET_HINT_MOSTLY_UNUSED: Lint = Lint {
+    name: "blanket_hint_mostly_unused",
+    desc: "blanket_hint_mostly_unused lint",
+    groups: &[],
+    default_level: LintLevel::Warn,
+    edition_lint_opts: None,
+    feature_gate: None,
+    docs: Some(
+        r#"
+### What it does
+Checks if `hint-mostly-unused` being applied to all dependencies.
+
+### Why it is bad
+`hint-mostly-unused` indicates that most of a crate's API surface will go
+unused by anything depending on it; this hint can speed up the build by
+attempting to minimize compilation time for items that aren't used at all.
+Misapplication to crates that don't fit that criteria will slow down the build
+rather than speeding it up. It should be selectively applied to dependencies
+that meet these criteria. Applying it globally is always a misapplication and
+will likely slow down the build.
+
+### Example
+```toml
+[profile.dev.package."*"]
+hint-mostly-unused = true
+```
+
+Should instead be:
+```toml
+[profile.dev.package.huge-mostly-unused-dependency]
+hint-mostly-unused = true
+```
+"#,
+    ),
+};
+
+pub fn blanket_hint_mostly_unused(
+    maybe_pkg: &MaybePackage,
+    path: &Path,
+    pkg_lints: &TomlToolLints,
+    error_count: &mut usize,
+    gctx: &GlobalContext,
+) -> CargoResult<()> {
+    let (lint_level, reason) = BLANKET_HINT_MOSTLY_UNUSED.level(
+        pkg_lints,
+        maybe_pkg.edition(),
+        maybe_pkg.unstable_features(),
+    );
+
+    if lint_level == LintLevel::Allow {
+        return Ok(());
+    }
+
+    let level = lint_level.to_diagnostic_level();
+    let manifest_path = rel_cwd_manifest_path(path, gctx);
+    let mut paths = Vec::new();
+
+    if let Some(profiles) = maybe_pkg.profiles() {
+        for (profile_name, top_level_profile) in &profiles.0 {
+            if let Some(true) = top_level_profile.hint_mostly_unused {
+                paths.push((
+                    vec!["profile", profile_name.as_str(), "hint-mostly-unused"],
+                    true,
+                ));
+            }
+
+            if let Some(build_override) = &top_level_profile.build_override
+                && let Some(true) = build_override.hint_mostly_unused
+            {
+                paths.push((
+                    vec![
+                        "profile",
+                        profile_name.as_str(),
+                        "build-override",
+                        "hint-mostly-unused",
+                    ],
+                    false,
+                ));
+            }
+
+            if let Some(packages) = &top_level_profile.package
+                && let Some(profile) = packages.get(&ProfilePackageSpec::All)
+                && let Some(true) = profile.hint_mostly_unused
+            {
+                paths.push((
+                    vec![
+                        "profile",
+                        profile_name.as_str(),
+                        "package",
+                        "*",
+                        "hint-mostly-unused",
+                    ],
+                    false,
+                ));
+            }
+        }
+    }
+
+    for (i, (path, show_per_pkg_suggestion)) in paths.iter().enumerate() {
+        if lint_level.is_error() {
+            *error_count += 1;
+        }
+        let title = "`hint-mostly-unused` is being blanket applied to all dependencies";
+        let help_txt =
+            "scope `hint-mostly-unused` to specific packages with a lot of unused object code";
+        if let (Some(span), Some(table_span)) = (
+            get_key_value_span(maybe_pkg.document(), &path),
+            get_key_value_span(maybe_pkg.document(), &path[..path.len() - 1]),
+        ) {
+            let mut report = Vec::new();
+            let mut primary_group = level.clone().primary_title(title).element(
+                Snippet::source(maybe_pkg.contents())
+                    .path(&manifest_path)
+                    .annotation(
+                        AnnotationKind::Primary.span(table_span.key.start..table_span.key.end),
+                    )
+                    .annotation(AnnotationKind::Context.span(span.key.start..span.value.end)),
+            );
+
+            if *show_per_pkg_suggestion {
+                report.push(
+                    Level::HELP.secondary_title(help_txt).element(
+                        Snippet::source(maybe_pkg.contents())
+                            .path(&manifest_path)
+                            .patch(Patch::new(
+                                table_span.key.end..table_span.key.end,
+                                ".package.<pkg_name>",
+                            )),
+                    ),
+                );
+            } else {
+                primary_group = primary_group.element(Level::HELP.message(help_txt));
+            }
+
+            if i == 0 {
+                primary_group =
+                    primary_group
+                        .element(Level::NOTE.message(
+                            BLANKET_HINT_MOSTLY_UNUSED.emitted_source(lint_level, reason),
+                        ));
+            }
+
+            // The primary group should always be first
+            report.insert(0, primary_group);
+
+            gctx.shell().print_report(&report, lint_level.force())?;
+        }
+    }
+
+    Ok(())
+}
+
 const UNKNOWN_LINTS: Lint = Lint {
     name: "unknown_lints",
     desc: "unknown lint",
diff --git a/src/cargo/util/mod.rs b/src/cargo/util/mod.rs
index a61fb5b..62f181f 100644
--- a/src/cargo/util/mod.rs
+++ b/src/cargo/util/mod.rs
@@ -18,6 +18,7 @@
 pub use self::into_url_with_base::IntoUrlWithBase;
 pub(crate) use self::io::LimitErrorReader;
 pub use self::lockserver::{LockServer, LockServerClient, LockServerStarted};
+pub use self::once::OnceExt;
 pub use self::progress::{Progress, ProgressStyle};
 pub use self::queue::Queue;
 pub use self::rustc::Rustc;
@@ -56,6 +57,7 @@
 mod lockserver;
 pub mod machine_message;
 pub mod network;
+mod once;
 mod progress;
 mod queue;
 pub mod restricted_names;
diff --git a/src/cargo/util/network/retry.rs b/src/cargo/util/network/retry.rs
index 5d4e580..539535d 100644
--- a/src/cargo/util/network/retry.rs
+++ b/src/cargo/util/network/retry.rs
@@ -41,7 +41,7 @@
 //! - <https://en.wikipedia.org/wiki/Exponential_backoff>
 //! - <https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Retry-After>
 
-use crate::util::errors::HttpNotSuccessful;
+use crate::util::errors::{GitCliError, HttpNotSuccessful};
 use crate::{CargoResult, GlobalContext};
 use anyhow::Error;
 use rand::Rng;
@@ -223,6 +223,12 @@
         }
     }
 
+    if let Some(err) = err.downcast_ref::<GitCliError>() {
+        if err.is_spurious() {
+            return true;
+        }
+    }
+
     false
 }
 
@@ -402,3 +408,12 @@
         _ => panic!("unexpected non-retry"),
     }
 }
+
+#[test]
+fn git_cli_error_spurious() {
+    let error = GitCliError::new(Error::msg("test-git-cli-error"), false);
+    assert!(!maybe_spurious(&error.into()));
+
+    let error = GitCliError::new(Error::msg("test-git-cli-error"), true);
+    assert!(maybe_spurious(&error.into()));
+}
diff --git a/src/cargo/util/once.rs b/src/cargo/util/once.rs
new file mode 100644
index 0000000..63f0647
--- /dev/null
+++ b/src/cargo/util/once.rs
@@ -0,0 +1,90 @@
+//! Extension functions for [`std::sync::OnceLock`] / [`std::cell::OnceCell`]
+//!
+//! This adds polyfills for functionality in `lazycell` that is not stable within `std`.
+
+pub trait OnceExt {
+    type T;
+
+    /// This might run `f` multiple times if different threads start initializing at once.
+    fn try_borrow_with<F, E>(&self, f: F) -> Result<&Self::T, E>
+    where
+        F: FnOnce() -> Result<Self::T, E>;
+
+    fn replace(&mut self, new_value: Self::T) -> Option<Self::T>;
+
+    fn filled(&self) -> bool;
+}
+
+impl<T> OnceExt for std::sync::OnceLock<T> {
+    type T = T;
+
+    fn try_borrow_with<F, E>(&self, f: F) -> Result<&T, E>
+    where
+        F: FnOnce() -> Result<T, E>,
+    {
+        if let Some(value) = self.get() {
+            return Ok(value);
+        }
+
+        // This is not how the unstable `OnceLock::get_or_try_init` works. That only starts `f` if
+        // no other `f` is executing and the value is not initialized. However, correctly implementing that is
+        // hard (one has properly handle panics in `f`) and not doable with the stable API of `OnceLock`.
+        let value = f()?;
+        // Another thread might have initialized `self` since we checked that `self.get()` returns `None`. If this is the case, `self.set()`
+        // returns an error. We ignore it and return the value set by the other
+        // thread.
+        let _ = self.set(value);
+        Ok(self.get().unwrap())
+    }
+
+    fn replace(&mut self, new_value: T) -> Option<T> {
+        if let Some(value) = self.get_mut() {
+            Some(std::mem::replace(value, new_value))
+        } else {
+            let result = self.set(new_value);
+            assert!(result.is_ok());
+            None
+        }
+    }
+
+    fn filled(&self) -> bool {
+        self.get().is_some()
+    }
+}
+
+impl<T> OnceExt for std::cell::OnceCell<T> {
+    type T = T;
+
+    fn try_borrow_with<F, E>(&self, f: F) -> Result<&T, E>
+    where
+        F: FnOnce() -> Result<T, E>,
+    {
+        if let Some(value) = self.get() {
+            return Ok(value);
+        }
+
+        // This is not how the unstable `OnceLock::get_or_try_init` works. That only starts `f` if
+        // no other `f` is executing and the value is not initialized. However, correctly implementing that is
+        // hard (one has properly handle panics in `f`) and not doable with the stable API of `OnceLock`.
+        let value = f()?;
+        // Another thread might have initialized `self` since we checked that `self.get()` returns `None`. If this is the case, `self.set()`
+        // returns an error. We ignore it and return the value set by the other
+        // thread.
+        let _ = self.set(value);
+        Ok(self.get().unwrap())
+    }
+
+    fn replace(&mut self, new_value: T) -> Option<T> {
+        if let Some(value) = self.get_mut() {
+            Some(std::mem::replace(value, new_value))
+        } else {
+            let result = self.set(new_value);
+            assert!(result.is_ok());
+            None
+        }
+    }
+
+    fn filled(&self) -> bool {
+        self.get().is_some()
+    }
+}
diff --git a/src/cargo/util/progress.rs b/src/cargo/util/progress.rs
index f212a49..c79f965 100644
--- a/src/cargo/util/progress.rs
+++ b/src/cargo/util/progress.rs
@@ -429,7 +429,7 @@
         if self.gctx.shell().is_cleared() || self.last_line.as_ref() != Some(&line) {
             let mut shell = self.gctx.shell();
             shell.set_needs_clear(false);
-            shell.status_header(&self.name)?;
+            shell.transient_status(&self.name)?;
             if let Some(tb) = report {
                 write!(shell.err(), "{line}{tb}\r")?;
             } else {
diff --git a/src/cargo/util/style.rs b/src/cargo/util/style.rs
index 824f42b..24e6695 100644
--- a/src/cargo/util/style.rs
+++ b/src/cargo/util/style.rs
@@ -11,3 +11,4 @@
 pub const GOOD: Style = AnsiColor::BrightGreen.on_default().effects(Effects::BOLD);
 pub const VALID: Style = AnsiColor::BrightCyan.on_default().effects(Effects::BOLD);
 pub const INVALID: Style = annotate_snippets::renderer::DEFAULT_WARNING_STYLE;
+pub const TRANSIENT: Style = annotate_snippets::renderer::DEFAULT_HELP_STYLE;
diff --git a/src/cargo/util/toml/mod.rs b/src/cargo/util/toml/mod.rs
index d0a7ced..f6954cd 100644
--- a/src/cargo/util/toml/mod.rs
+++ b/src/cargo/util/toml/mod.rs
@@ -81,8 +81,7 @@
             to_workspace_config(&original_toml, path, is_embedded, gctx, &mut warnings)?;
         if let WorkspaceConfig::Root(ws_root_config) = &workspace_config {
             let package_root = path.parent().unwrap();
-            gctx.ws_roots
-                .borrow_mut()
+            gctx.ws_roots()
                 .insert(package_root.to_owned(), ws_root_config.clone());
         }
         let normalized_toml = normalize_toml(
@@ -448,7 +447,7 @@
             edition,
             &features,
             original_toml.dependencies.as_ref(),
-            None,
+            DepKind::Normal,
             &inherit,
             &workspace_root,
             package_root,
@@ -468,7 +467,7 @@
             edition,
             &features,
             original_toml.dev_dependencies(),
-            Some(DepKind::Development),
+            DepKind::Development,
             &inherit,
             &workspace_root,
             package_root,
@@ -488,7 +487,7 @@
             edition,
             &features,
             original_toml.build_dependencies(),
-            Some(DepKind::Build),
+            DepKind::Build,
             &inherit,
             &workspace_root,
             package_root,
@@ -501,7 +500,7 @@
                 edition,
                 &features,
                 platform.dependencies.as_ref(),
-                None,
+                DepKind::Normal,
                 &inherit,
                 &workspace_root,
                 package_root,
@@ -521,7 +520,7 @@
                 edition,
                 &features,
                 platform.dev_dependencies(),
-                Some(DepKind::Development),
+                DepKind::Development,
                 &inherit,
                 &workspace_root,
                 package_root,
@@ -541,7 +540,7 @@
                 edition,
                 &features,
                 platform.build_dependencies(),
-                Some(DepKind::Build),
+                DepKind::Build,
                 &inherit,
                 &workspace_root,
                 package_root,
@@ -874,7 +873,7 @@
     edition: Edition,
     features: &Features,
     orig_deps: Option<&BTreeMap<manifest::PackageName, manifest::InheritableDependency>>,
-    kind: Option<DepKind>,
+    kind: DepKind,
     inherit: &dyn Fn() -> CargoResult<&'a InheritableFields>,
     workspace_root: &dyn Fn() -> CargoResult<&'a Path>,
     package_root: &Path,
@@ -907,27 +906,27 @@
             if d.public.is_some() {
                 let with_public_feature = features.require(Feature::public_dependency()).is_ok();
                 let with_z_public = gctx.cli_unstable().public_dependency;
-                if matches!(kind, None) {
-                    if !with_public_feature && !with_z_public {
-                        d.public = None;
-                        warnings.push(format!(
-                            "ignoring `public` on dependency {name_in_toml}, pass `-Zpublic-dependency` to enable support for it"
-                        ))
+                match kind {
+                    DepKind::Normal => {
+                        if !with_public_feature && !with_z_public {
+                            d.public = None;
+                            warnings.push(format!(
+                                "ignoring `public` on dependency {name_in_toml}, pass `-Zpublic-dependency` to enable support for it"
+                            ));
+                        }
                     }
-                } else {
-                    let kind_name = match kind {
-                        Some(k) => k.kind_table(),
-                        None => "dependencies",
-                    };
-                    let hint = format!(
-                        "'public' specifier can only be used on regular dependencies, not {kind_name}",
-                    );
-                    if with_public_feature || with_z_public {
-                        bail!(hint)
-                    } else {
-                        // If public feature isn't enabled in nightly, we instead warn that.
-                        warnings.push(hint);
-                        d.public = None;
+                    DepKind::Development | DepKind::Build => {
+                        let kind_name = kind.kind_table();
+                        let hint = format!(
+                            "'public' specifier can only be used on regular dependencies, not {kind_name}",
+                        );
+                        if with_public_feature || with_z_public {
+                            bail!(hint)
+                        } else {
+                            // If public feature isn't enabled in nightly, we instead warn that.
+                            warnings.push(hint);
+                            d.public = None;
+                        }
                     }
                 }
             }
@@ -996,7 +995,7 @@
 
     // Let the borrow exit scope so that it can be picked up if there is a need to
     // read a manifest
-    if let Some(ws_root) = gctx.ws_roots.borrow().get(workspace_path_root) {
+    if let Some(ws_root) = gctx.ws_roots().get(workspace_path_root) {
         return Ok(ws_root.inheritable().clone());
     };
 
@@ -1004,9 +1003,7 @@
     let man = read_manifest(&workspace_path, source_id, gctx)?;
     match man.workspace_config() {
         WorkspaceConfig::Root(root) => {
-            gctx.ws_roots
-                .borrow_mut()
-                .insert(workspace_path, root.clone());
+            gctx.ws_roots().insert(workspace_path, root.clone());
             Ok(root.inheritable().clone())
         }
         _ => bail!(
@@ -1314,7 +1311,7 @@
                 let edition_msrv = RustVersion::try_from(edition_msrv).unwrap();
                 if !edition_msrv.is_compatible_with(pkg_msrv.as_partial()) {
                     bail!(
-                        "rust-version {} is older than first version ({}) required by \
+                        "rust-version {} is imcompatible with the version ({}) required by \
                             the specified edition ({})",
                         pkg_msrv,
                         edition_msrv,
diff --git a/src/doc/contrib/src/tests/writing.md b/src/doc/contrib/src/tests/writing.md
index 3405850..99eef91 100644
--- a/src/doc/contrib/src/tests/writing.md
+++ b/src/doc/contrib/src/tests/writing.md
@@ -64,6 +64,16 @@
   - See [`support::compare`] for an explanation of the string pattern matching.
     Patterns are used to make it easier to match against the expected output.
 
+#### Filesystem layout testing
+
+Tests often to need to verify Cargo created/removed files.
+The `CargoPathExt` trait (implemented by `Path` and `PathBuf`) provides a `assert_dir_layout()` to verify the files in a directory (including nested directories).
+This takes a snapshot of file paths for the given directory and asserts that all files are present and no new files have been created.
+This function also takes a list of patterns to ignore from the snapshot to make working with platform specific files easier.
+
+Note: You will commonly need to call `unordered()` before passing your snapshot to deal with platform differences like binaries having `.exe` on Windows.
+`assert_build_dir_layout` is a more specialized version of `assert_dir_layout()` that is automatically unordered and ignores common platform specific files designed for the Cargo build cache.
+
 #### Testing Nightly Features
 
 If you are testing a Cargo feature that only works on "nightly" Cargo, then
diff --git a/src/doc/man/generated_txt/cargo-bench.txt b/src/doc/man/generated_txt/cargo-bench.txt
index 4b3c401..26791af 100644
--- a/src/doc/man/generated_txt/cargo-bench.txt
+++ b/src/doc/man/generated_txt/cargo-bench.txt
@@ -228,8 +228,8 @@
 
            o  Any supported target in rustc --print target-list.
 
-           o  "host", which will internally be substituted by the host’s
-              target. This can be particularly useful if you’re
+           o  "host-tuple", which will internally be substituted by the
+              host’s target. This can be particularly useful if you’re
               cross-compiling some crates, and don’t want to specify your
               host’s machine as a target (for instance, an xtask in a shared
               project that may be worked on by many hosts).
diff --git a/src/doc/man/generated_txt/cargo-build.txt b/src/doc/man/generated_txt/cargo-build.txt
index 2f82479..659c675 100644
--- a/src/doc/man/generated_txt/cargo-build.txt
+++ b/src/doc/man/generated_txt/cargo-build.txt
@@ -145,8 +145,8 @@
 
            o  Any supported target in rustc --print target-list.
 
-           o  "host", which will internally be substituted by the host’s
-              target. This can be particularly useful if you’re
+           o  "host-tuple", which will internally be substituted by the
+              host’s target. This can be particularly useful if you’re
               cross-compiling some crates, and don’t want to specify your
               host’s machine as a target (for instance, an xtask in a shared
               project that may be worked on by many hosts).
diff --git a/src/doc/man/generated_txt/cargo-check.txt b/src/doc/man/generated_txt/cargo-check.txt
index 42be192..b875932 100644
--- a/src/doc/man/generated_txt/cargo-check.txt
+++ b/src/doc/man/generated_txt/cargo-check.txt
@@ -142,8 +142,8 @@
 
            o  Any supported target in rustc --print target-list.
 
-           o  "host", which will internally be substituted by the host’s
-              target. This can be particularly useful if you’re
+           o  "host-tuple", which will internally be substituted by the
+              host’s target. This can be particularly useful if you’re
               cross-compiling some crates, and don’t want to specify your
               host’s machine as a target (for instance, an xtask in a shared
               project that may be worked on by many hosts).
diff --git a/src/doc/man/generated_txt/cargo-clean.txt b/src/doc/man/generated_txt/cargo-clean.txt
index 09feaf5..a81fb90 100644
--- a/src/doc/man/generated_txt/cargo-clean.txt
+++ b/src/doc/man/generated_txt/cargo-clean.txt
@@ -53,8 +53,8 @@
 
            o  Any supported target in rustc --print target-list.
 
-           o  "host", which will internally be substituted by the host’s
-              target. This can be particularly useful if you’re
+           o  "host-tuple", which will internally be substituted by the
+              host’s target. This can be particularly useful if you’re
               cross-compiling some crates, and don’t want to specify your
               host’s machine as a target (for instance, an xtask in a shared
               project that may be worked on by many hosts).
diff --git a/src/doc/man/generated_txt/cargo-doc.txt b/src/doc/man/generated_txt/cargo-doc.txt
index 9a1f6a0..b1f951e 100644
--- a/src/doc/man/generated_txt/cargo-doc.txt
+++ b/src/doc/man/generated_txt/cargo-doc.txt
@@ -124,8 +124,8 @@
 
            o  Any supported target in rustc --print target-list.
 
-           o  "host", which will internally be substituted by the host’s
-              target. This can be particularly useful if you’re
+           o  "host-tuple", which will internally be substituted by the
+              host’s target. This can be particularly useful if you’re
               cross-compiling some crates, and don’t want to specify your
               host’s machine as a target (for instance, an xtask in a shared
               project that may be worked on by many hosts).
diff --git a/src/doc/man/generated_txt/cargo-fetch.txt b/src/doc/man/generated_txt/cargo-fetch.txt
index 91e308f..ac8ea1f 100644
--- a/src/doc/man/generated_txt/cargo-fetch.txt
+++ b/src/doc/man/generated_txt/cargo-fetch.txt
@@ -33,8 +33,8 @@
 
            o  Any supported target in rustc --print target-list.
 
-           o  "host", which will internally be substituted by the host’s
-              target. This can be particularly useful if you’re
+           o  "host-tuple", which will internally be substituted by the
+              host’s target. This can be particularly useful if you’re
               cross-compiling some crates, and don’t want to specify your
               host’s machine as a target (for instance, an xtask in a shared
               project that may be worked on by many hosts).
diff --git a/src/doc/man/generated_txt/cargo-fix.txt b/src/doc/man/generated_txt/cargo-fix.txt
index 56e131b..d643bca 100644
--- a/src/doc/man/generated_txt/cargo-fix.txt
+++ b/src/doc/man/generated_txt/cargo-fix.txt
@@ -216,8 +216,8 @@
 
            o  Any supported target in rustc --print target-list.
 
-           o  "host", which will internally be substituted by the host’s
-              target. This can be particularly useful if you’re
+           o  "host-tuple", which will internally be substituted by the
+              host’s target. This can be particularly useful if you’re
               cross-compiling some crates, and don’t want to specify your
               host’s machine as a target (for instance, an xtask in a shared
               project that may be worked on by many hosts).
diff --git a/src/doc/man/generated_txt/cargo-install.txt b/src/doc/man/generated_txt/cargo-install.txt
index 2001a2c..36507aa 100644
--- a/src/doc/man/generated_txt/cargo-install.txt
+++ b/src/doc/man/generated_txt/cargo-install.txt
@@ -194,8 +194,8 @@
 
            o  Any supported target in rustc --print target-list.
 
-           o  "host", which will internally be substituted by the host’s
-              target. This can be particularly useful if you’re
+           o  "host-tuple", which will internally be substituted by the
+              host’s target. This can be particularly useful if you’re
               cross-compiling some crates, and don’t want to specify your
               host’s machine as a target (for instance, an xtask in a shared
               project that may be worked on by many hosts).
diff --git a/src/doc/man/generated_txt/cargo-package.txt b/src/doc/man/generated_txt/cargo-package.txt
index 54c2262..9ee3f87 100644
--- a/src/doc/man/generated_txt/cargo-package.txt
+++ b/src/doc/man/generated_txt/cargo-package.txt
@@ -196,8 +196,8 @@
 
            o  Any supported target in rustc --print target-list.
 
-           o  "host", which will internally be substituted by the host’s
-              target. This can be particularly useful if you’re
+           o  "host-tuple", which will internally be substituted by the
+              host’s target. This can be particularly useful if you’re
               cross-compiling some crates, and don’t want to specify your
               host’s machine as a target (for instance, an xtask in a shared
               project that may be worked on by many hosts).
diff --git a/src/doc/man/generated_txt/cargo-publish.txt b/src/doc/man/generated_txt/cargo-publish.txt
index c303754..d5170f0 100644
--- a/src/doc/man/generated_txt/cargo-publish.txt
+++ b/src/doc/man/generated_txt/cargo-publish.txt
@@ -117,8 +117,8 @@
 
            o  Any supported target in rustc --print target-list.
 
-           o  "host", which will internally be substituted by the host’s
-              target. This can be particularly useful if you’re
+           o  "host-tuple", which will internally be substituted by the
+              host’s target. This can be particularly useful if you’re
               cross-compiling some crates, and don’t want to specify your
               host’s machine as a target (for instance, an xtask in a shared
               project that may be worked on by many hosts).
diff --git a/src/doc/man/generated_txt/cargo-run.txt b/src/doc/man/generated_txt/cargo-run.txt
index 9f5f3a6..c93094d 100644
--- a/src/doc/man/generated_txt/cargo-run.txt
+++ b/src/doc/man/generated_txt/cargo-run.txt
@@ -69,8 +69,8 @@
 
            o  Any supported target in rustc --print target-list.
 
-           o  "host", which will internally be substituted by the host’s
-              target. This can be particularly useful if you’re
+           o  "host-tuple", which will internally be substituted by the
+              host’s target. This can be particularly useful if you’re
               cross-compiling some crates, and don’t want to specify your
               host’s machine as a target (for instance, an xtask in a shared
               project that may be worked on by many hosts).
diff --git a/src/doc/man/generated_txt/cargo-rustc.txt b/src/doc/man/generated_txt/cargo-rustc.txt
index 763b9b3..baf6eaf 100644
--- a/src/doc/man/generated_txt/cargo-rustc.txt
+++ b/src/doc/man/generated_txt/cargo-rustc.txt
@@ -136,8 +136,8 @@
 
            o  Any supported target in rustc --print target-list.
 
-           o  "host", which will internally be substituted by the host’s
-              target. This can be particularly useful if you’re
+           o  "host-tuple", which will internally be substituted by the
+              host’s target. This can be particularly useful if you’re
               cross-compiling some crates, and don’t want to specify your
               host’s machine as a target (for instance, an xtask in a shared
               project that may be worked on by many hosts).
diff --git a/src/doc/man/generated_txt/cargo-rustdoc.txt b/src/doc/man/generated_txt/cargo-rustdoc.txt
index da7ee6b..95401d1 100644
--- a/src/doc/man/generated_txt/cargo-rustdoc.txt
+++ b/src/doc/man/generated_txt/cargo-rustdoc.txt
@@ -136,8 +136,8 @@
 
            o  Any supported target in rustc --print target-list.
 
-           o  "host", which will internally be substituted by the host’s
-              target. This can be particularly useful if you’re
+           o  "host-tuple", which will internally be substituted by the
+              host’s target. This can be particularly useful if you’re
               cross-compiling some crates, and don’t want to specify your
               host’s machine as a target (for instance, an xtask in a shared
               project that may be worked on by many hosts).
diff --git a/src/doc/man/generated_txt/cargo-test.txt b/src/doc/man/generated_txt/cargo-test.txt
index fc74f7d..6190b15 100644
--- a/src/doc/man/generated_txt/cargo-test.txt
+++ b/src/doc/man/generated_txt/cargo-test.txt
@@ -250,8 +250,8 @@
 
            o  Any supported target in rustc --print target-list.
 
-           o  "host", which will internally be substituted by the host’s
-              target. This can be particularly useful if you’re
+           o  "host-tuple", which will internally be substituted by the
+              host’s target. This can be particularly useful if you’re
               cross-compiling some crates, and don’t want to specify your
               host’s machine as a target (for instance, an xtask in a shared
               project that may be worked on by many hosts).
diff --git a/src/doc/man/includes/options-target-triple.md b/src/doc/man/includes/options-target-triple.md
index 977b52b..990599e 100644
--- a/src/doc/man/includes/options-target-triple.md
+++ b/src/doc/man/includes/options-target-triple.md
@@ -7,7 +7,7 @@
 
 Possible values:
 - Any supported target in `rustc --print target-list`.
-- `"host"`, which will internally be substituted by the host's target. This can be particularly useful if you're cross-compiling some crates, and don't want to specify your host's machine as a target (for instance, an `xtask` in a shared project that may be worked on by many hosts).
+- `"host-tuple"`, which will internally be substituted by the host's target. This can be particularly useful if you're cross-compiling some crates, and don't want to specify your host's machine as a target (for instance, an `xtask` in a shared project that may be worked on by many hosts).
 - A path to a custom target specification. See [Custom Target Lookup Path](../../rustc/targets/custom.html#custom-target-lookup-path) for more information.
 
 
diff --git a/src/doc/src/CHANGELOG.md b/src/doc/src/CHANGELOG.md
index 1e7a748..3c89cf1 100644
--- a/src/doc/src/CHANGELOG.md
+++ b/src/doc/src/CHANGELOG.md
@@ -1,20 +1,208 @@
 # Changelog
 
-## Cargo 1.91 (2025-10-30)
-[840b83a1...HEAD](https://github.com/rust-lang/cargo/compare/840b83a1...HEAD)
+## Cargo 1.92 (2025-12-11)
+[24bb93c3...HEAD](https://github.com/rust-lang/cargo/compare/24bb93c3...HEAD)
 
 ### Added
 
+- Adds ghostty as supported terminal for term integration (OSC 9;4)
+  [#15977](https://github.com/rust-lang/cargo/pull/15977)
+
 ### Changed
 
+- Prefer unicode ellipses when truncating progress
+  [#15955](https://github.com/rust-lang/cargo/pull/15955)
+- Eliminate the last three "did you mean" warning phrasings
+  [#15356](https://github.com/rust-lang/cargo/pull/15356)
+- Clarify warning for using `features` or `default-features` in `patch`
+  [#15953](https://github.com/rust-lang/cargo/pull/15953)
+- Report all future-incompat content as a single annotate-snippet Report
+  [#15943](https://github.com/rust-lang/cargo/pull/15943)
+- cargo-info: Suggest a more universal `cargo tree` command
+  [#15954](https://github.com/rust-lang/cargo/pull/15954)
+- cargo-publish: Switch the 'ctrl-c on wait' line to a help message
+  [#15942](https://github.com/rust-lang/cargo/pull/15942)
+
 ### Fixed
 
 ### Nightly only
 
+- `-Zbuild-std`: test move away from panic_immediate_abort
+  [#16006](https://github.com/rust-lang/cargo/pull/16006)
+- `-Zcargo-lints`: Add lint for global use of `hint-mostly-unused`
+  [#15995](https://github.com/rust-lang/cargo/pull/15995)
+- `-Zscript`: Try alternative len code fences
+  [#15952](https://github.com/rust-lang/cargo/pull/15952)
+- `-Zscript`: Improve error quality
+  [#15972](https://github.com/rust-lang/cargo/pull/15972)
+- `-Zscript`: Show error source to users
+  [#15939](https://github.com/rust-lang/cargo/pull/15939)
+- `-Zscript`: Only allow horizontal whitespace after fences
+  [#15975](https://github.com/rust-lang/cargo/pull/15975)
+- `native-completions`: Added completion for `--features` flag
+  [#15309](https://github.com/rust-lang/cargo/pull/15309)
+- `native-completions`: Show local crates/features over other members
+  [#15956](https://github.com/rust-lang/cargo/pull/15956)
+- `native-completions`:: Allow completions for third-party subcommand names
+  [#15961](https://github.com/rust-lang/cargo/pull/15961)
+
 ### Documentation
 
+- 🎉 Add a new "Optimizing Build Performance" chapter
+  [#15924](https://github.com/rust-lang/cargo/pull/15924)
+  [#15970](https://github.com/rust-lang/cargo/pull/15970)
+- Clarify git sources vs git registries in source replacement documentation
+  [#15974](https://github.com/rust-lang/cargo/pull/15974)
+- Clarify what we mean by omitting features in registry index documentation
+  [#15957](https://github.com/rust-lang/cargo/pull/15957)
+- Clarify the role of the lockfile in dependency resolution
+  [#15958](https://github.com/rust-lang/cargo/pull/15958)
+- Clarify multiple version requirement behavior
+  [#15979](https://github.com/rust-lang/cargo/pull/15979)
+- contrib: Move docs building process to contributor guide
+  [#15854](https://github.com/rust-lang/cargo/pull/15854)
+
 ### Internal
 
+- Make GlobalContext Sync
+  [#15967](https://github.com/rust-lang/cargo/pull/15967)
+- cargo-util-schemas: Move lockfile schemas in
+  [#15980](https://github.com/rust-lang/cargo/pull/15980)
+  [#15990](https://github.com/rust-lang/cargo/pull/15990)
+- ci: Skip check-version-bump ci job in forks
+  [#15959](https://github.com/rust-lang/cargo/pull/15959)
+- Update dependencies.
+  [#15988](https://github.com/rust-lang/cargo/pull/15988)
+  [#15984](https://github.com/rust-lang/cargo/pull/15984)
+  [#15989](https://github.com/rust-lang/cargo/pull/15989)
+  [#15993](https://github.com/rust-lang/cargo/pull/15993)
+
+## Cargo 1.91 (2025-10-30)
+[840b83a1...rust-1.91.0](https://github.com/rust-lang/cargo/compare/840b83a1...rust-1.91.0)
+
+### Added
+
+- 🎉 Stabilize `build.build-dir`.
+  This config sets the directory where intermediate build artifacts are stored.
+  These artifacts are produced by Cargo and rustc during the build process.
+  End users usually won't need to interact with them, and the layout inside
+  `build-dir` is an implementation detail that may change without notice.
+  ([config doc](https://doc.rust-lang.org/nightly/cargo/reference/config.html#buildbuild-dir))
+  ([build cache doc](https://doc.rust-lang.org/nightly/cargo/reference/build-cache.html))
+  [#15833](https://github.com/rust-lang/cargo/pull/15833)
+  [#15840](https://github.com/rust-lang/cargo/pull/15840)
+
+### Changed
+
+- ❗️ `cargo publish` no longer keeps `.crate` tarballs as final build artifacts
+  when `build.build-dir` is set. These tarballs were previously included due to
+  an oversight and are now treated as intermediate artifacts.
+  To get `.crate` tarballs as final artifacts, use `cargo package`.
+  In the next version, this change will apply regardless of `build.build-dir`.
+  [#15910](https://github.com/rust-lang/cargo/pull/15910)
+- Adjust Cargo messages to match rustc diagnostic style
+  [#15928](https://github.com/rust-lang/cargo/pull/15928)
+- More helpful error for invalid `cargo-features = []`
+  [#15781](https://github.com/rust-lang/cargo/pull/15781)
+- Don't stop at first error when emitting lints and warnings
+  [#15889](https://github.com/rust-lang/cargo/pull/15889)
+- Show the bad manifest path in the error message
+  [#15896](https://github.com/rust-lang/cargo/pull/15896)
+- Suggest workspace hints for invalid boolean dependencies
+  [#15507](https://github.com/rust-lang/cargo/pull/15507)
+- cargo-package: Always reuse the workspace's target-dir during the package
+  verification. Previously Cargo created a new standalone target directory
+  within the unpacked source.
+  [#15783](https://github.com/rust-lang/cargo/pull/15783)
+- cargo-publish: Add more context to publish-failed error message
+  [#15879](https://github.com/rust-lang/cargo/pull/15879)
+
+### Fixed
+
+### Nightly only
+
+- 🔥 `-Zsection-timings` extend the output of `cargo build --timings`. It tells
+  rustc to produce timings of individual compilation sections, which will be
+  then displayed in the timings HTML/JSON output.
+  ([docs](https://doc.rust-lang.org/nightly/cargo/reference/unstable.html#section-timings))
+  [#15780](https://github.com/rust-lang/cargo/pull/15780)
+  [#15923](https://github.com/rust-lang/cargo/pull/15923)
+- 🔥 `-Zbuild-dir-new-layout` enables the new build-dir filesystem layout, which
+  unblocks work towards caching and locking improvements.
+  ([docs](https://doc.rust-lang.org/nightly/cargo/reference/unstable.html#build-dir-new-layout))
+  ([project goal](https://rust-lang.github.io/rust-project-goals/2025h2/cargo-build-dir-layout.html))
+  [#15848](https://github.com/rust-lang/cargo/pull/15848)
+- 🔥 `-Zbuild-analysis` records and persists detailed build metrics (timings, rebuild reasons, etc.)
+  across runs, with new commands to query past builds.
+  ([docs](https://doc.rust-lang.org/nightly/cargo/reference/unstable.html#build-analysis))
+  ([project goal](https://rust-lang.github.io/rust-project-goals/2025h2/cargo-build-analysis.html))
+  [#15845](https://github.com/rust-lang/cargo/pull/15845)
+- `multiple-build-scripts`:  Accessing each build script's `OUT_DIR` and in the
+  correct order
+  [#15776](https://github.com/rust-lang/cargo/pull/15776)
+- `-Zcargo-lints`: Linting system infra improvement
+  [#15865](https://github.com/rust-lang/cargo/pull/15865)
+- `-Zscript`: Cover some frontmatter corner cases
+  [#15886](https://github.com/rust-lang/cargo/pull/15886)
+- `-Zscript`: Match test updates in rustc
+  [#15878](https://github.com/rust-lang/cargo/pull/15878)
+- `-Zscript`: Switch frontmatter tests to end-to-end
+  [#15899](https://github.com/rust-lang/cargo/pull/15899)
+- `-Zscript`: Report script manifest errors for the right line number
+  [#15927](https://github.com/rust-lang/cargo/pull/15927)
+- `-Zscript`: Pull out as a dedicated mod
+  [#15914](https://github.com/rust-lang/cargo/pull/15914)
+
+### Documentation
+
+- Clarify that `cargo doc --no-deps` is cumulative and won’t delete prev
+  [#15800](https://github.com/rust-lang/cargo/pull/15800)
+- Switch from `--nocapture` to `--no-capture` in docs and help text.
+  [#15930](https://github.com/rust-lang/cargo/pull/15930)
+- Mention how Cargo fetch git submodules
+  [#15853](https://github.com/rust-lang/cargo/pull/15853)
+  [#15860](https://github.com/rust-lang/cargo/pull/15860)
+- Link out to the Plumbing commands effort
+  [#15821](https://github.com/rust-lang/cargo/pull/15821)
+- Switch to using native mdbook fragment redirects
+  [#15861](https://github.com/rust-lang/cargo/pull/15861)
+- Reorder `lto` options in profiles
+  [#15841](https://github.com/rust-lang/cargo/pull/15841)
+  [#15855](https://github.com/rust-lang/cargo/pull/15855)
+
+### Internal
+
+- Replace ad-hoc flock implementation with std flock
+  [#15935](https://github.com/rust-lang/cargo/pull/15935)
+  [#15941](https://github.com/rust-lang/cargo/pull/15941)
+- Prepare for annotate-snippets `Report`s being generated in more places
+  [#15920](https://github.com/rust-lang/cargo/pull/15920)
+  [#15926](https://github.com/rust-lang/cargo/pull/15926)
+- test: avoid hardcoded target spec json
+  [#15880](https://github.com/rust-lang/cargo/pull/15880)
+- test: Ensure consistent behavior regardless of rustup use
+  [#15949](https://github.com/rust-lang/cargo/pull/15949)
+- test: Switch more expected results to snapshots for credential process
+  [#15929](https://github.com/rust-lang/cargo/pull/15929)
+- ci: Add Arm64 Windows CI jobs
+  [#15790](https://github.com/rust-lang/cargo/pull/15790)
+- ci: remove x86_64-apple-darwin from CI and tests
+  [#15831](https://github.com/rust-lang/cargo/pull/15831)
+- Update dependencies.
+  [#15795](https://github.com/rust-lang/cargo/pull/15795)
+  [#15804](https://github.com/rust-lang/cargo/pull/15804)
+  [#15815](https://github.com/rust-lang/cargo/pull/15815)
+  [#15816](https://github.com/rust-lang/cargo/pull/15816)
+  [#15819](https://github.com/rust-lang/cargo/pull/15819)
+  [#15825](https://github.com/rust-lang/cargo/pull/15825)
+  [#15832](https://github.com/rust-lang/cargo/pull/15832)
+  [#15851](https://github.com/rust-lang/cargo/pull/15851)
+  [#15898](https://github.com/rust-lang/cargo/pull/15898)
+  [#15904](https://github.com/rust-lang/cargo/pull/15904)
+  [#15909](https://github.com/rust-lang/cargo/pull/15909)
+  [#15918](https://github.com/rust-lang/cargo/pull/15918)
+  [#15950](https://github.com/rust-lang/cargo/pull/15950)
+
 ## Cargo 1.90 (2025-09-18)
 [c24e1064...rust-1.90.0](https://github.com/rust-lang/cargo/compare/c24e1064...rust-1.90.0)
 
diff --git a/src/doc/src/commands/cargo-bench.md b/src/doc/src/commands/cargo-bench.md
index a1c5192..0a0f24d 100644
--- a/src/doc/src/commands/cargo-bench.md
+++ b/src/doc/src/commands/cargo-bench.md
@@ -261,7 +261,7 @@
 <p>Possible values:</p>
 <ul>
 <li>Any supported target in <code>rustc --print target-list</code>.</li>
-<li><code>"host"</code>, which will internally be substituted by the host’s target. This can be particularly useful if you’re cross-compiling some crates, and don’t want to specify your host’s machine as a target (for instance, an <code>xtask</code> in a shared project that may be worked on by many hosts).</li>
+<li><code>"host-tuple"</code>, which will internally be substituted by the host’s target. This can be particularly useful if you’re cross-compiling some crates, and don’t want to specify your host’s machine as a target (for instance, an <code>xtask</code> in a shared project that may be worked on by many hosts).</li>
 <li>A path to a custom target specification. See <a href="../../rustc/targets/custom.html#custom-target-lookup-path">Custom Target Lookup Path</a> for more information.</li>
 </ul>
 <p>This may also be specified with the <code>build.target</code> <a href="../reference/config.html">config value</a>.</p>
diff --git a/src/doc/src/commands/cargo-build.md b/src/doc/src/commands/cargo-build.md
index 6438755..c6b82be 100644
--- a/src/doc/src/commands/cargo-build.md
+++ b/src/doc/src/commands/cargo-build.md
@@ -176,7 +176,7 @@
 <p>Possible values:</p>
 <ul>
 <li>Any supported target in <code>rustc --print target-list</code>.</li>
-<li><code>"host"</code>, which will internally be substituted by the host’s target. This can be particularly useful if you’re cross-compiling some crates, and don’t want to specify your host’s machine as a target (for instance, an <code>xtask</code> in a shared project that may be worked on by many hosts).</li>
+<li><code>"host-tuple"</code>, which will internally be substituted by the host’s target. This can be particularly useful if you’re cross-compiling some crates, and don’t want to specify your host’s machine as a target (for instance, an <code>xtask</code> in a shared project that may be worked on by many hosts).</li>
 <li>A path to a custom target specification. See <a href="../../rustc/targets/custom.html#custom-target-lookup-path">Custom Target Lookup Path</a> for more information.</li>
 </ul>
 <p>This may also be specified with the <code>build.target</code> <a href="../reference/config.html">config value</a>.</p>
diff --git a/src/doc/src/commands/cargo-check.md b/src/doc/src/commands/cargo-check.md
index a80c704..158c4f7 100644
--- a/src/doc/src/commands/cargo-check.md
+++ b/src/doc/src/commands/cargo-check.md
@@ -172,7 +172,7 @@
 <p>Possible values:</p>
 <ul>
 <li>Any supported target in <code>rustc --print target-list</code>.</li>
-<li><code>"host"</code>, which will internally be substituted by the host’s target. This can be particularly useful if you’re cross-compiling some crates, and don’t want to specify your host’s machine as a target (for instance, an <code>xtask</code> in a shared project that may be worked on by many hosts).</li>
+<li><code>"host-tuple"</code>, which will internally be substituted by the host’s target. This can be particularly useful if you’re cross-compiling some crates, and don’t want to specify your host’s machine as a target (for instance, an <code>xtask</code> in a shared project that may be worked on by many hosts).</li>
 <li>A path to a custom target specification. See <a href="../../rustc/targets/custom.html#custom-target-lookup-path">Custom Target Lookup Path</a> for more information.</li>
 </ul>
 <p>This may also be specified with the <code>build.target</code> <a href="../reference/config.html">config value</a>.</p>
diff --git a/src/doc/src/commands/cargo-clean.md b/src/doc/src/commands/cargo-clean.md
index 1eb9881..cc24f7b 100644
--- a/src/doc/src/commands/cargo-clean.md
+++ b/src/doc/src/commands/cargo-clean.md
@@ -64,7 +64,7 @@
 <p>Possible values:</p>
 <ul>
 <li>Any supported target in <code>rustc --print target-list</code>.</li>
-<li><code>"host"</code>, which will internally be substituted by the host’s target. This can be particularly useful if you’re cross-compiling some crates, and don’t want to specify your host’s machine as a target (for instance, an <code>xtask</code> in a shared project that may be worked on by many hosts).</li>
+<li><code>"host-tuple"</code>, which will internally be substituted by the host’s target. This can be particularly useful if you’re cross-compiling some crates, and don’t want to specify your host’s machine as a target (for instance, an <code>xtask</code> in a shared project that may be worked on by many hosts).</li>
 <li>A path to a custom target specification. See <a href="../../rustc/targets/custom.html#custom-target-lookup-path">Custom Target Lookup Path</a> for more information.</li>
 </ul>
 <p>This may also be specified with the <code>build.target</code> <a href="../reference/config.html">config value</a>.</p>
diff --git a/src/doc/src/commands/cargo-doc.md b/src/doc/src/commands/cargo-doc.md
index 76c0754..0afb4f8 100644
--- a/src/doc/src/commands/cargo-doc.md
+++ b/src/doc/src/commands/cargo-doc.md
@@ -153,7 +153,7 @@
 <p>Possible values:</p>
 <ul>
 <li>Any supported target in <code>rustc --print target-list</code>.</li>
-<li><code>"host"</code>, which will internally be substituted by the host’s target. This can be particularly useful if you’re cross-compiling some crates, and don’t want to specify your host’s machine as a target (for instance, an <code>xtask</code> in a shared project that may be worked on by many hosts).</li>
+<li><code>"host-tuple"</code>, which will internally be substituted by the host’s target. This can be particularly useful if you’re cross-compiling some crates, and don’t want to specify your host’s machine as a target (for instance, an <code>xtask</code> in a shared project that may be worked on by many hosts).</li>
 <li>A path to a custom target specification. See <a href="../../rustc/targets/custom.html#custom-target-lookup-path">Custom Target Lookup Path</a> for more information.</li>
 </ul>
 <p>This may also be specified with the <code>build.target</code> <a href="../reference/config.html">config value</a>.</p>
diff --git a/src/doc/src/commands/cargo-fetch.md b/src/doc/src/commands/cargo-fetch.md
index 4437624..81d3e5e 100644
--- a/src/doc/src/commands/cargo-fetch.md
+++ b/src/doc/src/commands/cargo-fetch.md
@@ -34,7 +34,7 @@
 <p>Possible values:</p>
 <ul>
 <li>Any supported target in <code>rustc --print target-list</code>.</li>
-<li><code>"host"</code>, which will internally be substituted by the host’s target. This can be particularly useful if you’re cross-compiling some crates, and don’t want to specify your host’s machine as a target (for instance, an <code>xtask</code> in a shared project that may be worked on by many hosts).</li>
+<li><code>"host-tuple"</code>, which will internally be substituted by the host’s target. This can be particularly useful if you’re cross-compiling some crates, and don’t want to specify your host’s machine as a target (for instance, an <code>xtask</code> in a shared project that may be worked on by many hosts).</li>
 <li>A path to a custom target specification. See <a href="../../rustc/targets/custom.html#custom-target-lookup-path">Custom Target Lookup Path</a> for more information.</li>
 </ul>
 <p>This may also be specified with the <code>build.target</code> <a href="../reference/config.html">config value</a>.</p>
diff --git a/src/doc/src/commands/cargo-fix.md b/src/doc/src/commands/cargo-fix.md
index 5a0dfcc..4f9eacf 100644
--- a/src/doc/src/commands/cargo-fix.md
+++ b/src/doc/src/commands/cargo-fix.md
@@ -252,7 +252,7 @@
 <p>Possible values:</p>
 <ul>
 <li>Any supported target in <code>rustc --print target-list</code>.</li>
-<li><code>"host"</code>, which will internally be substituted by the host’s target. This can be particularly useful if you’re cross-compiling some crates, and don’t want to specify your host’s machine as a target (for instance, an <code>xtask</code> in a shared project that may be worked on by many hosts).</li>
+<li><code>"host-tuple"</code>, which will internally be substituted by the host’s target. This can be particularly useful if you’re cross-compiling some crates, and don’t want to specify your host’s machine as a target (for instance, an <code>xtask</code> in a shared project that may be worked on by many hosts).</li>
 <li>A path to a custom target specification. See <a href="../../rustc/targets/custom.html#custom-target-lookup-path">Custom Target Lookup Path</a> for more information.</li>
 </ul>
 <p>This may also be specified with the <code>build.target</code> <a href="../reference/config.html">config value</a>.</p>
diff --git a/src/doc/src/commands/cargo-install.md b/src/doc/src/commands/cargo-install.md
index 8e272a8..c1e9471 100644
--- a/src/doc/src/commands/cargo-install.md
+++ b/src/doc/src/commands/cargo-install.md
@@ -217,7 +217,7 @@
 <p>Possible values:</p>
 <ul>
 <li>Any supported target in <code>rustc --print target-list</code>.</li>
-<li><code>"host"</code>, which will internally be substituted by the host’s target. This can be particularly useful if you’re cross-compiling some crates, and don’t want to specify your host’s machine as a target (for instance, an <code>xtask</code> in a shared project that may be worked on by many hosts).</li>
+<li><code>"host-tuple"</code>, which will internally be substituted by the host’s target. This can be particularly useful if you’re cross-compiling some crates, and don’t want to specify your host’s machine as a target (for instance, an <code>xtask</code> in a shared project that may be worked on by many hosts).</li>
 <li>A path to a custom target specification. See <a href="../../rustc/targets/custom.html#custom-target-lookup-path">Custom Target Lookup Path</a> for more information.</li>
 </ul>
 <p>This may also be specified with the <code>build.target</code> <a href="../reference/config.html">config value</a>.</p>
diff --git a/src/doc/src/commands/cargo-package.md b/src/doc/src/commands/cargo-package.md
index 5c75c00..75cbf29 100644
--- a/src/doc/src/commands/cargo-package.md
+++ b/src/doc/src/commands/cargo-package.md
@@ -207,7 +207,7 @@
 <p>Possible values:</p>
 <ul>
 <li>Any supported target in <code>rustc --print target-list</code>.</li>
-<li><code>"host"</code>, which will internally be substituted by the host’s target. This can be particularly useful if you’re cross-compiling some crates, and don’t want to specify your host’s machine as a target (for instance, an <code>xtask</code> in a shared project that may be worked on by many hosts).</li>
+<li><code>"host-tuple"</code>, which will internally be substituted by the host’s target. This can be particularly useful if you’re cross-compiling some crates, and don’t want to specify your host’s machine as a target (for instance, an <code>xtask</code> in a shared project that may be worked on by many hosts).</li>
 <li>A path to a custom target specification. See <a href="../../rustc/targets/custom.html#custom-target-lookup-path">Custom Target Lookup Path</a> for more information.</li>
 </ul>
 <p>This may also be specified with the <code>build.target</code> <a href="../reference/config.html">config value</a>.</p>
diff --git a/src/doc/src/commands/cargo-publish.md b/src/doc/src/commands/cargo-publish.md
index 6b6081d..ccdb093 100644
--- a/src/doc/src/commands/cargo-publish.md
+++ b/src/doc/src/commands/cargo-publish.md
@@ -127,7 +127,7 @@
 <p>Possible values:</p>
 <ul>
 <li>Any supported target in <code>rustc --print target-list</code>.</li>
-<li><code>"host"</code>, which will internally be substituted by the host’s target. This can be particularly useful if you’re cross-compiling some crates, and don’t want to specify your host’s machine as a target (for instance, an <code>xtask</code> in a shared project that may be worked on by many hosts).</li>
+<li><code>"host-tuple"</code>, which will internally be substituted by the host’s target. This can be particularly useful if you’re cross-compiling some crates, and don’t want to specify your host’s machine as a target (for instance, an <code>xtask</code> in a shared project that may be worked on by many hosts).</li>
 <li>A path to a custom target specification. See <a href="../../rustc/targets/custom.html#custom-target-lookup-path">Custom Target Lookup Path</a> for more information.</li>
 </ul>
 <p>This may also be specified with the <code>build.target</code> <a href="../reference/config.html">config value</a>.</p>
diff --git a/src/doc/src/commands/cargo-run.md b/src/doc/src/commands/cargo-run.md
index 968dbda..3fae83c 100644
--- a/src/doc/src/commands/cargo-run.md
+++ b/src/doc/src/commands/cargo-run.md
@@ -93,7 +93,7 @@
 <p>Possible values:</p>
 <ul>
 <li>Any supported target in <code>rustc --print target-list</code>.</li>
-<li><code>"host"</code>, which will internally be substituted by the host’s target. This can be particularly useful if you’re cross-compiling some crates, and don’t want to specify your host’s machine as a target (for instance, an <code>xtask</code> in a shared project that may be worked on by many hosts).</li>
+<li><code>"host-tuple"</code>, which will internally be substituted by the host’s target. This can be particularly useful if you’re cross-compiling some crates, and don’t want to specify your host’s machine as a target (for instance, an <code>xtask</code> in a shared project that may be worked on by many hosts).</li>
 <li>A path to a custom target specification. See <a href="../../rustc/targets/custom.html#custom-target-lookup-path">Custom Target Lookup Path</a> for more information.</li>
 </ul>
 <p>This may also be specified with the <code>build.target</code> <a href="../reference/config.html">config value</a>.</p>
diff --git a/src/doc/src/commands/cargo-rustc.md b/src/doc/src/commands/cargo-rustc.md
index 73a1681..979c573 100644
--- a/src/doc/src/commands/cargo-rustc.md
+++ b/src/doc/src/commands/cargo-rustc.md
@@ -165,7 +165,7 @@
 <p>Possible values:</p>
 <ul>
 <li>Any supported target in <code>rustc --print target-list</code>.</li>
-<li><code>"host"</code>, which will internally be substituted by the host’s target. This can be particularly useful if you’re cross-compiling some crates, and don’t want to specify your host’s machine as a target (for instance, an <code>xtask</code> in a shared project that may be worked on by many hosts).</li>
+<li><code>"host-tuple"</code>, which will internally be substituted by the host’s target. This can be particularly useful if you’re cross-compiling some crates, and don’t want to specify your host’s machine as a target (for instance, an <code>xtask</code> in a shared project that may be worked on by many hosts).</li>
 <li>A path to a custom target specification. See <a href="../../rustc/targets/custom.html#custom-target-lookup-path">Custom Target Lookup Path</a> for more information.</li>
 </ul>
 <p>This may also be specified with the <code>build.target</code> <a href="../reference/config.html">config value</a>.</p>
diff --git a/src/doc/src/commands/cargo-rustdoc.md b/src/doc/src/commands/cargo-rustdoc.md
index 8ae1559..4e0efe1 100644
--- a/src/doc/src/commands/cargo-rustdoc.md
+++ b/src/doc/src/commands/cargo-rustdoc.md
@@ -171,7 +171,7 @@
 <p>Possible values:</p>
 <ul>
 <li>Any supported target in <code>rustc --print target-list</code>.</li>
-<li><code>"host"</code>, which will internally be substituted by the host’s target. This can be particularly useful if you’re cross-compiling some crates, and don’t want to specify your host’s machine as a target (for instance, an <code>xtask</code> in a shared project that may be worked on by many hosts).</li>
+<li><code>"host-tuple"</code>, which will internally be substituted by the host’s target. This can be particularly useful if you’re cross-compiling some crates, and don’t want to specify your host’s machine as a target (for instance, an <code>xtask</code> in a shared project that may be worked on by many hosts).</li>
 <li>A path to a custom target specification. See <a href="../../rustc/targets/custom.html#custom-target-lookup-path">Custom Target Lookup Path</a> for more information.</li>
 </ul>
 <p>This may also be specified with the <code>build.target</code> <a href="../reference/config.html">config value</a>.</p>
diff --git a/src/doc/src/commands/cargo-test.md b/src/doc/src/commands/cargo-test.md
index 9f8716b..1b6a31a 100644
--- a/src/doc/src/commands/cargo-test.md
+++ b/src/doc/src/commands/cargo-test.md
@@ -283,7 +283,7 @@
 <p>Possible values:</p>
 <ul>
 <li>Any supported target in <code>rustc --print target-list</code>.</li>
-<li><code>"host"</code>, which will internally be substituted by the host’s target. This can be particularly useful if you’re cross-compiling some crates, and don’t want to specify your host’s machine as a target (for instance, an <code>xtask</code> in a shared project that may be worked on by many hosts).</li>
+<li><code>"host-tuple"</code>, which will internally be substituted by the host’s target. This can be particularly useful if you’re cross-compiling some crates, and don’t want to specify your host’s machine as a target (for instance, an <code>xtask</code> in a shared project that may be worked on by many hosts).</li>
 <li>A path to a custom target specification. See <a href="../../rustc/targets/custom.html#custom-target-lookup-path">Custom Target Lookup Path</a> for more information.</li>
 </ul>
 <p>This may also be specified with the <code>build.target</code> <a href="../reference/config.html">config value</a>.</p>
diff --git a/src/doc/src/reference/config.md b/src/doc/src/reference/config.md
index b90aeb9..ecb68d7 100644
--- a/src/doc/src/reference/config.md
+++ b/src/doc/src/reference/config.md
@@ -462,7 +462,7 @@
 
 Possible values:
 - Any supported target in `rustc --print target-list`.
-- `"host"`, which will internally be substituted by the host's target. This can be particularly useful if you're cross-compiling some crates, and don't want to specify your host's machine as a target (for instance, an `xtask` in a shared project that may be worked on by many hosts).
+- `"host-tuple"`, which will internally be substituted by the host's target. This can be particularly useful if you're cross-compiling some crates, and don't want to specify your host's machine as a target (for instance, an `xtask` in a shared project that may be worked on by many hosts).
 - A path to a custom target specification. See [Custom Target Lookup Path](../../rustc/targets/custom.html#custom-target-lookup-path) for more information.
 
 Can be overridden with the `--target` CLI option.
diff --git a/src/doc/src/reference/lints.md b/src/doc/src/reference/lints.md
index d1f1244..8393efb 100644
--- a/src/doc/src/reference/lints.md
+++ b/src/doc/src/reference/lints.md
@@ -5,8 +5,37 @@
 ## Warn-by-default
 
 These lints are all set to the 'warn' level by default.
+- [`blanket_hint_mostly_unused`](#blanket_hint_mostly_unused)
 - [`unknown_lints`](#unknown_lints)
 
+## `blanket_hint_mostly_unused`
+Set to `warn` by default
+
+### What it does
+Checks if `hint-mostly-unused` being applied to all dependencies.
+
+### Why it is bad
+`hint-mostly-unused` indicates that most of a crate's API surface will go
+unused by anything depending on it; this hint can speed up the build by
+attempting to minimize compilation time for items that aren't used at all.
+Misapplication to crates that don't fit that criteria will slow down the build
+rather than speeding it up. It should be selectively applied to dependencies
+that meet these criteria. Applying it globally is always a misapplication and
+will likely slow down the build.
+
+### Example
+```toml
+[profile.dev.package."*"]
+hint-mostly-unused = true
+```
+
+Should instead be:
+```toml
+[profile.dev.package.huge-mostly-unused-dependency]
+hint-mostly-unused = true
+```
+
+
 ## `unknown_lints`
 Set to `warn` by default
 
diff --git a/src/doc/src/reference/unstable.md b/src/doc/src/reference/unstable.md
index c8b6423..ee90cb7 100644
--- a/src/doc/src/reference/unstable.md
+++ b/src/doc/src/reference/unstable.md
@@ -125,7 +125,6 @@
     * [gitoxide](#gitoxide) --- Use `gitoxide` instead of `git2` for a set of operations.
     * [script](#script) --- Enable support for single-file `.rs` packages.
     * [lockfile-path](#lockfile-path) --- Allows to specify a path to lockfile other than the default path `<workspace_root>/Cargo.lock`.
-    * [package-workspace](#package-workspace) --- Allows for packaging and publishing multiple crates in a workspace.
     * [native-completions](#native-completions) --- Move cargo shell completions to native completions.
     * [warnings](#warnings) --- controls warning behavior; options for allowing or denying warnings.
     * [Package message format](#package-message-format) --- Message format for `cargo package`.
diff --git a/src/etc/man/cargo-bench.1 b/src/etc/man/cargo-bench.1
index 62f056e..8683fdc 100644
--- a/src/etc/man/cargo-bench.1
+++ b/src/etc/man/cargo-bench.1
@@ -277,7 +277,7 @@
 .RE
 .sp
 .RS 4
-\h'-04'\(bu\h'+03'\fB"host"\fR, which will internally be substituted by the host\[cq]s target. This can be particularly useful if you\[cq]re cross\-compiling some crates, and don\[cq]t want to specify your host\[cq]s machine as a target (for instance, an \fBxtask\fR in a shared project that may be worked on by many hosts).
+\h'-04'\(bu\h'+03'\fB"host\-tuple"\fR, which will internally be substituted by the host\[cq]s target. This can be particularly useful if you\[cq]re cross\-compiling some crates, and don\[cq]t want to specify your host\[cq]s machine as a target (for instance, an \fBxtask\fR in a shared project that may be worked on by many hosts).
 .RE
 .sp
 .RS 4
diff --git a/src/etc/man/cargo-build.1 b/src/etc/man/cargo-build.1
index dd478a5..dfb32de 100644
--- a/src/etc/man/cargo-build.1
+++ b/src/etc/man/cargo-build.1
@@ -176,7 +176,7 @@
 .RE
 .sp
 .RS 4
-\h'-04'\(bu\h'+03'\fB"host"\fR, which will internally be substituted by the host\[cq]s target. This can be particularly useful if you\[cq]re cross\-compiling some crates, and don\[cq]t want to specify your host\[cq]s machine as a target (for instance, an \fBxtask\fR in a shared project that may be worked on by many hosts).
+\h'-04'\(bu\h'+03'\fB"host\-tuple"\fR, which will internally be substituted by the host\[cq]s target. This can be particularly useful if you\[cq]re cross\-compiling some crates, and don\[cq]t want to specify your host\[cq]s machine as a target (for instance, an \fBxtask\fR in a shared project that may be worked on by many hosts).
 .RE
 .sp
 .RS 4
diff --git a/src/etc/man/cargo-check.1 b/src/etc/man/cargo-check.1
index 0fd8d9b..a75ea2c 100644
--- a/src/etc/man/cargo-check.1
+++ b/src/etc/man/cargo-check.1
@@ -172,7 +172,7 @@
 .RE
 .sp
 .RS 4
-\h'-04'\(bu\h'+03'\fB"host"\fR, which will internally be substituted by the host\[cq]s target. This can be particularly useful if you\[cq]re cross\-compiling some crates, and don\[cq]t want to specify your host\[cq]s machine as a target (for instance, an \fBxtask\fR in a shared project that may be worked on by many hosts).
+\h'-04'\(bu\h'+03'\fB"host\-tuple"\fR, which will internally be substituted by the host\[cq]s target. This can be particularly useful if you\[cq]re cross\-compiling some crates, and don\[cq]t want to specify your host\[cq]s machine as a target (for instance, an \fBxtask\fR in a shared project that may be worked on by many hosts).
 .RE
 .sp
 .RS 4
diff --git a/src/etc/man/cargo-clean.1 b/src/etc/man/cargo-clean.1
index 4ca8ed9..60edaeb 100644
--- a/src/etc/man/cargo-clean.1
+++ b/src/etc/man/cargo-clean.1
@@ -67,7 +67,7 @@
 .RE
 .sp
 .RS 4
-\h'-04'\(bu\h'+03'\fB"host"\fR, which will internally be substituted by the host\[cq]s target. This can be particularly useful if you\[cq]re cross\-compiling some crates, and don\[cq]t want to specify your host\[cq]s machine as a target (for instance, an \fBxtask\fR in a shared project that may be worked on by many hosts).
+\h'-04'\(bu\h'+03'\fB"host\-tuple"\fR, which will internally be substituted by the host\[cq]s target. This can be particularly useful if you\[cq]re cross\-compiling some crates, and don\[cq]t want to specify your host\[cq]s machine as a target (for instance, an \fBxtask\fR in a shared project that may be worked on by many hosts).
 .RE
 .sp
 .RS 4
diff --git a/src/etc/man/cargo-doc.1 b/src/etc/man/cargo-doc.1
index cfae7bb..9b81b7a 100644
--- a/src/etc/man/cargo-doc.1
+++ b/src/etc/man/cargo-doc.1
@@ -147,7 +147,7 @@
 .RE
 .sp
 .RS 4
-\h'-04'\(bu\h'+03'\fB"host"\fR, which will internally be substituted by the host\[cq]s target. This can be particularly useful if you\[cq]re cross\-compiling some crates, and don\[cq]t want to specify your host\[cq]s machine as a target (for instance, an \fBxtask\fR in a shared project that may be worked on by many hosts).
+\h'-04'\(bu\h'+03'\fB"host\-tuple"\fR, which will internally be substituted by the host\[cq]s target. This can be particularly useful if you\[cq]re cross\-compiling some crates, and don\[cq]t want to specify your host\[cq]s machine as a target (for instance, an \fBxtask\fR in a shared project that may be worked on by many hosts).
 .RE
 .sp
 .RS 4
diff --git a/src/etc/man/cargo-fetch.1 b/src/etc/man/cargo-fetch.1
index 7260879..c2f4fdd 100644
--- a/src/etc/man/cargo-fetch.1
+++ b/src/etc/man/cargo-fetch.1
@@ -35,7 +35,7 @@
 .RE
 .sp
 .RS 4
-\h'-04'\(bu\h'+03'\fB"host"\fR, which will internally be substituted by the host\[cq]s target. This can be particularly useful if you\[cq]re cross\-compiling some crates, and don\[cq]t want to specify your host\[cq]s machine as a target (for instance, an \fBxtask\fR in a shared project that may be worked on by many hosts).
+\h'-04'\(bu\h'+03'\fB"host\-tuple"\fR, which will internally be substituted by the host\[cq]s target. This can be particularly useful if you\[cq]re cross\-compiling some crates, and don\[cq]t want to specify your host\[cq]s machine as a target (for instance, an \fBxtask\fR in a shared project that may be worked on by many hosts).
 .RE
 .sp
 .RS 4
diff --git a/src/etc/man/cargo-fix.1 b/src/etc/man/cargo-fix.1
index 0e79e99..26ad486 100644
--- a/src/etc/man/cargo-fix.1
+++ b/src/etc/man/cargo-fix.1
@@ -267,7 +267,7 @@
 .RE
 .sp
 .RS 4
-\h'-04'\(bu\h'+03'\fB"host"\fR, which will internally be substituted by the host\[cq]s target. This can be particularly useful if you\[cq]re cross\-compiling some crates, and don\[cq]t want to specify your host\[cq]s machine as a target (for instance, an \fBxtask\fR in a shared project that may be worked on by many hosts).
+\h'-04'\(bu\h'+03'\fB"host\-tuple"\fR, which will internally be substituted by the host\[cq]s target. This can be particularly useful if you\[cq]re cross\-compiling some crates, and don\[cq]t want to specify your host\[cq]s machine as a target (for instance, an \fBxtask\fR in a shared project that may be worked on by many hosts).
 .RE
 .sp
 .RS 4
diff --git a/src/etc/man/cargo-install.1 b/src/etc/man/cargo-install.1
index 04c9064..1899430 100644
--- a/src/etc/man/cargo-install.1
+++ b/src/etc/man/cargo-install.1
@@ -252,7 +252,7 @@
 .RE
 .sp
 .RS 4
-\h'-04'\(bu\h'+03'\fB"host"\fR, which will internally be substituted by the host\[cq]s target. This can be particularly useful if you\[cq]re cross\-compiling some crates, and don\[cq]t want to specify your host\[cq]s machine as a target (for instance, an \fBxtask\fR in a shared project that may be worked on by many hosts).
+\h'-04'\(bu\h'+03'\fB"host\-tuple"\fR, which will internally be substituted by the host\[cq]s target. This can be particularly useful if you\[cq]re cross\-compiling some crates, and don\[cq]t want to specify your host\[cq]s machine as a target (for instance, an \fBxtask\fR in a shared project that may be worked on by many hosts).
 .RE
 .sp
 .RS 4
diff --git a/src/etc/man/cargo-package.1 b/src/etc/man/cargo-package.1
index 168f315..7d20c6f 100644
--- a/src/etc/man/cargo-package.1
+++ b/src/etc/man/cargo-package.1
@@ -249,7 +249,7 @@
 .RE
 .sp
 .RS 4
-\h'-04'\(bu\h'+03'\fB"host"\fR, which will internally be substituted by the host\[cq]s target. This can be particularly useful if you\[cq]re cross\-compiling some crates, and don\[cq]t want to specify your host\[cq]s machine as a target (for instance, an \fBxtask\fR in a shared project that may be worked on by many hosts).
+\h'-04'\(bu\h'+03'\fB"host\-tuple"\fR, which will internally be substituted by the host\[cq]s target. This can be particularly useful if you\[cq]re cross\-compiling some crates, and don\[cq]t want to specify your host\[cq]s machine as a target (for instance, an \fBxtask\fR in a shared project that may be worked on by many hosts).
 .RE
 .sp
 .RS 4
diff --git a/src/etc/man/cargo-publish.1 b/src/etc/man/cargo-publish.1
index 6d9d3a4..ba7f2bf 100644
--- a/src/etc/man/cargo-publish.1
+++ b/src/etc/man/cargo-publish.1
@@ -142,7 +142,7 @@
 .RE
 .sp
 .RS 4
-\h'-04'\(bu\h'+03'\fB"host"\fR, which will internally be substituted by the host\[cq]s target. This can be particularly useful if you\[cq]re cross\-compiling some crates, and don\[cq]t want to specify your host\[cq]s machine as a target (for instance, an \fBxtask\fR in a shared project that may be worked on by many hosts).
+\h'-04'\(bu\h'+03'\fB"host\-tuple"\fR, which will internally be substituted by the host\[cq]s target. This can be particularly useful if you\[cq]re cross\-compiling some crates, and don\[cq]t want to specify your host\[cq]s machine as a target (for instance, an \fBxtask\fR in a shared project that may be worked on by many hosts).
 .RE
 .sp
 .RS 4
diff --git a/src/etc/man/cargo-run.1 b/src/etc/man/cargo-run.1
index f1640ee..16afce2 100644
--- a/src/etc/man/cargo-run.1
+++ b/src/etc/man/cargo-run.1
@@ -82,7 +82,7 @@
 .RE
 .sp
 .RS 4
-\h'-04'\(bu\h'+03'\fB"host"\fR, which will internally be substituted by the host\[cq]s target. This can be particularly useful if you\[cq]re cross\-compiling some crates, and don\[cq]t want to specify your host\[cq]s machine as a target (for instance, an \fBxtask\fR in a shared project that may be worked on by many hosts).
+\h'-04'\(bu\h'+03'\fB"host\-tuple"\fR, which will internally be substituted by the host\[cq]s target. This can be particularly useful if you\[cq]re cross\-compiling some crates, and don\[cq]t want to specify your host\[cq]s machine as a target (for instance, an \fBxtask\fR in a shared project that may be worked on by many hosts).
 .RE
 .sp
 .RS 4
diff --git a/src/etc/man/cargo-rustc.1 b/src/etc/man/cargo-rustc.1
index 865e8db..c42752e 100644
--- a/src/etc/man/cargo-rustc.1
+++ b/src/etc/man/cargo-rustc.1
@@ -162,7 +162,7 @@
 .RE
 .sp
 .RS 4
-\h'-04'\(bu\h'+03'\fB"host"\fR, which will internally be substituted by the host\[cq]s target. This can be particularly useful if you\[cq]re cross\-compiling some crates, and don\[cq]t want to specify your host\[cq]s machine as a target (for instance, an \fBxtask\fR in a shared project that may be worked on by many hosts).
+\h'-04'\(bu\h'+03'\fB"host\-tuple"\fR, which will internally be substituted by the host\[cq]s target. This can be particularly useful if you\[cq]re cross\-compiling some crates, and don\[cq]t want to specify your host\[cq]s machine as a target (for instance, an \fBxtask\fR in a shared project that may be worked on by many hosts).
 .RE
 .sp
 .RS 4
diff --git a/src/etc/man/cargo-rustdoc.1 b/src/etc/man/cargo-rustdoc.1
index 77f9bc4..b033294 100644
--- a/src/etc/man/cargo-rustdoc.1
+++ b/src/etc/man/cargo-rustdoc.1
@@ -164,7 +164,7 @@
 .RE
 .sp
 .RS 4
-\h'-04'\(bu\h'+03'\fB"host"\fR, which will internally be substituted by the host\[cq]s target. This can be particularly useful if you\[cq]re cross\-compiling some crates, and don\[cq]t want to specify your host\[cq]s machine as a target (for instance, an \fBxtask\fR in a shared project that may be worked on by many hosts).
+\h'-04'\(bu\h'+03'\fB"host\-tuple"\fR, which will internally be substituted by the host\[cq]s target. This can be particularly useful if you\[cq]re cross\-compiling some crates, and don\[cq]t want to specify your host\[cq]s machine as a target (for instance, an \fBxtask\fR in a shared project that may be worked on by many hosts).
 .RE
 .sp
 .RS 4
diff --git a/src/etc/man/cargo-test.1 b/src/etc/man/cargo-test.1
index 83e3c09..22e22e5 100644
--- a/src/etc/man/cargo-test.1
+++ b/src/etc/man/cargo-test.1
@@ -297,7 +297,7 @@
 .RE
 .sp
 .RS 4
-\h'-04'\(bu\h'+03'\fB"host"\fR, which will internally be substituted by the host\[cq]s target. This can be particularly useful if you\[cq]re cross\-compiling some crates, and don\[cq]t want to specify your host\[cq]s machine as a target (for instance, an \fBxtask\fR in a shared project that may be worked on by many hosts).
+\h'-04'\(bu\h'+03'\fB"host\-tuple"\fR, which will internally be substituted by the host\[cq]s target. This can be particularly useful if you\[cq]re cross\-compiling some crates, and don\[cq]t want to specify your host\[cq]s machine as a target (for instance, an \fBxtask\fR in a shared project that may be worked on by many hosts).
 .RE
 .sp
 .RS 4
diff --git a/tests/build-std/main.rs b/tests/build-std/main.rs
index 2958b0a..b4ae66a 100644
--- a/tests/build-std/main.rs
+++ b/tests/build-std/main.rs
@@ -396,7 +396,9 @@
 }
 
 #[cargo_test(build_std_real)]
-fn test_panic_abort() {
+fn default_features_still_included_with_extra_build_std_features() {
+    // This is a regression test to ensure when adding extra `build-std-features`,
+    // the default feature set is still respected and included.
     // See rust-lang/cargo#14935
     let p = project()
         .file(
@@ -413,7 +415,7 @@
     p.cargo("check")
         .build_std_arg("std,panic_abort")
         .env("RUSTFLAGS", "-C panic=abort")
-        .arg("-Zbuild-std-features=panic_immediate_abort")
+        .arg("-Zbuild-std-features=optimize_for_size")
         .run();
 }
 
diff --git a/tests/testsuite/bad_config.rs b/tests/testsuite/bad_config.rs
index 6ecf107..d8eec97 100644
--- a/tests/testsuite/bad_config.rs
+++ b/tests/testsuite/bad_config.rs
@@ -47,10 +47,7 @@
   failed to load TOML configuration from `[ROOT]/foo/.cargo/config.toml`
 
 Caused by:
-  failed to parse key `http`
-
-Caused by:
-  failed to parse key `proxy`
+  failed to parse config at `http.proxy`
 
 Caused by:
   found TOML configuration value of unknown type `float`
diff --git a/tests/testsuite/build_dir.rs b/tests/testsuite/build_dir.rs
index d3b8941..6af2799 100644
--- a/tests/testsuite/build_dir.rs
+++ b/tests/testsuite/build_dir.rs
@@ -6,15 +6,13 @@
 //! file verify the files saved to disk are in the correct locations according to the `build-dir`
 //! configuration.
 //!
-//! Tests check if directories match some "layout" by using [`assert_build_dir_layout`] and
-//! [`assert_artifact_dir_layout`].
+//! Tests check if directories match some "layout" by using [`CargoPathExt::assert_file_layout`]
 
 use std::path::PathBuf;
 
 use crate::prelude::*;
 use cargo_test_support::registry::RegistryBuilder;
-use cargo_test_support::{Project, prelude::*};
-use cargo_test_support::{paths, project, str};
+use cargo_test_support::{paths, prelude::*, project, str};
 use std::env::consts::{DLL_PREFIX, DLL_SUFFIX, EXE_SUFFIX};
 
 #[cargo_test]
@@ -33,20 +31,30 @@
 
     p.cargo("build").enable_mac_dsym().run();
 
-    assert_build_dir_layout(p.root().join("build-dir"), "debug");
-    assert_artifact_dir_layout(p.root().join("target-dir"), "debug");
-    assert_exists_patterns_with_base_dir(
-        &p.root(),
-        &[
-            // Check the pre-uplifted binary in the build-dir
-            &format!("build-dir/debug/deps/foo*{EXE_SUFFIX}"),
-            "build-dir/debug/deps/foo*.d",
-            // Verify the binary was copied to the target-dir
-            &format!("target-dir/debug/foo{EXE_SUFFIX}"),
-            "target-dir/debug/foo.d",
-        ],
-    );
     assert_not_exists(&p.root().join("target"));
+
+    p.root().join("build-dir").assert_build_dir_layout(str![[r#"
+[ROOT]/foo/build-dir/.rustc_info.json
+[ROOT]/foo/build-dir/CACHEDIR.TAG
+[ROOT]/foo/build-dir/debug/.cargo-lock
+[ROOT]/foo/build-dir/debug/.fingerprint/foo-[HASH]/bin-foo
+[ROOT]/foo/build-dir/debug/.fingerprint/foo-[HASH]/bin-foo.json
+[ROOT]/foo/build-dir/debug/.fingerprint/foo-[HASH]/dep-bin-foo
+[ROOT]/foo/build-dir/debug/.fingerprint/foo-[HASH]/invoked.timestamp
+[ROOT]/foo/build-dir/debug/deps/foo[..][EXE]
+[ROOT]/foo/build-dir/debug/deps/foo[..].d
+
+"#]]);
+
+    p.root()
+        .join("target-dir")
+        .assert_build_dir_layout(str![[r#"
+[ROOT]/foo/target-dir/CACHEDIR.TAG
+[ROOT]/foo/target-dir/debug/.cargo-lock
+[ROOT]/foo/target-dir/debug/foo[EXE]
+[ROOT]/foo/target-dir/debug/foo.d
+
+"#]]);
 }
 
 #[cargo_test]
@@ -65,8 +73,6 @@
 
     p.cargo("build --release").enable_mac_dsym().run();
 
-    assert_build_dir_layout(p.root().join("build-dir"), "release");
-    assert_exists(&p.root().join(format!("target-dir/release/foo{EXE_SUFFIX}")));
     assert_exists_patterns_with_base_dir(
         &p.root(),
         &[
@@ -78,6 +84,28 @@
             "target-dir/release/foo.d",
         ],
     );
+    p.root().join("build-dir").assert_build_dir_layout(str![[r#"
+[ROOT]/foo/build-dir/.rustc_info.json
+[ROOT]/foo/build-dir/CACHEDIR.TAG
+[ROOT]/foo/build-dir/release/.cargo-lock
+[ROOT]/foo/build-dir/release/.fingerprint/foo-[HASH]/bin-foo
+[ROOT]/foo/build-dir/release/.fingerprint/foo-[HASH]/bin-foo.json
+[ROOT]/foo/build-dir/release/.fingerprint/foo-[HASH]/dep-bin-foo
+[ROOT]/foo/build-dir/release/.fingerprint/foo-[HASH]/invoked.timestamp
+[ROOT]/foo/build-dir/release/deps/foo[..][EXE]
+[ROOT]/foo/build-dir/release/deps/foo[..].d
+
+"#]]);
+
+    p.root()
+        .join("target-dir")
+        .assert_build_dir_layout(str![[r#"
+[ROOT]/foo/target-dir/CACHEDIR.TAG
+[ROOT]/foo/target-dir/release/.cargo-lock
+[ROOT]/foo/target-dir/release/foo[EXE]
+[ROOT]/foo/target-dir/release/foo.d
+
+"#]]);
 }
 
 #[cargo_test]
@@ -146,8 +174,6 @@
 
         p.cargo("build").enable_mac_dsym().run();
 
-        assert_build_dir_layout(p.root().join("build-dir"), "debug");
-
         // Verify lib artifacts were copied into the artifact dir
         assert_exists_patterns_with_base_dir(&p.root().join("target-dir/debug"), &expected_files);
     }
@@ -161,8 +187,20 @@
 
     p.cargo("build").enable_mac_dsym().run();
 
-    assert_build_dir_layout(p.root().join("target"), "debug");
-    assert_exists(&p.root().join(format!("target/debug/foo{EXE_SUFFIX}")));
+    p.root().join("target").assert_build_dir_layout(str![[r#"
+[ROOT]/foo/target/.rustc_info.json
+[ROOT]/foo/target/CACHEDIR.TAG
+[ROOT]/foo/target/debug/.cargo-lock
+[ROOT]/foo/target/debug/.fingerprint/foo-[HASH]/bin-foo
+[ROOT]/foo/target/debug/.fingerprint/foo-[HASH]/bin-foo.json
+[ROOT]/foo/target/debug/.fingerprint/foo-[HASH]/dep-bin-foo
+[ROOT]/foo/target/debug/.fingerprint/foo-[HASH]/invoked.timestamp
+[ROOT]/foo/target/debug/deps/foo[..][EXE]
+[ROOT]/foo/target/debug/deps/foo[..].d
+[ROOT]/foo/target/debug/foo[EXE]
+[ROOT]/foo/target/debug/foo.d
+
+"#]]);
 }
 
 #[cargo_test]
@@ -176,8 +214,18 @@
         .enable_mac_dsym()
         .run();
 
-    assert_build_dir_layout(p.root().join("build-dir"), "debug");
-    assert_exists(&p.root().join(format!("target/debug/foo{EXE_SUFFIX}")));
+    p.root().join("build-dir").assert_build_dir_layout(str![[r#"
+[ROOT]/foo/build-dir/.rustc_info.json
+[ROOT]/foo/build-dir/CACHEDIR.TAG
+[ROOT]/foo/build-dir/debug/.cargo-lock
+[ROOT]/foo/build-dir/debug/.fingerprint/foo-[HASH]/bin-foo
+[ROOT]/foo/build-dir/debug/.fingerprint/foo-[HASH]/bin-foo.json
+[ROOT]/foo/build-dir/debug/.fingerprint/foo-[HASH]/dep-bin-foo
+[ROOT]/foo/build-dir/debug/.fingerprint/foo-[HASH]/invoked.timestamp
+[ROOT]/foo/build-dir/debug/deps/foo[..][EXE]
+[ROOT]/foo/build-dir/debug/deps/foo[..].d
+
+"#]]);
 }
 
 #[cargo_test]
@@ -208,14 +256,32 @@
 
     p.cargo("build").enable_mac_dsym().run();
 
-    assert_build_dir_layout(p.root().join("build-dir"), "debug");
-    assert_exists_patterns_with_base_dir(
-        &p.root(),
-        &[
-            &format!("build-dir/debug/build/foo-*/build-script-build{EXE_SUFFIX}"),
-            "build-dir/debug/build/foo-*/out/foo.txt", // Verify OUT_DIR
-        ],
-    );
+    p.root().join("build-dir").assert_build_dir_layout(str![[r#"
+[ROOT]/foo/build-dir/CACHEDIR.TAG
+[ROOT]/foo/build-dir/debug/.cargo-lock
+[ROOT]/foo/build-dir/debug/deps/foo[..].d
+[ROOT]/foo/build-dir/debug/deps/foo[..][EXE]
+[ROOT]/foo/build-dir/debug/.fingerprint/foo-[HASH]/invoked.timestamp
+[ROOT]/foo/build-dir/debug/.fingerprint/foo-[HASH]/dep-bin-foo
+[ROOT]/foo/build-dir/debug/.fingerprint/foo-[HASH]/bin-foo
+[ROOT]/foo/build-dir/debug/.fingerprint/foo-[HASH]/bin-foo.json
+[ROOT]/foo/build-dir/.rustc_info.json
+[ROOT]/foo/build-dir/debug/.fingerprint/foo-[HASH]/run-build-script-build-script-build
+[ROOT]/foo/build-dir/debug/.fingerprint/foo-[HASH]/run-build-script-build-script-build.json
+[ROOT]/foo/build-dir/debug/.fingerprint/foo-[HASH]/invoked.timestamp
+[ROOT]/foo/build-dir/debug/.fingerprint/foo-[HASH]/dep-build-script-build-script-build
+[ROOT]/foo/build-dir/debug/.fingerprint/foo-[HASH]/build-script-build-script-build
+[ROOT]/foo/build-dir/debug/.fingerprint/foo-[HASH]/build-script-build-script-build.json
+[ROOT]/foo/build-dir/debug/build/foo-[HASH]/build_script_build[..].d
+[ROOT]/foo/build-dir/debug/build/foo-[HASH]/build_script_build[..][EXE]
+[ROOT]/foo/build-dir/debug/build/foo-[HASH]/build-script-build[EXE]
+[ROOT]/foo/build-dir/debug/build/foo-[HASH]/out/foo.txt
+[ROOT]/foo/build-dir/debug/build/foo-[HASH]/invoked.timestamp
+[ROOT]/foo/build-dir/debug/build/foo-[HASH]/output
+[ROOT]/foo/build-dir/debug/build/foo-[HASH]/stderr
+[ROOT]/foo/build-dir/debug/build/foo-[HASH]/root-output
+
+"#]]);
 }
 
 #[cargo_test]
@@ -247,8 +313,40 @@
 
     p.cargo("test").enable_mac_dsym().run();
 
-    assert_build_dir_layout(p.root().join("build-dir"), "debug");
-    assert_exists(&p.root().join(format!("build-dir/tmp/foo.txt")));
+    p.root().join("build-dir").assert_build_dir_layout(str![[r#"
+[ROOT]/foo/build-dir/CACHEDIR.TAG
+[ROOT]/foo/build-dir/debug/.cargo-lock
+[ROOT]/foo/build-dir/debug/deps/foo-[HASH].d
+[ROOT]/foo/build-dir/debug/deps/foo-[HASH].d
+[ROOT]/foo/build-dir/debug/deps/foo[..].d
+[ROOT]/foo/build-dir/debug/deps/foo-[HASH][EXE]
+[ROOT]/foo/build-dir/debug/deps/foo-[HASH][EXE]
+[ROOT]/foo/build-dir/debug/deps/foo[..][EXE]
+[ROOT]/foo/build-dir/debug/.fingerprint/foo-[HASH]/invoked.timestamp
+[ROOT]/foo/build-dir/debug/.fingerprint/foo-[HASH]/dep-test-bin-foo
+[ROOT]/foo/build-dir/debug/.fingerprint/foo-[HASH]/test-bin-foo
+[ROOT]/foo/build-dir/debug/.fingerprint/foo-[HASH]/test-bin-foo.json
+[ROOT]/foo/build-dir/debug/.fingerprint/foo-[HASH]/invoked.timestamp
+[ROOT]/foo/build-dir/debug/.fingerprint/foo-[HASH]/dep-test-integration-test-foo
+[ROOT]/foo/build-dir/debug/.fingerprint/foo-[HASH]/test-integration-test-foo
+[ROOT]/foo/build-dir/debug/.fingerprint/foo-[HASH]/test-integration-test-foo.json
+[ROOT]/foo/build-dir/debug/.fingerprint/foo-[HASH]/invoked.timestamp
+[ROOT]/foo/build-dir/debug/.fingerprint/foo-[HASH]/dep-bin-foo
+[ROOT]/foo/build-dir/debug/.fingerprint/foo-[HASH]/bin-foo
+[ROOT]/foo/build-dir/debug/.fingerprint/foo-[HASH]/bin-foo.json
+[ROOT]/foo/build-dir/tmp/foo.txt
+[ROOT]/foo/build-dir/.rustc_info.json
+
+"#]]);
+
+    p.root()
+        .join("target-dir")
+        .assert_build_dir_layout(str![[r#"
+[ROOT]/foo/target-dir/CACHEDIR.TAG
+[ROOT]/foo/target-dir/debug/.cargo-lock
+[ROOT]/foo/target-dir/debug/foo[EXE]
+
+"#]]);
 }
 
 #[cargo_test]
@@ -268,18 +366,28 @@
 
     p.cargo("build --examples").enable_mac_dsym().run();
 
-    assert_build_dir_layout(p.root().join("build-dir"), "debug");
-    assert_exists_patterns_with_base_dir(
-        &p.root(),
-        &[
-            // uplifted (target-dir)
-            &format!("target-dir/debug/examples/foo{EXE_SUFFIX}"),
-            "target-dir/debug/examples/foo.d",
-            // pre-uplifted (build-dir)
-            &format!("build-dir/debug/examples/foo*{EXE_SUFFIX}"),
-            "build-dir/debug/examples/foo*.d",
-        ],
-    );
+    p.root().join("build-dir").assert_build_dir_layout(str![[r#"
+[ROOT]/foo/build-dir/.rustc_info.json
+[ROOT]/foo/build-dir/CACHEDIR.TAG
+[ROOT]/foo/build-dir/debug/.cargo-lock
+[ROOT]/foo/build-dir/debug/.fingerprint/foo-[HASH]/dep-example-foo
+[ROOT]/foo/build-dir/debug/.fingerprint/foo-[HASH]/example-foo
+[ROOT]/foo/build-dir/debug/.fingerprint/foo-[HASH]/example-foo.json
+[ROOT]/foo/build-dir/debug/.fingerprint/foo-[HASH]/invoked.timestamp
+[ROOT]/foo/build-dir/debug/examples/foo[..][EXE]
+[ROOT]/foo/build-dir/debug/examples/foo[..].d
+
+"#]]);
+
+    p.root()
+        .join("target-dir")
+        .assert_build_dir_layout(str![[r#"
+[ROOT]/foo/target-dir/CACHEDIR.TAG
+[ROOT]/foo/target-dir/debug/.cargo-lock
+[ROOT]/foo/target-dir/debug/examples/foo[EXE]
+[ROOT]/foo/target-dir/debug/examples/foo.d
+
+"#]]);
 }
 
 #[cargo_test]
@@ -299,14 +407,33 @@
 
     p.cargo("build --bench=foo").enable_mac_dsym().run();
 
-    assert_build_dir_layout(p.root().join("build-dir"), "debug");
-    assert_exists_patterns_with_base_dir(
-        &p.root(),
-        &[
-            &format!("build-dir/debug/deps/foo*{EXE_SUFFIX}"),
-            "build-dir/debug/deps/foo*.d",
-        ],
-    );
+    p.root().join("build-dir").assert_build_dir_layout(str![[r#"
+[ROOT]/foo/build-dir/CACHEDIR.TAG
+[ROOT]/foo/build-dir/debug/.cargo-lock
+[ROOT]/foo/build-dir/debug/deps/foo-[HASH].d
+[ROOT]/foo/build-dir/debug/deps/foo[..].d
+[ROOT]/foo/build-dir/debug/deps/foo-[HASH][EXE]
+[ROOT]/foo/build-dir/debug/deps/foo[..][EXE]
+[ROOT]/foo/build-dir/debug/.fingerprint/foo-[HASH]/invoked.timestamp
+[ROOT]/foo/build-dir/debug/.fingerprint/foo-[HASH]/dep-test-bench-foo
+[ROOT]/foo/build-dir/debug/.fingerprint/foo-[HASH]/test-bench-foo
+[ROOT]/foo/build-dir/debug/.fingerprint/foo-[HASH]/test-bench-foo.json
+[ROOT]/foo/build-dir/debug/.fingerprint/foo-[HASH]/invoked.timestamp
+[ROOT]/foo/build-dir/debug/.fingerprint/foo-[HASH]/dep-bin-foo
+[ROOT]/foo/build-dir/debug/.fingerprint/foo-[HASH]/bin-foo
+[ROOT]/foo/build-dir/debug/.fingerprint/foo-[HASH]/bin-foo.json
+[ROOT]/foo/build-dir/.rustc_info.json
+
+"#]]);
+
+    p.root()
+        .join("target-dir")
+        .assert_build_dir_layout(str![[r#"
+[ROOT]/foo/target-dir/CACHEDIR.TAG
+[ROOT]/foo/target-dir/debug/.cargo-lock
+[ROOT]/foo/target-dir/debug/foo[EXE]
+
+"#]]);
 }
 
 #[cargo_test]
@@ -347,17 +474,35 @@
 
     p.cargo("package").enable_mac_dsym().run();
 
-    assert_build_dir_layout(p.root().join("build-dir"), "debug");
-
     let package_artifact_dir = p.root().join("target-dir/package");
     assert_exists(&package_artifact_dir);
     assert_exists(&package_artifact_dir.join("foo-0.0.1.crate"));
     assert!(package_artifact_dir.join("foo-0.0.1.crate").is_file());
+    p.root().join("build-dir").assert_build_dir_layout(str![[r#"
+[ROOT]/foo/build-dir/.rustc_info.json
+[ROOT]/foo/build-dir/debug/.cargo-lock
+[ROOT]/foo/build-dir/debug/.fingerprint/foo-[HASH]/bin-foo
+[ROOT]/foo/build-dir/debug/.fingerprint/foo-[HASH]/bin-foo.json
+[ROOT]/foo/build-dir/debug/.fingerprint/foo-[HASH]/dep-bin-foo
+[ROOT]/foo/build-dir/debug/.fingerprint/foo-[HASH]/invoked.timestamp
+[ROOT]/foo/build-dir/debug/deps/foo[..][EXE]
+[ROOT]/foo/build-dir/debug/deps/foo[..].d
+[ROOT]/foo/build-dir/debug/foo[EXE]
+[ROOT]/foo/build-dir/debug/foo.d
+[ROOT]/foo/build-dir/package/foo-0.0.1/Cargo.lock
+[ROOT]/foo/build-dir/package/foo-0.0.1/Cargo.toml
+[ROOT]/foo/build-dir/package/foo-0.0.1/Cargo.toml.orig
+[ROOT]/foo/build-dir/package/foo-0.0.1/src/main.rs
+[ROOT]/foo/build-dir/package/foo-0.0.1.crate
 
-    let package_build_dir = p.root().join("build-dir/package");
-    assert_exists(&package_build_dir);
-    assert_exists(&package_build_dir.join("foo-0.0.1"));
-    assert!(package_build_dir.join("foo-0.0.1").is_dir());
+"#]]);
+
+    p.root()
+        .join("target-dir")
+        .assert_build_dir_layout(str![[r#"
+[ROOT]/foo/target-dir/package/foo-0.0.1.crate
+
+"#]]);
 }
 
 #[cargo_test]
@@ -381,8 +526,6 @@
         .enable_mac_dsym()
         .run();
 
-    assert_build_dir_layout(p.root().join("build-dir"), "debug");
-
     let package_artifact_dir = p.root().join("target-dir/package");
     assert!(!package_artifact_dir.exists());
 
@@ -408,7 +551,28 @@
 
     p.cargo("build").enable_mac_dsym().run();
 
-    assert_build_dir_layout(p.root().join("build-dir"), "debug");
+    p.root().join("build-dir").assert_build_dir_layout(str![[r#"
+[ROOT]/foo/build-dir/.rustc_info.json
+[ROOT]/foo/build-dir/CACHEDIR.TAG
+[ROOT]/foo/build-dir/debug/.cargo-lock
+[ROOT]/foo/build-dir/debug/.fingerprint/foo-[HASH]/bin-foo
+[ROOT]/foo/build-dir/debug/.fingerprint/foo-[HASH]/bin-foo.json
+[ROOT]/foo/build-dir/debug/.fingerprint/foo-[HASH]/dep-bin-foo
+[ROOT]/foo/build-dir/debug/.fingerprint/foo-[HASH]/invoked.timestamp
+[ROOT]/foo/build-dir/debug/deps/foo[..][EXE]
+[ROOT]/foo/build-dir/debug/deps/foo[..].d
+
+"#]]);
+
+    p.root()
+        .join("target-dir")
+        .assert_build_dir_layout(str![[r#"
+[ROOT]/foo/target-dir/CACHEDIR.TAG
+[ROOT]/foo/target-dir/debug/.cargo-lock
+[ROOT]/foo/target-dir/debug/foo[EXE]
+[ROOT]/foo/target-dir/debug/foo.d
+
+"#]]);
 
     p.cargo("clean").enable_mac_dsym().run();
 
@@ -526,11 +690,30 @@
 
     p.cargo("build").enable_mac_dsym().run();
 
-    assert_build_dir_layout(p.root().join("build-dir"), "debug");
-    assert_artifact_dir_layout(p.root().join("target-dir"), "debug");
-
     // Verify the binary was uplifted to the target-dir
     assert_exists(&p.root().join(&format!("target-dir/debug/foo{EXE_SUFFIX}")));
+    p.root().join("build-dir").assert_build_dir_layout(str![[r#"
+[ROOT]/foo/build-dir/.rustc_info.json
+[ROOT]/foo/build-dir/CACHEDIR.TAG
+[ROOT]/foo/build-dir/debug/.cargo-lock
+[ROOT]/foo/build-dir/debug/.fingerprint/foo-[HASH]/bin-foo
+[ROOT]/foo/build-dir/debug/.fingerprint/foo-[HASH]/bin-foo.json
+[ROOT]/foo/build-dir/debug/.fingerprint/foo-[HASH]/dep-bin-foo
+[ROOT]/foo/build-dir/debug/.fingerprint/foo-[HASH]/invoked.timestamp
+[ROOT]/foo/build-dir/debug/deps/foo[..][EXE]
+[ROOT]/foo/build-dir/debug/deps/foo[..].d
+
+"#]]);
+
+    p.root()
+        .join("target-dir")
+        .assert_build_dir_layout(str![[r#"
+[ROOT]/foo/target-dir/CACHEDIR.TAG
+[ROOT]/foo/target-dir/debug/.cargo-lock
+[ROOT]/foo/target-dir/debug/foo[EXE]
+[ROOT]/foo/target-dir/debug/foo.d
+
+"#]]);
 }
 
 #[cargo_test]
@@ -549,11 +732,32 @@
 
     p.cargo("build").enable_mac_dsym().run();
 
-    assert_build_dir_layout(paths::home().join(".cargo/build-dir"), "debug");
-    assert_artifact_dir_layout(p.root().join("target-dir"), "debug");
-
     // Verify the binary was uplifted to the target-dir
     assert_exists(&p.root().join(&format!("target-dir/debug/foo{EXE_SUFFIX}")));
+    paths::cargo_home()
+        .join("build-dir")
+        .assert_build_dir_layout(str![[r#"
+[ROOT]/home/.cargo/build-dir/.rustc_info.json
+[ROOT]/home/.cargo/build-dir/CACHEDIR.TAG
+[ROOT]/home/.cargo/build-dir/debug/.cargo-lock
+[ROOT]/home/.cargo/build-dir/debug/.fingerprint/foo-[HASH]/bin-foo
+[ROOT]/home/.cargo/build-dir/debug/.fingerprint/foo-[HASH]/bin-foo.json
+[ROOT]/home/.cargo/build-dir/debug/.fingerprint/foo-[HASH]/dep-bin-foo
+[ROOT]/home/.cargo/build-dir/debug/.fingerprint/foo-[HASH]/invoked.timestamp
+[ROOT]/home/.cargo/build-dir/debug/deps/foo[..][EXE]
+[ROOT]/home/.cargo/build-dir/debug/deps/foo[..].d
+
+"#]]);
+
+    p.root()
+        .join("target-dir")
+        .assert_build_dir_layout(str![[r#"
+[ROOT]/foo/target-dir/CACHEDIR.TAG
+[ROOT]/foo/target-dir/debug/.cargo-lock
+[ROOT]/foo/target-dir/debug/foo[EXE]
+[ROOT]/foo/target-dir/debug/foo.d
+
+"#]]);
 }
 
 #[cargo_test]
@@ -587,11 +791,31 @@
     let hash_dir = parse_workspace_manifest_path_hash(&foo_dir);
 
     let build_dir = hash_dir.as_path().join("build-dir");
-    assert_build_dir_layout(build_dir, "debug");
-    assert_artifact_dir_layout(p.root().join("target-dir"), "debug");
 
     // Verify the binary was uplifted to the target-dir
     assert_exists(&p.root().join(&format!("target-dir/debug/foo{EXE_SUFFIX}")));
+    build_dir.assert_build_dir_layout(str![[r#"
+[ROOT]/foo/foo/[HASH]/build-dir/.rustc_info.json
+[ROOT]/foo/foo/[HASH]/build-dir/CACHEDIR.TAG
+[ROOT]/foo/foo/[HASH]/build-dir/debug/.cargo-lock
+[ROOT]/foo/foo/[HASH]/build-dir/debug/.fingerprint/foo-[HASH]/bin-foo
+[ROOT]/foo/foo/[HASH]/build-dir/debug/.fingerprint/foo-[HASH]/bin-foo.json
+[ROOT]/foo/foo/[HASH]/build-dir/debug/.fingerprint/foo-[HASH]/dep-bin-foo
+[ROOT]/foo/foo/[HASH]/build-dir/debug/.fingerprint/foo-[HASH]/invoked.timestamp
+[ROOT]/foo/foo/[HASH]/build-dir/debug/deps/foo[..][EXE]
+[ROOT]/foo/foo/[HASH]/build-dir/debug/deps/foo[..].d
+
+"#]]);
+
+    p.root()
+        .join("target-dir")
+        .assert_build_dir_layout(str![[r#"
+[ROOT]/foo/target-dir/CACHEDIR.TAG
+[ROOT]/foo/target-dir/debug/.cargo-lock
+[ROOT]/foo/target-dir/debug/foo[EXE]
+[ROOT]/foo/target-dir/debug/foo.d
+
+"#]]);
 }
 
 /// Verify that the {workspace-path-hash} does not changes if cargo is run from inside of
@@ -633,7 +857,25 @@
     let foo_dir = p.root().join("foo");
     assert_exists(&foo_dir);
     let original_hash_dir = parse_workspace_manifest_path_hash(&foo_dir);
-    verify_layouts(&p, &original_hash_dir);
+
+    original_hash_dir.assert_build_dir_layout(str![[r#"
+[ROOT]/foo/foo/[HASH]/build-dir/.rustc_info.json
+[ROOT]/foo/foo/[HASH]/build-dir/CACHEDIR.TAG
+[ROOT]/foo/foo/[HASH]/build-dir/debug/.cargo-lock
+[ROOT]/foo/foo/[HASH]/build-dir/debug/.fingerprint/foo-[HASH]/dep-lib-foo
+[ROOT]/foo/foo/[HASH]/build-dir/debug/.fingerprint/foo-[HASH]/invoked.timestamp
+[ROOT]/foo/foo/[HASH]/build-dir/debug/.fingerprint/foo-[HASH]/lib-foo
+[ROOT]/foo/foo/[HASH]/build-dir/debug/.fingerprint/foo-[HASH]/lib-foo.json
+[ROOT]/foo/foo/[HASH]/build-dir/debug/deps/foo-[HASH].d
+[ROOT]/foo/foo/[HASH]/build-dir/debug/deps/libfoo-[HASH].rmeta
+
+"#]]);
+
+    p.root().join("target").assert_build_dir_layout(str![[r#"
+[ROOT]/foo/target/CACHEDIR.TAG
+[ROOT]/foo/target/debug/.cargo-lock
+
+"#]]);
 
     // Create a symlink of the project root.
     let mut symlinked_dir = p.root().clone();
@@ -650,16 +892,28 @@
     // Parse and verify the hash created from the symlinked dir
     assert_exists(&foo_dir);
     let symlink_hash_dir = parse_workspace_manifest_path_hash(&foo_dir);
-    verify_layouts(&p, &symlink_hash_dir);
+
+    symlink_hash_dir.assert_build_dir_layout(str![[r#"
+[ROOT]/foo/foo/[HASH]/build-dir/.rustc_info.json
+[ROOT]/foo/foo/[HASH]/build-dir/CACHEDIR.TAG
+[ROOT]/foo/foo/[HASH]/build-dir/debug/.cargo-lock
+[ROOT]/foo/foo/[HASH]/build-dir/debug/.fingerprint/foo-[HASH]/dep-lib-foo
+[ROOT]/foo/foo/[HASH]/build-dir/debug/.fingerprint/foo-[HASH]/invoked.timestamp
+[ROOT]/foo/foo/[HASH]/build-dir/debug/.fingerprint/foo-[HASH]/lib-foo
+[ROOT]/foo/foo/[HASH]/build-dir/debug/.fingerprint/foo-[HASH]/lib-foo.json
+[ROOT]/foo/foo/[HASH]/build-dir/debug/deps/foo-[HASH].d
+[ROOT]/foo/foo/[HASH]/build-dir/debug/deps/libfoo-[HASH].rmeta
+
+"#]]);
+
+    p.root().join("target").assert_build_dir_layout(str![[r#"
+[ROOT]/foo/target/CACHEDIR.TAG
+[ROOT]/foo/target/debug/.cargo-lock
+
+"#]]);
 
     // Verify the hash dir created from the symlinked and non-symlinked dirs are the same.
     assert_eq!(original_hash_dir, symlink_hash_dir);
-
-    fn verify_layouts(p: &Project, build_dir_parent: &PathBuf) {
-        let build_dir = build_dir_parent.as_path().join("build-dir");
-        assert_build_dir_layout(build_dir, "debug");
-        assert_artifact_dir_layout(p.root().join("target"), "debug");
-    }
 }
 
 #[cargo_test]
@@ -750,71 +1004,6 @@
 }
 
 #[track_caller]
-fn assert_build_dir_layout(path: PathBuf, profile: &str) {
-    assert_dir_layout(path, profile, true);
-}
-
-#[allow(dead_code)]
-#[track_caller]
-fn assert_artifact_dir_layout(path: PathBuf, profile: &str) {
-    assert_dir_layout(path, profile, false);
-}
-
-#[track_caller]
-fn assert_dir_layout(path: PathBuf, profile: &str, is_build_dir: bool) {
-    println!("checking if {path:?} is a build directory ({is_build_dir})");
-    // For things that are in both `target` and the build directory we only check if they are
-    // present if `is_build_dir` is true.
-    if is_build_dir {
-        assert_eq!(
-            is_build_dir,
-            path.join(profile).is_dir(),
-            "Expected {:?} to exist and be a directory",
-            path.join(profile)
-        );
-    }
-
-    let error_message = |dir: &str| {
-        if is_build_dir {
-            format!("`{dir}` dir was expected but not found")
-        } else {
-            format!("`{dir}` dir was not expected but was found")
-        }
-    };
-
-    if is_build_dir {
-        assert_exists(&path.join(".rustc_info.json"));
-    } else {
-        assert_not_exists(&path.join(".rustc_info.json"));
-    }
-
-    assert_eq!(
-        is_build_dir,
-        path.join(profile).join("deps").is_dir(),
-        "{}",
-        error_message("deps")
-    );
-    assert_eq!(
-        is_build_dir,
-        path.join(profile).join("build").is_dir(),
-        "{}",
-        error_message("build")
-    );
-    assert_eq!(
-        is_build_dir,
-        path.join(profile).join("incremental").is_dir(),
-        "{}",
-        error_message("incremental")
-    );
-    assert_eq!(
-        is_build_dir,
-        path.join(profile).join(".fingerprint").is_dir(),
-        "{}",
-        error_message(".fingerprint")
-    );
-}
-
-#[track_caller]
 fn assert_exists(path: &PathBuf) {
     assert!(
         path.exists(),
diff --git a/tests/testsuite/cargo_alias_config.rs b/tests/testsuite/cargo_alias_config.rs
index 5fa73f6..044a5a2 100644
--- a/tests/testsuite/cargo_alias_config.rs
+++ b/tests/testsuite/cargo_alias_config.rs
@@ -87,13 +87,10 @@
   failed to load TOML configuration from `[ROOT]/foo/.cargo/config.toml`
 
 Caused by:
-  failed to parse key `alias`
+  failed to parse config at `alias.b-cargo-test[0]`
 
 Caused by:
-  failed to parse key `b-cargo-test`
-
-Caused by:
-  expected string but found integer in list
+  expected string but found integer at index 0
 
 "#]])
         .run();
diff --git a/tests/testsuite/config.rs b/tests/testsuite/config.rs
index 81506bb..ff8bad6 100644
--- a/tests/testsuite/config.rs
+++ b/tests/testsuite/config.rs
@@ -1363,10 +1363,10 @@
   failed to load TOML configuration from `[ROOT]/.cargo/config.toml`
 
 Caused by:
-  failed to parse key `foo`
+  failed to parse config at `foo[0]`
 
 Caused by:
-  expected string but found integer in list
+  expected string but found integer at index 0
 "#]],
     );
 }
diff --git a/tests/testsuite/config_cli.rs b/tests/testsuite/config_cli.rs
index e7e36f6..e95d8ae 100644
--- a/tests/testsuite/config_cli.rs
+++ b/tests/testsuite/config_cli.rs
@@ -527,7 +527,7 @@
 failed to convert --config argument `a=2019-12-01`
 
 Caused by:
-  failed to parse key `a`
+  failed to parse config at `a`
 
 Caused by:
   found TOML configuration value of unknown type `datetime`
diff --git a/tests/testsuite/cross_compile.rs b/tests/testsuite/cross_compile.rs
index e2f9009..40c4648 100644
--- a/tests/testsuite/cross_compile.rs
+++ b/tests/testsuite/cross_compile.rs
@@ -157,7 +157,7 @@
         .file("src/lib.rs", r#""#)
         .build();
 
-    p.cargo("build -v --target host")
+    p.cargo("build -v --target host-tuple")
         .with_stderr_contains("[RUNNING] `rustc [..] --target [HOST_TARGET] [..]`")
         .run();
 }
@@ -174,7 +174,7 @@
             &format!(
                 r#"
                     [build]
-                    target = "host"
+                    target = "host-tuple"
                 "#,
             ),
         )
diff --git a/tests/testsuite/git.rs b/tests/testsuite/git.rs
index c4a0dec..90acbb1 100644
--- a/tests/testsuite/git.rs
+++ b/tests/testsuite/git.rs
@@ -4092,6 +4092,12 @@
         .with_stderr_data(str![[r#"
 [UPDATING] git repository `https://github.com/rust-lang/bitflags.git`
 fatal: remote [ERROR] upload-pack: not our ref 11111b376b93484341c68fbca3ca110ae5cd2790
+[WARNING] spurious network error (3 tries remaining): process didn't exit successfully: `git fetch --no-tags --force --update-head-ok [..]
+fatal: remote [ERROR] upload-pack: not our ref 11111b376b93484341c68fbca3ca110ae5cd2790
+[WARNING] spurious network error (2 tries remaining): process didn't exit successfully: `git fetch --no-tags --force --update-head-ok [..]
+fatal: remote [ERROR] upload-pack: not our ref 11111b376b93484341c68fbca3ca110ae5cd2790
+[WARNING] spurious network error (1 try remaining): process didn't exit successfully: `git fetch --no-tags --force --update-head-ok [..]
+fatal: remote [ERROR] upload-pack: not our ref 11111b376b93484341c68fbca3ca110ae5cd2790
 [ERROR] failed to get `bitflags` as a dependency of package `foo v0.1.0 ([ROOT]/foo)`
 
 Caused by:
diff --git a/tests/testsuite/lints/blanket_hint_mostly_unused.rs b/tests/testsuite/lints/blanket_hint_mostly_unused.rs
new file mode 100644
index 0000000..18e55a8
--- /dev/null
+++ b/tests/testsuite/lints/blanket_hint_mostly_unused.rs
@@ -0,0 +1,167 @@
+use crate::prelude::*;
+use cargo_test_support::project;
+use cargo_test_support::str;
+
+#[cargo_test(nightly, reason = "-Zhint-mostly-unused is unstable")]
+fn named_profile_blanket() {
+    let p = project()
+        .file(
+            "Cargo.toml",
+            r#"
+[package]
+name = "foo"
+version = "0.0.1"
+edition = "2015"
+
+[profile.dev]
+hint-mostly-unused = true
+"#,
+        )
+        .file("src/main.rs", "fn main() {}")
+        .build();
+    p.cargo("check -Zprofile-hint-mostly-unused -v")
+        .masquerade_as_nightly_cargo(&["profile-hint-mostly-unused", "cargo-lints"])
+        .with_stderr_data(str![[r#"
+[WARNING] `hint-mostly-unused` is being blanket applied to all dependencies
+ --> Cargo.toml:7:10
+  |
+7 | [profile.dev]
+  |          ^^^
+8 | hint-mostly-unused = true
+  | -------------------------
+  |
+  = [NOTE] `cargo::blanket_hint_mostly_unused` is set to `warn` by default
+[HELP] scope `hint-mostly-unused` to specific packages with a lot of unused object code
+  |
+7 | [profile.dev.package.<pkg_name>]
+  |             +++++++++++++++++++
+[CHECKING] foo v0.0.1 ([ROOT]/foo)
+[RUNNING] `rustc --crate-name foo [..]`
+[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s
+
+"#]])
+        .run();
+}
+
+#[cargo_test(nightly, reason = "-Zhint-mostly-unused is unstable")]
+fn profile_package_wildcard() {
+    let p = project()
+        .file(
+            "Cargo.toml",
+            r#"
+[package]
+name = "foo"
+version = "0.0.1"
+edition = "2015"
+
+[profile.dev.package."*"]
+hint-mostly-unused = true
+"#,
+        )
+        .file("src/main.rs", "fn main() {}")
+        .build();
+    p.cargo("check -Zprofile-hint-mostly-unused -v")
+        .masquerade_as_nightly_cargo(&["profile-hint-mostly-unused", "cargo-lints"])
+        .with_stderr_data(str![[r#"
+[WARNING] `hint-mostly-unused` is being blanket applied to all dependencies
+ --> Cargo.toml:7:22
+  |
+7 | [profile.dev.package."*"]
+  |                      ^^^
+8 | hint-mostly-unused = true
+  | -------------------------
+  |
+  = [HELP] scope `hint-mostly-unused` to specific packages with a lot of unused object code
+  = [NOTE] `cargo::blanket_hint_mostly_unused` is set to `warn` by default
+[CHECKING] foo v0.0.1 ([ROOT]/foo)
+[RUNNING] `rustc --crate-name foo [..]`
+[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s
+
+"#]])
+        .run();
+}
+
+#[cargo_test(nightly, reason = "-Zhint-mostly-unused is unstable")]
+fn profile_build_override() {
+    let p = project()
+        .file(
+            "Cargo.toml",
+            r#"
+[package]
+name = "foo"
+version = "0.0.1"
+edition = "2015"
+
+[profile.dev.build-override]
+hint-mostly-unused = true
+"#,
+        )
+        .file("src/main.rs", "fn main() {}")
+        .build();
+    p.cargo("check -Zprofile-hint-mostly-unused -v")
+        .masquerade_as_nightly_cargo(&["profile-hint-mostly-unused", "cargo-lints"])
+        .with_stderr_data(str![[r#"
+[WARNING] `hint-mostly-unused` is being blanket applied to all dependencies
+ --> Cargo.toml:7:14
+  |
+7 | [profile.dev.build-override]
+  |              ^^^^^^^^^^^^^^
+8 | hint-mostly-unused = true
+  | -------------------------
+  |
+  = [HELP] scope `hint-mostly-unused` to specific packages with a lot of unused object code
+  = [NOTE] `cargo::blanket_hint_mostly_unused` is set to `warn` by default
+[CHECKING] foo v0.0.1 ([ROOT]/foo)
+[RUNNING] `rustc --crate-name foo [..]`
+[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s
+
+"#]])
+        .run();
+}
+
+#[cargo_test(nightly, reason = "-Zhint-mostly-unused is unstable")]
+fn workspace_profile_package_wildcard() {
+    let p = project()
+        .file(
+            "Cargo.toml",
+            r#"
+[workspace]
+members = ["foo"]
+
+[profile.dev.package."*"]
+hint-mostly-unused = true
+"#,
+        )
+        .file(
+            "foo/Cargo.toml",
+            r#"
+[package]
+name = "foo"
+version = "0.0.1"
+edition = "2015"
+authors = []
+"#,
+        )
+        .file("foo/src/lib.rs", "")
+        .build();
+
+    p.cargo("check -Zprofile-hint-mostly-unused -v")
+        .masquerade_as_nightly_cargo(&["profile-hint-mostly-unused", "cargo-lints"])
+        .with_stderr_data(str![[r#"
+[WARNING] `hint-mostly-unused` is being blanket applied to all dependencies
+ --> Cargo.toml:5:22
+  |
+5 | [profile.dev.package."*"]
+  |                      ^^^
+6 | hint-mostly-unused = true
+  | -------------------------
+  |
+  = [HELP] scope `hint-mostly-unused` to specific packages with a lot of unused object code
+  = [NOTE] `cargo::blanket_hint_mostly_unused` is set to `warn` by default
+[CHECKING] foo v0.0.1 ([ROOT]/foo/foo)
+[RUNNING] `rustc --crate-name foo [..]`
+[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s
+
+"#]])
+        .run();
+}
diff --git a/tests/testsuite/lints/mod.rs b/tests/testsuite/lints/mod.rs
index 908663a..ac92d79 100644
--- a/tests/testsuite/lints/mod.rs
+++ b/tests/testsuite/lints/mod.rs
@@ -3,6 +3,7 @@
 use cargo_test_support::registry::Package;
 use cargo_test_support::str;
 
+mod blanket_hint_mostly_unused;
 mod error;
 mod inherited;
 mod unknown_lints;
diff --git a/tests/testsuite/publish.rs b/tests/testsuite/publish.rs
index 846b068..c3da82a 100644
--- a/tests/testsuite/publish.rs
+++ b/tests/testsuite/publish.rs
@@ -3428,7 +3428,7 @@
 [UPLOADING] dep v0.0.1 ([ROOT]/foo/dep)
 [UPLOADED] dep v0.0.1 to registry `crates-io`
 [NOTE] waiting for dep v0.0.1 to be available at registry `crates-io`.
-2 remaining crates to be published
+      2 remaining crates to be published
 [WARNING] timed out waiting for dep v0.0.1 to be available in registry `crates-io`
 [NOTE] the registry may have a backlog that is delaying making the crate available. The crate should be available soon.
 [ERROR] unable to publish main v0.0.1 and other v0.0.1 due to a timeout while waiting for published dependencies to be available.
@@ -3751,12 +3751,12 @@
 [UPLOADING] level3 v0.0.1 ([ROOT]/foo/level3)
 [UPLOADED] level3 v0.0.1 to registry `crates-io`
 [NOTE] waiting for level3 v0.0.1 to be available at registry `crates-io`.
-2 remaining crates to be published
+      2 remaining crates to be published
 [PUBLISHED] level3 v0.0.1 at registry `crates-io`
 [UPLOADING] level2 v0.0.1 ([ROOT]/foo/level2)
 [UPLOADED] level2 v0.0.1 to registry `crates-io`
 [NOTE] waiting for level2 v0.0.1 to be available at registry `crates-io`.
-1 remaining crate to be published
+      1 remaining crate to be published
 [PUBLISHED] level2 v0.0.1 at registry `crates-io`
 [UPLOADING] level1 v0.0.1 ([ROOT]/foo/level1)
 [UPLOADED] level1 v0.0.1 to registry `crates-io`
@@ -3855,7 +3855,7 @@
 [UPLOADED] b v0.0.1 to registry `crates-io`
 [UPLOADED] a v0.0.1 to registry `crates-io`
 [NOTE] waiting for a v0.0.1 or b v0.0.1 to be available at registry `crates-io`.
-1 remaining crate to be published
+      1 remaining crate to be published
 [PUBLISHED] a v0.0.1 and b v0.0.1 at registry `crates-io`
 [UPLOADING] c v0.0.1 ([ROOT]/foo/c)
 [UPLOADED] c v0.0.1 to registry `crates-io`
diff --git a/tests/testsuite/rust_version.rs b/tests/testsuite/rust_version.rs
index 61f79b2..23363f6 100644
--- a/tests/testsuite/rust_version.rs
+++ b/tests/testsuite/rust_version.rs
@@ -82,7 +82,7 @@
 [ERROR] failed to parse manifest at `[ROOT]/foo/Cargo.toml`
 
 Caused by:
-  rust-version 1.1 is older than first version (1.31.0) required by the specified edition (2018)
+  rust-version 1.1 is imcompatible with the version (1.31.0) required by the specified edition (2018)
 
 "#]])
         .run();
diff --git a/tests/testsuite/tool_paths.rs b/tests/testsuite/tool_paths.rs
index 1321e4d..0849f63 100644
--- a/tests/testsuite/tool_paths.rs
+++ b/tests/testsuite/tool_paths.rs
@@ -342,9 +342,6 @@
     p.cargo("run")
         .env(&key, "nonexistent-runner --foo")
         .with_status(101)
-        // FIXME: Update "Caused by" error message once rust/pull/87704 is merged.
-        // On Windows, changing to a custom executable resolver has changed the
-        // error messages.
         .with_stderr_data(str![[r#"
 [COMPILING] foo v0.0.1 ([ROOT]/foo)
 [FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s