Version in base suite: 1.85.0+dfsg3-1
Base version: rustc_1.85.0+dfsg3-1
Target version: rustc_1.85.1+dfsg1-1+deb13u1
Base file: /srv/ftp-master.debian.org/ftp/pool/main/r/rustc/rustc_1.85.0+dfsg3-1.dsc
Target file: /srv/ftp-master.debian.org/policy/pool/main/r/rustc/rustc_1.85.1+dfsg1-1+deb13u1.dsc
RELEASES.md | 11
compiler/rustc_codegen_ssa/src/target_features.rs | 54
debian/changelog | 10
debian/control | 2
debian/copyright | 1
debian/gbp.conf | 4
debian/patches/behaviour/d-rust-lldb-paths.patch | 2
debian/patches/build/bootstrap-don-t-attempt-to-download-rustc-in-tests.patch | 2
debian/patches/build/bootstrap-tests-disable-compiler-rt-optimizing.patch | 2
debian/patches/build/d-bootstrap-custom-debuginfo-path.patch | 4
debian/patches/cargo/CVE-2026-5222-avoid-stripping-.git-suffix-when-for-non-gi.patch | 90
debian/patches/cargo/CVE-2026-5223-prohibit-unpacking-symlinks-and-other-unexp.patch | 108
debian/patches/prune/d-0020-remove-windows-dependencies.patch | 4
debian/patches/prune/d-0021-vendor-remove-windows-dependencies.patch | 2
debian/patches/series | 4
debian/patches/vendor/gitoxide-backport-fix-for-CVE-2025-31130.patch | 2
debian/patches/vendor/tar-CVE-2026-33055.patch | 51
debian/patches/vendor/tar-CVE-2026-33056.patch | 86
debian/rebase-patches.sh | 18
git-commit-hash | 2
git-commit-info | 6
library/std/src/fs.rs | 2
library/std/src/sys/pal/windows/fs.rs | 187
src/bootstrap/Cargo.lock | 4
src/bootstrap/Cargo.toml | 4
src/bootstrap/src/core/config/config.rs | 2
src/bootstrap/src/lib.rs | 4
src/ci/docker/scripts/rfl-build.sh | 20
src/librustdoc/doctest.rs | 170
src/librustdoc/doctest/runner.rs | 37
src/version | 2
tests/run-make/doctests-merge/rmake.rs | 1
tests/rustdoc-ui/doctest/doctest-output.rs | 2
tests/rustdoc-ui/doctest/failed-doctest-test-crate.edition2015.stdout | 28
tests/rustdoc-ui/doctest/failed-doctest-test-crate.edition2024.stdout | 23
tests/rustdoc-ui/doctest/failed-doctest-test-crate.rs | 17
tests/rustdoc-ui/target-feature-stability.rs | 28
vendor/cc-1.1.22/.cargo-checksum.json | 1
vendor/cc-1.1.22/CHANGELOG.md | 187
vendor/cc-1.1.22/Cargo.lock | 182
vendor/cc-1.1.22/Cargo.toml | 66
vendor/cc-1.1.22/LICENSE-APACHE | 201
vendor/cc-1.1.22/LICENSE-MIT | 25
vendor/cc-1.1.22/README.md | 27
vendor/cc-1.1.22/clippy.toml | 5
vendor/cc-1.1.22/src/command_helpers.rs | 488 +
vendor/cc-1.1.22/src/detect_compiler_family.c | 15
vendor/cc-1.1.22/src/lib.rs | 4318 ++++++++++
vendor/cc-1.1.22/src/parallel/async_executor.rs | 118
vendor/cc-1.1.22/src/parallel/job_token.rs | 273
vendor/cc-1.1.22/src/parallel/mod.rs | 4
vendor/cc-1.1.22/src/parallel/once_lock.rs | 47
vendor/cc-1.1.22/src/parallel/stderr.rs | 91
vendor/cc-1.1.22/src/target_info.rs | 26
vendor/cc-1.1.22/src/tempfile.rs | 86
vendor/cc-1.1.22/src/tool.rs | 476 +
vendor/cc-1.1.22/src/utilities.rs | 45
vendor/cc-1.1.22/src/windows/com.rs | 110
vendor/cc-1.1.22/src/windows/find_tools.rs | 1191 ++
vendor/cc-1.1.22/src/windows/mod.rs | 22
vendor/cc-1.1.22/src/windows/registry.rs | 191
vendor/cc-1.1.22/src/windows/setup_config.rs | 283
vendor/cc-1.1.22/src/windows/vs_instances.rs | 199
vendor/cc-1.1.22/src/windows/winapi.rs | 146
vendor/cc-1.1.22/src/windows/windows_sys.rs | 121
vendor/cc-1.1.22/src/windows/windows_targets.rs | 19
version | 2
67 files changed, 9721 insertions(+), 240 deletions(-)
dpkg-source: warning: cannot verify inline signature for /srv/release.debian.org/tmp/tmpq8ovk0yh/rustc_1.85.0+dfsg3-1.dsc: no acceptable signature found
dpkg-source: warning: cannot verify inline signature for /srv/release.debian.org/tmp/tmpq8ovk0yh/rustc_1.85.1+dfsg1-1+deb13u1.dsc: no acceptable signature found
diff -Nru rustc-1.85.0+dfsg3/RELEASES.md rustc-1.85.1+dfsg1/RELEASES.md
--- rustc-1.85.0+dfsg3/RELEASES.md 2025-02-17 18:17:27.000000000 +0000
+++ rustc-1.85.1+dfsg1/RELEASES.md 2025-03-15 16:27:19.000000000 +0000
@@ -1,3 +1,14 @@
+Version 1.85.1 (2025-03-18)
+==========================
+
+
+
+- [Fix the doctest-merging feature of the 2024 Edition.](https://github.com/rust-lang/rust/pull/137899/)
+- [Relax some `target_feature` checks when generating docs.](https://github.com/rust-lang/rust/pull/137632/)
+- [Fix errors in `std::fs::rename` on Windows 1607.](https://github.com/rust-lang/rust/pull/137528/)
+- [Downgrade bootstrap `cc` to fix custom targets.](https://github.com/rust-lang/rust/pull/137460/)
+- [Skip submodule updates when building Rust from a source tarball.](https://github.com/rust-lang/rust/pull/137338/)
+
Version 1.85.0 (2025-02-20)
==========================
diff -Nru rustc-1.85.0+dfsg3/compiler/rustc_codegen_ssa/src/target_features.rs rustc-1.85.1+dfsg1/compiler/rustc_codegen_ssa/src/target_features.rs
--- rustc-1.85.0+dfsg3/compiler/rustc_codegen_ssa/src/target_features.rs 2025-02-17 18:17:27.000000000 +0000
+++ rustc-1.85.1+dfsg1/compiler/rustc_codegen_ssa/src/target_features.rs 2025-03-15 16:27:19.000000000 +0000
@@ -10,7 +10,7 @@
use rustc_middle::ty::TyCtxt;
use rustc_session::parse::feature_err;
use rustc_span::{Span, Symbol, sym};
-use rustc_target::target_features;
+use rustc_target::target_features::{self, Stability};
use crate::errors;
@@ -65,11 +65,16 @@
// Only allow target features whose feature gates have been enabled
// and which are permitted to be toggled.
if let Err(reason) = stability.toggle_allowed(/*enable*/ true) {
- tcx.dcx().emit_err(errors::ForbiddenTargetFeatureAttr {
- span: item.span(),
- feature,
- reason,
- });
+ // We skip this error in rustdoc, where we want to allow all target features of
+ // all targets, so we can't check their ABI compatibility and anyway we are not
+ // generating code so "it's fine".
+ if !tcx.sess.opts.actually_rustdoc {
+ tcx.dcx().emit_err(errors::ForbiddenTargetFeatureAttr {
+ span: item.span(),
+ feature,
+ reason,
+ });
+ }
} else if let Some(nightly_feature) = stability.requires_nightly()
&& !rust_features.enabled(nightly_feature)
{
@@ -149,11 +154,38 @@
assert_eq!(cnum, LOCAL_CRATE);
let target = &tcx.sess.target;
if tcx.sess.opts.actually_rustdoc {
- // rustdoc needs to be able to document functions that use all the features, so
- // whitelist them all
- rustc_target::target_features::all_rust_features()
- .map(|(a, b)| (a.to_string(), b.compute_toggleability(target)))
- .collect()
+ // HACK: rustdoc would like to pretend that we have all the target features, so we
+ // have to merge all the lists into one. To ensure an unstable target never prevents
+ // a stable one from working, we merge the stability info of all instances of the
+ // same target feature name, with the "most stable" taking precedence. And then we
+ // hope that this doesn't cause issues anywhere else in the compiler...
+ let mut result: UnordMap> = Default::default();
+ for (name, stability) in rustc_target::target_features::all_rust_features() {
+ use std::collections::hash_map::Entry;
+ match result.entry(name.to_owned()) {
+ Entry::Vacant(vacant_entry) => {
+ vacant_entry.insert(stability.compute_toggleability(target));
+ }
+ Entry::Occupied(mut occupied_entry) => {
+ // Merge the two stabilities, "more stable" taking precedence.
+ match (occupied_entry.get(), &stability) {
+ (Stability::Stable { .. }, _)
+ | (
+ Stability::Unstable { .. },
+ Stability::Unstable { .. } | Stability::Forbidden { .. },
+ )
+ | (Stability::Forbidden { .. }, Stability::Forbidden { .. }) => {
+ // The stability in the entry is at least as good as the new one, just keep it.
+ }
+ _ => {
+ // Overwrite stabilite.
+ occupied_entry.insert(stability.compute_toggleability(target));
+ }
+ }
+ }
+ }
+ }
+ result
} else {
tcx.sess
.target
diff -Nru rustc-1.85.0+dfsg3/debian/changelog rustc-1.85.1+dfsg1/debian/changelog
--- rustc-1.85.0+dfsg3/debian/changelog 2025-04-24 15:47:57.000000000 +0000
+++ rustc-1.85.1+dfsg1/debian/changelog 2026-07-24 16:02:33.000000000 +0000
@@ -1,3 +1,13 @@
+rustc (1.85.1+dfsg1-1+deb13u1) trixie; urgency=medium
+
+ * New upstream point release 1.85.1 (Closes: #1135220)
+ - fix doctest merging with edition 2024
+ - fix rustdoc on 32-bit ARM
+ * backport tar CVE-2026-33055/CVE-2026-33056 fixes (Closes: #1135225)
+ * cherry-pick cargo CVE-2026-5222/CVE-2026-5223 fixes
+
+ -- Fabian Grünbichler Fri, 24 Jul 2026 18:02:33 +0200
+
rustc (1.85.0+dfsg3-1) unstable; urgency=medium
* backport fix for gix-features CVE-2025-31130
diff -Nru rustc-1.85.0+dfsg3/debian/control rustc-1.85.1+dfsg1/debian/control
--- rustc-1.85.0+dfsg3/debian/control 2025-04-11 11:13:51.000000000 +0000
+++ rustc-1.85.1+dfsg1/debian/control 2026-05-29 12:39:18.000000000 +0000
@@ -15,7 +15,7 @@
python3:native,
cargo:native (>= 1.84.0+dfsg) ,
rustc:native (>= 1.84.0+dfsg) ,
- rustc:native (<= 1.85.0+dfsg++) ,
+ rustc:native (<= 1.85.1++) ,
llvm-19-dev:native,
llvm-19-tools:native,
gcc-mingw-w64-x86-64-posix:native [amd64] ,
diff -Nru rustc-1.85.0+dfsg3/debian/copyright rustc-1.85.1+dfsg1/debian/copyright
--- rustc-1.85.0+dfsg3/debian/copyright 2025-04-24 15:47:57.000000000 +0000
+++ rustc-1.85.1+dfsg1/debian/copyright 2026-05-29 12:39:18.000000000 +0000
@@ -140,7 +140,6 @@
vendor/cc-1.0.73
vendor/cc-1.0.98
vendor/cc-1.0.99
- vendor/cc-1.1.22
vendor/cfg-if-0.1.10
vendor/chrono-0.4.19
vendor/chrono-0.4.38
diff -Nru rustc-1.85.0+dfsg3/debian/gbp.conf rustc-1.85.1+dfsg1/debian/gbp.conf
--- rustc-1.85.0+dfsg3/debian/gbp.conf 2025-04-11 11:13:51.000000000 +0000
+++ rustc-1.85.1+dfsg1/debian/gbp.conf 2026-05-29 12:39:18.000000000 +0000
@@ -4,8 +4,8 @@
component = extra
[import-orig]
-upstream-branch = upstream/experimental
-debian-branch = debian/experimental
+upstream-branch = upstream/trixie
+debian-branch = debian/trixie
[pq]
patch-numbers = False
diff -Nru rustc-1.85.0+dfsg3/debian/patches/behaviour/d-rust-lldb-paths.patch rustc-1.85.1+dfsg1/debian/patches/behaviour/d-rust-lldb-paths.patch
--- rustc-1.85.0+dfsg3/debian/patches/behaviour/d-rust-lldb-paths.patch 2025-04-24 15:47:57.000000000 +0000
+++ rustc-1.85.1+dfsg1/debian/patches/behaviour/d-rust-lldb-paths.patch 2026-05-29 12:58:45.000000000 +0000
@@ -11,7 +11,7 @@
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/src/etc/rust-lldb b/src/etc/rust-lldb
-index bce72f1..38e76c2 100755
+index bce72f1..a45e0bc 100755
--- a/src/etc/rust-lldb
+++ b/src/etc/rust-lldb
@@ -7,10 +7,10 @@ set -e
diff -Nru rustc-1.85.0+dfsg3/debian/patches/build/bootstrap-don-t-attempt-to-download-rustc-in-tests.patch rustc-1.85.1+dfsg1/debian/patches/build/bootstrap-don-t-attempt-to-download-rustc-in-tests.patch
--- rustc-1.85.0+dfsg3/debian/patches/build/bootstrap-don-t-attempt-to-download-rustc-in-tests.patch 2025-04-24 15:45:20.000000000 +0000
+++ rustc-1.85.1+dfsg1/debian/patches/build/bootstrap-don-t-attempt-to-download-rustc-in-tests.patch 2026-05-29 12:58:46.000000000 +0000
@@ -14,7 +14,7 @@
1 file changed, 4 insertions(+)
diff --git a/src/bootstrap/src/core/config/config.rs b/src/bootstrap/src/core/config/config.rs
-index d77da96..b1c6238 100644
+index c049794..6a4749b 100644
--- a/src/bootstrap/src/core/config/config.rs
+++ b/src/bootstrap/src/core/config/config.rs
@@ -1456,6 +1456,10 @@ impl Config {
diff -Nru rustc-1.85.0+dfsg3/debian/patches/build/bootstrap-tests-disable-compiler-rt-optimizing.patch rustc-1.85.1+dfsg1/debian/patches/build/bootstrap-tests-disable-compiler-rt-optimizing.patch
--- rustc-1.85.0+dfsg3/debian/patches/build/bootstrap-tests-disable-compiler-rt-optimizing.patch 2025-04-24 15:45:20.000000000 +0000
+++ rustc-1.85.1+dfsg1/debian/patches/build/bootstrap-tests-disable-compiler-rt-optimizing.patch 2026-05-29 12:58:45.000000000 +0000
@@ -16,7 +16,7 @@
1 file changed, 2 insertions(+)
diff --git a/src/bootstrap/src/core/config/config.rs b/src/bootstrap/src/core/config/config.rs
-index 0587408..d77da96 100644
+index 053330d..c049794 100644
--- a/src/bootstrap/src/core/config/config.rs
+++ b/src/bootstrap/src/core/config/config.rs
@@ -1454,6 +1454,8 @@ impl Config {
diff -Nru rustc-1.85.0+dfsg3/debian/patches/build/d-bootstrap-custom-debuginfo-path.patch rustc-1.85.1+dfsg1/debian/patches/build/d-bootstrap-custom-debuginfo-path.patch
--- rustc-1.85.0+dfsg3/debian/patches/build/d-bootstrap-custom-debuginfo-path.patch 2025-04-24 15:45:20.000000000 +0000
+++ rustc-1.85.1+dfsg1/debian/patches/build/d-bootstrap-custom-debuginfo-path.patch 2026-05-29 12:58:44.000000000 +0000
@@ -10,10 +10,10 @@
2 files changed, 3 insertions(+), 4 deletions(-)
diff --git a/src/bootstrap/src/lib.rs b/src/bootstrap/src/lib.rs
-index ccc115a..d483301 100644
+index e5d2fc7..0f10470 100644
--- a/src/bootstrap/src/lib.rs
+++ b/src/bootstrap/src/lib.rs
-@@ -1148,10 +1148,9 @@ Executed at: {executed_at}"#,
+@@ -1152,10 +1152,9 @@ Executed at: {executed_at}"#,
match which {
GitRepo::Rustc => {
diff -Nru rustc-1.85.0+dfsg3/debian/patches/cargo/CVE-2026-5222-avoid-stripping-.git-suffix-when-for-non-gi.patch rustc-1.85.1+dfsg1/debian/patches/cargo/CVE-2026-5222-avoid-stripping-.git-suffix-when-for-non-gi.patch
--- rustc-1.85.0+dfsg3/debian/patches/cargo/CVE-2026-5222-avoid-stripping-.git-suffix-when-for-non-gi.patch 1970-01-01 00:00:00.000000000 +0000
+++ rustc-1.85.1+dfsg1/debian/patches/cargo/CVE-2026-5222-avoid-stripping-.git-suffix-when-for-non-gi.patch 2026-05-29 12:58:47.000000000 +0000
@@ -0,0 +1,90 @@
+From: Arlo Siemsen
+Date: Mon, 25 May 2026 09:49:43 +0200
+Subject: CVE-2026-5222: avoid stripping .git suffix when for non git
+ registries
+MIME-Version: 1.0
+Content-Type: text/plain; charset="utf-8"
+Content-Transfer-Encoding: 8bit
+
+FG: backported from 1.96.0
+
+Signed-off-by: Fabian Grünbichler
+---
+ src/tools/cargo/src/cargo/sources/git/source.rs | 7 ++++
+ src/tools/cargo/src/cargo/util/canonical_url.rs | 44 ++++++++++++++-----------
+ 2 files changed, 31 insertions(+), 20 deletions(-)
+
+diff --git a/src/tools/cargo/src/cargo/sources/git/source.rs b/src/tools/cargo/src/cargo/sources/git/source.rs
+index 1c1dc4c..c1299b9 100644
+--- a/src/tools/cargo/src/cargo/sources/git/source.rs
++++ b/src/tools/cargo/src/cargo/sources/git/source.rs
+@@ -450,6 +450,13 @@ mod test {
+ assert_eq!(ident1, ident2);
+ }
+
++ #[test]
++ fn test_canonicalize_idents_does_not_strip_dot_git_for_sparse() {
++ let ident1 = ident(&src("sparse+https://crates.io/fake-registry"));
++ let ident2 = ident(&src("sparse+https://crates.io/fake-registry.git"));
++ assert_ne!(ident1, ident2);
++ }
++
+ fn src(s: &str) -> SourceId {
+ SourceId::for_git(&s.into_url().unwrap(), GitReference::DefaultBranch).unwrap()
+ }
+diff --git a/src/tools/cargo/src/cargo/util/canonical_url.rs b/src/tools/cargo/src/cargo/util/canonical_url.rs
+index 7516e03..2716d2d 100644
+--- a/src/tools/cargo/src/cargo/util/canonical_url.rs
++++ b/src/tools/cargo/src/cargo/util/canonical_url.rs
+@@ -33,27 +33,31 @@ impl CanonicalUrl {
+ url.path_segments_mut().unwrap().pop_if_empty();
+ }
+
+- // For GitHub URLs specifically, just lower-case everything. GitHub
+- // treats both the same, but they hash differently, and we're gonna be
+- // hashing them. This wants a more general solution, and also we're
+- // almost certainly not using the same case conversion rules that GitHub
+- // does. (See issue #84)
+- if url.host_str() == Some("github.com") {
+- url = format!("https{}", &url[url::Position::AfterScheme..])
+- .parse()
+- .unwrap();
+- let path = url.path().to_lowercase();
+- url.set_path(&path);
+- }
++ // Perform further canonicalization specific to git registries, which
++ // do not contain a `+` specifier.
++ if !url.scheme().contains('+') {
++ // For GitHub URLs specifically, just lower-case everything. GitHub
++ // treats both the same, but they hash differently, and we're gonna be
++ // hashing them. This wants a more general solution, and also we're
++ // almost certainly not using the same case conversion rules that GitHub
++ // does. (See issue #84)
++ if url.host_str() == Some("github.com") {
++ url = format!("https{}", &url[url::Position::AfterScheme..])
++ .parse()
++ .unwrap();
++ let path = url.path().to_lowercase();
++ url.set_path(&path);
++ }
+
+- // Repos can generally be accessed with or without `.git` extension.
+- let needs_chopping = url.path().ends_with(".git");
+- if needs_chopping {
+- let last = {
+- let last = url.path_segments().unwrap().next_back().unwrap();
+- last[..last.len() - 4].to_owned()
+- };
+- url.path_segments_mut().unwrap().pop().push(&last);
++ // Repos can generally be accessed with or without `.git` extension.
++ let needs_chopping = url.path().ends_with(".git");
++ if needs_chopping {
++ let last = {
++ let last = url.path_segments().unwrap().next_back().unwrap();
++ last[..last.len() - 4].to_owned()
++ };
++ url.path_segments_mut().unwrap().pop().push(&last);
++ }
+ }
+
+ Ok(CanonicalUrl(url))
diff -Nru rustc-1.85.0+dfsg3/debian/patches/cargo/CVE-2026-5223-prohibit-unpacking-symlinks-and-other-unexp.patch rustc-1.85.1+dfsg1/debian/patches/cargo/CVE-2026-5223-prohibit-unpacking-symlinks-and-other-unexp.patch
--- rustc-1.85.0+dfsg3/debian/patches/cargo/CVE-2026-5223-prohibit-unpacking-symlinks-and-other-unexp.patch 1970-01-01 00:00:00.000000000 +0000
+++ rustc-1.85.1+dfsg1/debian/patches/cargo/CVE-2026-5223-prohibit-unpacking-symlinks-and-other-unexp.patch 2026-05-29 12:59:09.000000000 +0000
@@ -0,0 +1,108 @@
+From: Josh Triplett
+Date: Mon, 30 Mar 2026 10:35:55 -0700
+Subject: CVE-2026-5223: prohibit unpacking symlinks and other unexpected
+ entries
+MIME-Version: 1.0
+Content-Type: text/plain; charset="utf-8"
+Content-Transfer-Encoding: 8bit
+
+Cargo has historically not allowed creating .crate packages containing
+symlinks. (It packages the symlink target in place of the symlink,
+instead.) So, any package containing a symlink would have to be
+hand-constructed. Such packages are also not allowed on crates.io, so it
+could only come from an alternate registry.
+
+Rather than dealing with symlink traversal attacks when unpacking a
+crate, just prohibit symlinks entirely.
+
+In the process, also prohibit other kinds of unusual entries. As an
+exception, allow character devices but warn about them, because some
+exist in crates on crates.io.
+
+FG: backported from 1.96.0
+Signed-off-by: Fabian Grünbichler
+---
+ src/tools/cargo/src/cargo/sources/registry/mod.rs | 11 +++++++-
+ src/tools/cargo/tests/testsuite/registry.rs | 31 ++++++++++++-----------
+ 2 files changed, 26 insertions(+), 16 deletions(-)
+
+diff --git a/src/tools/cargo/src/cargo/sources/registry/mod.rs b/src/tools/cargo/src/cargo/sources/registry/mod.rs
+index bf10f81..313258f 100644
+--- a/src/tools/cargo/src/cargo/sources/registry/mod.rs
++++ b/src/tools/cargo/src/cargo/sources/registry/mod.rs
+@@ -197,7 +197,7 @@ use cargo_util::paths::{self, exclude_from_backups_and_indexing};
+ use flate2::read::GzDecoder;
+ use serde::Deserialize;
+ use serde::Serialize;
+-use tar::Archive;
++use tar::{Archive, EntryType};
+ use tracing::debug;
+
+ use crate::core::dependency::Dependency;
+@@ -662,6 +662,15 @@ impl<'gctx> RegistrySource<'gctx> {
+ prefix
+ )
+ }
++
++ // Prevent unpacking symlinks and other unexpected entry types
++ match entry.header().entry_type() {
++ EntryType::Regular | EntryType::Directory => {}
++ t => anyhow::bail!(
++ "invalid tarball downloaded, contains an entry at {entry_path:?} with invalid type {t:?}",
++ ),
++ }
++
+ // Prevent unpacking the lockfile from the crate itself.
+ if entry_path
+ .file_name()
+diff --git a/src/tools/cargo/tests/testsuite/registry.rs b/src/tools/cargo/tests/testsuite/registry.rs
+index 8498713..df922ef 100644
+--- a/src/tools/cargo/tests/testsuite/registry.rs
++++ b/src/tools/cargo/tests/testsuite/registry.rs
+@@ -3213,8 +3213,7 @@ fn package_lock_inside_package_is_overwritten() {
+ }
+
+ #[cargo_test]
+-fn package_lock_as_a_symlink_inside_package_is_overwritten() {
+- let registry = registry::init();
++fn package_lock_as_a_symlink_inside_package_is_invalid() {
+ let p = project()
+ .file(
+ "Cargo.toml",
+@@ -3237,21 +3236,23 @@ fn package_lock_as_a_symlink_inside_package_is_overwritten() {
+ .symlink(".cargo-ok", "src/lib.rs")
+ .publish();
+
+- p.cargo("check").run();
++ p.cargo("check")
++ .with_status(101)
++ .with_stderr_data(str![[r#"
++[UPDATING] `dummy-registry` index
++[LOCKING] 1 package to latest compatible version
++[DOWNLOADING] crates ...
++[DOWNLOADED] bar v0.0.1 (registry `dummy-registry`)
++[ERROR] failed to download replaced source registry `crates-io`
+
+- let id = SourceId::for_registry(registry.index_url()).unwrap();
+- let hash = cargo::util::hex::short_hash(&id);
+- let pkg_root = paths::cargo_home()
+- .join("registry")
+- .join("src")
+- .join(format!("-{}", hash))
+- .join("bar-0.0.1");
+- let ok = pkg_root.join(".cargo-ok");
+- let librs = pkg_root.join("src/lib.rs");
++Caused by:
++ failed to unpack package `bar v0.0.1 (registry `dummy-registry`)`
+
+- // Is correctly overwritten and doesn't affect the file linked to
+- assert_eq!(ok.metadata().unwrap().len(), 7);
+- assert_eq!(fs::read_to_string(librs).unwrap(), "pub fn f() {}");
++Caused by:
++ invalid tarball downloaded, contains an entry at "bar-0.0.1/.cargo-ok" with invalid type Symlink
++
++"#]])
++ .run();
+ }
+
+ #[cargo_test]
diff -Nru rustc-1.85.0+dfsg3/debian/patches/prune/d-0020-remove-windows-dependencies.patch rustc-1.85.1+dfsg1/debian/patches/prune/d-0020-remove-windows-dependencies.patch
--- rustc-1.85.0+dfsg3/debian/patches/prune/d-0020-remove-windows-dependencies.patch 2025-04-24 15:45:20.000000000 +0000
+++ rustc-1.85.1+dfsg1/debian/patches/prune/d-0020-remove-windows-dependencies.patch 2026-05-29 12:58:43.000000000 +0000
@@ -153,10 +153,10 @@
default = ['backtrace']
backtrace = ['addr2line', 'miniz_oxide', 'object', 'ruzstd']
diff --git a/src/bootstrap/Cargo.toml b/src/bootstrap/Cargo.toml
-index d8775a6..3d16075 100644
+index 68e0591..f56f1dc 100644
--- a/src/bootstrap/Cargo.toml
+++ b/src/bootstrap/Cargo.toml
-@@ -64,21 +64,6 @@ xz2 = "0.1"
+@@ -66,21 +66,6 @@ xz2 = "0.1"
# Dependencies needed by the build-metrics feature
sysinfo = { version = "0.33.0", default-features = false, optional = true, features = ["system"] }
diff -Nru rustc-1.85.0+dfsg3/debian/patches/prune/d-0021-vendor-remove-windows-dependencies.patch rustc-1.85.1+dfsg1/debian/patches/prune/d-0021-vendor-remove-windows-dependencies.patch
--- rustc-1.85.0+dfsg3/debian/patches/prune/d-0021-vendor-remove-windows-dependencies.patch 2025-04-24 15:45:20.000000000 +0000
+++ rustc-1.85.1+dfsg1/debian/patches/prune/d-0021-vendor-remove-windows-dependencies.patch 2026-05-29 12:58:43.000000000 +0000
@@ -283,7 +283,7 @@
[badges.maintenance]
status = "passively-maintained"
diff --git a/vendor/curl-0.4.47/Cargo.toml b/vendor/curl-0.4.47/Cargo.toml
-index 580f431..7ac8e91 100644
+index 580f431f..7ac8e91 100644
--- a/vendor/curl-0.4.47/Cargo.toml
+++ b/vendor/curl-0.4.47/Cargo.toml
@@ -144,14 +144,3 @@ optional = true
diff -Nru rustc-1.85.0+dfsg3/debian/patches/series rustc-1.85.1+dfsg1/debian/patches/series
--- rustc-1.85.0+dfsg3/debian/patches/series 2025-04-24 15:47:57.000000000 +0000
+++ rustc-1.85.1+dfsg1/debian/patches/series 2026-05-29 12:58:48.000000000 +0000
@@ -48,3 +48,7 @@
vendor/cargo-update-git2-bindings.patch
vendor/gitoxide-backport-fix-for-CVE-2025-31130.patch
upstream/RUSTSEC-2025-0024-sync-mpsc-prevent-double-free-on-Drop.patch
+vendor/tar-CVE-2026-33056.patch
+vendor/tar-CVE-2026-33055.patch
+cargo/CVE-2026-5222-avoid-stripping-.git-suffix-when-for-non-gi.patch
+cargo/CVE-2026-5223-prohibit-unpacking-symlinks-and-other-unexp.patch
diff -Nru rustc-1.85.0+dfsg3/debian/patches/vendor/gitoxide-backport-fix-for-CVE-2025-31130.patch rustc-1.85.1+dfsg1/debian/patches/vendor/gitoxide-backport-fix-for-CVE-2025-31130.patch
--- rustc-1.85.0+dfsg3/debian/patches/vendor/gitoxide-backport-fix-for-CVE-2025-31130.patch 2025-04-24 15:47:57.000000000 +0000
+++ rustc-1.85.1+dfsg1/debian/patches/vendor/gitoxide-backport-fix-for-CVE-2025-31130.patch 2026-05-29 12:58:47.000000000 +0000
@@ -406,7 +406,7 @@
-#[cfg(any(feature = "rustsha1", feature = "fast-sha1"))]
-pub use write::Write;
diff --git a/vendor/gix-hash-0.15.1/Cargo.toml b/vendor/gix-hash-0.15.1/Cargo.toml
-index 6cb9fc8..a219070 100644
+index 6cb9fc8..ce31fb0 100644
--- a/vendor/gix-hash-0.15.1/Cargo.toml
+++ b/vendor/gix-hash-0.15.1/Cargo.toml
@@ -46,18 +46,26 @@ optional = true
diff -Nru rustc-1.85.0+dfsg3/debian/patches/vendor/tar-CVE-2026-33055.patch rustc-1.85.1+dfsg1/debian/patches/vendor/tar-CVE-2026-33055.patch
--- rustc-1.85.0+dfsg3/debian/patches/vendor/tar-CVE-2026-33055.patch 1970-01-01 00:00:00.000000000 +0000
+++ rustc-1.85.1+dfsg1/debian/patches/vendor/tar-CVE-2026-33055.patch 2026-05-29 12:58:47.000000000 +0000
@@ -0,0 +1,51 @@
+From: Alex Crichton
+Date: Thu, 19 Mar 2026 16:56:51 -0500
+Subject: archive: Unconditionally honor PAX size (#441)
+MIME-Version: 1.0
+Content-Type: text/plain; charset="utf-8"
+Content-Transfer-Encoding: 8bit
+
+This synchronizes our behavior with most other tar parsers
+(including astral-tokio-tar and Go archive/tar) ensuring
+that we don't parse things differently.
+
+The problem with parsing size in particular differently is
+it's easy to craft a tar archive that appears completely differently
+between two parsers. This is the case with e.g. crates.io where
+astral-tokio-tar is used for validation server side, but cargo uses
+the `tar` crate to upload.
+
+With this, the two projects agree.
+
+Signed-off-by: Colin Walters
+Co-authored-by: Colin Walters
+
+FG: drop test-related changes, adapt version
+Signed-off-by: Fabian Grünbichler
+
+
+Fixes: CVE-2026-33055
+---
+ vendor/tar-0.4.43/src/archive.rs | 9 +++++----
+ 1 file changed, 5 insertions(+), 4 deletions(-)
+
+diff --git a/vendor/tar-0.4.43/src/archive.rs b/vendor/tar-0.4.43/src/archive.rs
+index 17938a8..519049e 100644
+--- a/vendor/tar-0.4.43/src/archive.rs
++++ b/vendor/tar-0.4.43/src/archive.rs
+@@ -351,10 +351,11 @@ impl<'a> EntriesFields<'a> {
+
+ let file_pos = self.next;
+ let mut size = header.entry_size()?;
+- if size == 0 {
+- if let Some(pax_size) = pax_size {
+- size = pax_size;
+- }
++ // If this exists, it must override the header size. Disagreement among
++ // parsers allows construction of malicious archives that appear different
++ // when parsed.
++ if let Some(pax_size) = pax_size {
++ size = pax_size;
+ }
+ let ret = EntryFields {
+ size: size,
diff -Nru rustc-1.85.0+dfsg3/debian/patches/vendor/tar-CVE-2026-33056.patch rustc-1.85.1+dfsg1/debian/patches/vendor/tar-CVE-2026-33056.patch
--- rustc-1.85.0+dfsg3/debian/patches/vendor/tar-CVE-2026-33056.patch 1970-01-01 00:00:00.000000000 +0000
+++ rustc-1.85.1+dfsg1/debian/patches/vendor/tar-CVE-2026-33056.patch 2026-05-29 12:58:47.000000000 +0000
@@ -0,0 +1,86 @@
+From: Alex Crichton
+Date: Thu, 19 Mar 2026 16:58:05 -0500
+Subject: archive: Prevent symlink-directory collision chmod attack (#442)
+MIME-Version: 1.0
+Content-Type: text/plain; charset="utf-8"
+Content-Transfer-Encoding: 8bit
+
+When unpacking a tarball containing a symlink followed by a directory
+entry with the same path, unpack_dir previously used fs::metadata()
+which follows symlinks. This allowed an attacker to modify permissions
+on arbitrary directories outside the extraction path.
+
+The fix uses fs::symlink_metadata() to detect symlinks and refuse to
+treat them as valid existing directories.
+
+Document more exhaustively+consistently security caveats.
+
+Reported-by: Sergei Zimmerman
+Assisted-by: OpenCode (Claude claude-opus-4-5)
+
+Signed-off-by: Colin Walters
+Co-authored-by: Colin Walters
+
+FG: drop test-related changes, adapt version
+Signed-off-by: Fabian Grünbichler
+
+Fixes: CVE-2026-33056
+---
+ vendor/tar-0.4.43/src/archive.rs | 18 +++++++++++++++---
+ vendor/tar-0.4.43/src/entry.rs | 7 ++++---
+ 2 files changed, 19 insertions(+), 6 deletions(-)
+
+diff --git a/vendor/tar-0.4.43/src/archive.rs b/vendor/tar-0.4.43/src/archive.rs
+index 924e54a..17938a8 100644
+--- a/vendor/tar-0.4.43/src/archive.rs
++++ b/vendor/tar-0.4.43/src/archive.rs
+@@ -92,9 +92,21 @@ impl Archive {
+ /// extracting each file in turn to the location specified by the entry's
+ /// path name.
+ ///
+- /// This operation is relatively sensitive in that it will not write files
+- /// outside of the path specified by `dst`. Files in the archive which have
+- /// a '..' in their path are skipped during the unpacking process.
++ /// # Security
++ ///
++ /// A best-effort is made to prevent writing files outside `dst` (paths
++ /// containing `..` are skipped, symlinks are validated). However, there
++ /// have been historical bugs in this area, and more may exist. For this
++ /// reason, when processing untrusted archives, stronger sandboxing is
++ /// encouraged: e.g. the [`cap-std`] crate and/or OS-level
++ /// containerization/virtualization.
++ ///
++ /// If `dst` does not exist, it is created. Unpacking into an existing
++ /// directory merges content. This function assumes `dst` is not
++ /// concurrently modified by untrusted processes. Protecting against
++ /// TOCTOU races is out of scope for this crate.
++ ///
++ /// [`cap-std`]: https://docs.rs/cap-std/
+ ///
+ /// # Examples
+ ///
+diff --git a/vendor/tar-0.4.43/src/entry.rs b/vendor/tar-0.4.43/src/entry.rs
+index b6b48b4..c9f3b9f 100644
+--- a/vendor/tar-0.4.43/src/entry.rs
++++ b/vendor/tar-0.4.43/src/entry.rs
+@@ -212,8 +212,9 @@ impl<'a, R: Read> Entry<'a, R> {
+ /// also be propagated to the path `dst`. Any existing file at the location
+ /// `dst` will be overwritten.
+ ///
+- /// This function carefully avoids writing outside of `dst`. If the file has
+- /// a '..' in its path, this function will skip it and return false.
++ /// # Security
++ ///
++ /// See [`Archive::unpack`].
+ ///
+ /// # Examples
+ ///
+@@ -446,7 +447,7 @@ impl<'a> EntryFields<'a> {
+ // If the directory already exists just let it slide
+ fs::create_dir(dst).or_else(|err| {
+ if err.kind() == ErrorKind::AlreadyExists {
+- let prev = fs::metadata(dst);
++ let prev = fs::symlink_metadata(dst);
+ if prev.map(|m| m.is_dir()).unwrap_or(false) {
+ return Ok(());
+ }
diff -Nru rustc-1.85.0+dfsg3/debian/rebase-patches.sh rustc-1.85.1+dfsg1/debian/rebase-patches.sh
--- rustc-1.85.0+dfsg3/debian/rebase-patches.sh 2025-03-17 18:06:58.000000000 +0000
+++ rustc-1.85.1+dfsg1/debian/rebase-patches.sh 2026-05-29 12:39:18.000000000 +0000
@@ -5,13 +5,13 @@
dfsg="${2:-+dfsg1}"
upstream_tag="upstream/${ver/\~/_}${dfsg/\~/_}"
-git show -s upstream/experimental
-git show -s debian/experimental
+git show -s upstream/trixie
+git show -s debian/trixie
printf "\ngit top-level dir: %s\n" "$(git rev-parse --show-toplevel)"
printf "version: $ver\n"
-if ! git merge-base --is-ancestor upstream/experimental debian/experimental; then
- echo >&2 "upstream/experimental is not an ancestor of debian/experimental"
+if ! git merge-base --is-ancestor upstream/trixie debian/trixie; then
+ echo >&2 "upstream/trixie is not an ancestor of debian/trixie"
fi
if git rev-parse "${upstream_tag}" 2>/dev/null >/dev/null; then
echo >&2 "tag already exists: ${upstream_tag}"
@@ -21,8 +21,8 @@
if [ "$x" != "y" ]; then exit 1; fi
cd "$(git rev-parse --show-toplevel)"
-git branch -f upstream/rebase-patches upstream/experimental
-git branch -f debian/rebase-patches debian/experimental
+git branch -f upstream/rebase-patches upstream/trixie
+git branch -f debian/rebase-patches debian/trixie
git checkout debian/rebase-patches
gbp pq drop || true
@@ -52,9 +52,9 @@
git add debian/patches
git commit -m "early-stage update of patches for ${ver}${dfsg}"
git checkout .
-git rebase @~ --onto=debian/experimental
-git branch -f debian/experimental
-git checkout debian/experimental
+git rebase @~ --onto=debian/trixie
+git branch -f debian/trixie
+git checkout debian/trixie
# cleanup
git tag -d "${upstream_tag}" || true
diff -Nru rustc-1.85.0+dfsg3/git-commit-hash rustc-1.85.1+dfsg1/git-commit-hash
--- rustc-1.85.0+dfsg3/git-commit-hash 2025-02-17 18:17:27.000000000 +0000
+++ rustc-1.85.1+dfsg1/git-commit-hash 2025-03-15 16:27:19.000000000 +0000
@@ -1 +1 @@
-4d91de4e48198da2e33413efdcd9cd2cc0c46688
\ No newline at end of file
+4eb161250e340c8f48f66e2b929ef4a5bed7c181
\ No newline at end of file
diff -Nru rustc-1.85.0+dfsg3/git-commit-info rustc-1.85.1+dfsg1/git-commit-info
--- rustc-1.85.0+dfsg3/git-commit-info 2025-02-17 18:17:27.000000000 +0000
+++ rustc-1.85.1+dfsg1/git-commit-info 2025-03-15 16:27:19.000000000 +0000
@@ -1,3 +1,3 @@
-4d91de4e48198da2e33413efdcd9cd2cc0c46688
-4d91de4e4
-2025-02-17
+4eb161250e340c8f48f66e2b929ef4a5bed7c181
+4eb161250
+2025-03-15
diff -Nru rustc-1.85.0+dfsg3/library/std/src/fs.rs rustc-1.85.1+dfsg1/library/std/src/fs.rs
--- rustc-1.85.0+dfsg3/library/std/src/fs.rs 2025-02-17 18:17:27.000000000 +0000
+++ rustc-1.85.1+dfsg1/library/std/src/fs.rs 2025-03-15 16:27:19.000000000 +0000
@@ -2402,7 +2402,7 @@
/// # Platform-specific behavior
///
/// This function currently corresponds to the `rename` function on Unix
-/// and the `SetFileInformationByHandle` function on Windows.
+/// and the `MoveFileExW` or `SetFileInformationByHandle` function on Windows.
///
/// Because of this, the behavior when both `from` and `to` exist differs. On
/// Unix, if `from` is a directory, `to` must also be an (empty) directory. If
diff -Nru rustc-1.85.0+dfsg3/library/std/src/sys/pal/windows/fs.rs rustc-1.85.1+dfsg1/library/std/src/sys/pal/windows/fs.rs
--- rustc-1.85.0+dfsg3/library/std/src/sys/pal/windows/fs.rs 2025-02-17 18:17:27.000000000 +0000
+++ rustc-1.85.1+dfsg1/library/std/src/sys/pal/windows/fs.rs 2025-03-15 16:27:19.000000000 +0000
@@ -1,10 +1,10 @@
use super::api::{self, WinError};
use super::{IoResult, to_u16s};
-use crate::alloc::{alloc, handle_alloc_error};
+use crate::alloc::{Layout, alloc, dealloc};
use crate::borrow::Cow;
use crate::ffi::{OsStr, OsString, c_void};
use crate::io::{self, BorrowedCursor, Error, IoSlice, IoSliceMut, SeekFrom};
-use crate::mem::{self, MaybeUninit};
+use crate::mem::{self, MaybeUninit, offset_of};
use crate::os::windows::io::{AsHandle, BorrowedHandle};
use crate::os::windows::prelude::*;
use crate::path::{Path, PathBuf};
@@ -296,6 +296,10 @@
impl File {
pub fn open(path: &Path, opts: &OpenOptions) -> io::Result {
let path = maybe_verbatim(path)?;
+ Self::open_native(&path, opts)
+ }
+
+ fn open_native(path: &[u16], opts: &OpenOptions) -> io::Result {
let creation = opts.get_creation_mode()?;
let handle = unsafe {
c::CreateFileW(
@@ -1234,141 +1238,72 @@
let old = maybe_verbatim(old)?;
let new = maybe_verbatim(new)?;
- let new_len_without_nul_in_bytes = (new.len() - 1).try_into().unwrap();
-
- // The last field of FILE_RENAME_INFO, the file name, is unsized,
- // and FILE_RENAME_INFO has two padding bytes.
- // Therefore we need to make sure to not allocate less than
- // size_of::() bytes, which would be the case with
- // 0 or 1 character paths + a null byte.
- let struct_size = mem::size_of::()
- .max(mem::offset_of!(c::FILE_RENAME_INFO, FileName) + new.len() * mem::size_of::());
-
- let struct_size: u32 = struct_size.try_into().unwrap();
-
- let create_file = |extra_access, extra_flags| {
- let handle = unsafe {
- HandleOrInvalid::from_raw_handle(c::CreateFileW(
- old.as_ptr(),
- c::SYNCHRONIZE | c::DELETE | extra_access,
- c::FILE_SHARE_READ | c::FILE_SHARE_WRITE | c::FILE_SHARE_DELETE,
- ptr::null(),
- c::OPEN_EXISTING,
- c::FILE_ATTRIBUTE_NORMAL | c::FILE_FLAG_BACKUP_SEMANTICS | extra_flags,
- ptr::null_mut(),
- ))
- };
-
- OwnedHandle::try_from(handle).map_err(|_| io::Error::last_os_error())
- };
-
- // The following code replicates `MoveFileEx`'s behavior as reverse-engineered from its disassembly.
- // If `old` refers to a mount point, we move it instead of the target.
- let handle = match create_file(c::FILE_READ_ATTRIBUTES, c::FILE_FLAG_OPEN_REPARSE_POINT) {
- Ok(handle) => {
- let mut file_attribute_tag_info: MaybeUninit =
- MaybeUninit::uninit();
-
- let result = unsafe {
- cvt(c::GetFileInformationByHandleEx(
- handle.as_raw_handle(),
- c::FileAttributeTagInfo,
- file_attribute_tag_info.as_mut_ptr().cast(),
- mem::size_of::().try_into().unwrap(),
- ))
+ if unsafe { c::MoveFileExW(old.as_ptr(), new.as_ptr(), c::MOVEFILE_REPLACE_EXISTING) } == 0 {
+ let err = api::get_last_error();
+ // if `MoveFileExW` fails with ERROR_ACCESS_DENIED then try to move
+ // the file while ignoring the readonly attribute.
+ // This is accomplished by calling `SetFileInformationByHandle` with `FileRenameInfoEx`.
+ if err == WinError::ACCESS_DENIED {
+ let mut opts = OpenOptions::new();
+ opts.access_mode(c::DELETE);
+ opts.custom_flags(c::FILE_FLAG_OPEN_REPARSE_POINT | c::FILE_FLAG_BACKUP_SEMANTICS);
+ let Ok(f) = File::open_native(&old, &opts) else { return Err(err).io_result() };
+
+ // Calculate the layout of the `FILE_RENAME_INFO` we pass to `SetFileInformation`
+ // This is a dynamically sized struct so we need to get the position of the last field to calculate the actual size.
+ let Ok(new_len_without_nul_in_bytes): Result = ((new.len() - 1) * 2).try_into()
+ else {
+ return Err(err).io_result();
};
-
- if let Err(err) = result {
- if err.raw_os_error() == Some(c::ERROR_INVALID_PARAMETER as _)
- || err.raw_os_error() == Some(c::ERROR_INVALID_FUNCTION as _)
- {
- // `GetFileInformationByHandleEx` documents that not all underlying drivers support all file information classes.
- // Since we know we passed the correct arguments, this means the underlying driver didn't understand our request;
- // `MoveFileEx` proceeds by reopening the file without inhibiting reparse point behavior.
- None
- } else {
- Some(Err(err))
- }
- } else {
- // SAFETY: The struct has been initialized by GetFileInformationByHandleEx
- let file_attribute_tag_info = unsafe { file_attribute_tag_info.assume_init() };
- let file_type = FileType::new(
- file_attribute_tag_info.FileAttributes,
- file_attribute_tag_info.ReparseTag,
- );
-
- if file_type.is_symlink() {
- // The file is a mount point, junction point or symlink so
- // don't reopen the file so that the link gets renamed.
- Some(Ok(handle))
- } else {
- // Otherwise reopen the file without inhibiting reparse point behavior.
- None
+ let offset: u32 = offset_of!(c::FILE_RENAME_INFO, FileName).try_into().unwrap();
+ let struct_size = offset + new_len_without_nul_in_bytes + 2;
+ let layout =
+ Layout::from_size_align(struct_size as usize, align_of::())
+ .unwrap();
+
+ // SAFETY: We allocate enough memory for a full FILE_RENAME_INFO struct and a filename.
+ let file_rename_info;
+ unsafe {
+ file_rename_info = alloc(layout).cast::();
+ if file_rename_info.is_null() {
+ return Err(io::ErrorKind::OutOfMemory.into());
}
- }
- }
- // The underlying driver may not support `FILE_FLAG_OPEN_REPARSE_POINT`: Retry without it.
- Err(err) if err.raw_os_error() == Some(c::ERROR_INVALID_PARAMETER as _) => None,
- Err(err) => Some(Err(err)),
- }
- .unwrap_or_else(|| create_file(0, 0))?;
-
- let layout = core::alloc::Layout::from_size_align(
- struct_size as _,
- mem::align_of::(),
- )
- .unwrap();
-
- let file_rename_info = unsafe { alloc(layout) } as *mut c::FILE_RENAME_INFO;
-
- if file_rename_info.is_null() {
- handle_alloc_error(layout);
- }
-
- // SAFETY: file_rename_info is a non-null pointer pointing to memory allocated by the global allocator.
- let mut file_rename_info = unsafe { Box::from_raw(file_rename_info) };
-
- // SAFETY: We have allocated enough memory for a full FILE_RENAME_INFO struct and a filename.
- unsafe {
- (&raw mut (*file_rename_info).Anonymous).write(c::FILE_RENAME_INFO_0 {
- Flags: c::FILE_RENAME_FLAG_REPLACE_IF_EXISTS | c::FILE_RENAME_FLAG_POSIX_SEMANTICS,
- });
-
- (&raw mut (*file_rename_info).RootDirectory).write(ptr::null_mut());
- (&raw mut (*file_rename_info).FileNameLength).write(new_len_without_nul_in_bytes);
-
- new.as_ptr()
- .copy_to_nonoverlapping((&raw mut (*file_rename_info).FileName) as *mut u16, new.len());
- }
- // We don't use `set_file_information_by_handle` here as `FILE_RENAME_INFO` is used for both `FileRenameInfo` and `FileRenameInfoEx`.
- let result = unsafe {
- cvt(c::SetFileInformationByHandle(
- handle.as_raw_handle(),
- c::FileRenameInfoEx,
- (&raw const *file_rename_info).cast::(),
- struct_size,
- ))
- };
+ (&raw mut (*file_rename_info).Anonymous).write(c::FILE_RENAME_INFO_0 {
+ Flags: c::FILE_RENAME_FLAG_REPLACE_IF_EXISTS
+ | c::FILE_RENAME_FLAG_POSIX_SEMANTICS,
+ });
- if let Err(err) = result {
- if err.raw_os_error() == Some(c::ERROR_INVALID_PARAMETER as _) {
- // FileRenameInfoEx and FILE_RENAME_FLAG_POSIX_SEMANTICS were added in Windows 10 1607; retry with FileRenameInfo.
- file_rename_info.Anonymous.ReplaceIfExists = 1;
+ (&raw mut (*file_rename_info).RootDirectory).write(ptr::null_mut());
+ // Don't include the NULL in the size
+ (&raw mut (*file_rename_info).FileNameLength).write(new_len_without_nul_in_bytes);
+
+ new.as_ptr().copy_to_nonoverlapping(
+ (&raw mut (*file_rename_info).FileName).cast::(),
+ new.len(),
+ );
+ }
- cvt(unsafe {
+ let result = unsafe {
c::SetFileInformationByHandle(
- handle.as_raw_handle(),
- c::FileRenameInfo,
- (&raw const *file_rename_info).cast::(),
+ f.as_raw_handle(),
+ c::FileRenameInfoEx,
+ file_rename_info.cast::(),
struct_size,
)
- })?;
+ };
+ unsafe { dealloc(file_rename_info.cast::(), layout) };
+ if result == 0 {
+ if api::get_last_error() == WinError::DIR_NOT_EMPTY {
+ return Err(WinError::DIR_NOT_EMPTY).io_result();
+ } else {
+ return Err(err).io_result();
+ }
+ }
} else {
- return Err(err);
+ return Err(err).io_result();
}
}
-
Ok(())
}
diff -Nru rustc-1.85.0+dfsg3/src/bootstrap/Cargo.lock rustc-1.85.1+dfsg1/src/bootstrap/Cargo.lock
--- rustc-1.85.0+dfsg3/src/bootstrap/Cargo.lock 2025-02-17 18:17:27.000000000 +0000
+++ rustc-1.85.1+dfsg1/src/bootstrap/Cargo.lock 2025-03-15 16:27:19.000000000 +0000
@@ -84,9 +84,9 @@
[[package]]
name = "cc"
-version = "1.2.0"
+version = "1.1.22"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "1aeb932158bd710538c73702db6945cb68a8fb08c519e6e12706b94263b36db8"
+checksum = "9540e661f81799159abee814118cc139a2004b3a3aa3ea37724a1b66530b90e0"
dependencies = [
"shlex",
]
diff -Nru rustc-1.85.0+dfsg3/src/bootstrap/Cargo.toml rustc-1.85.1+dfsg1/src/bootstrap/Cargo.toml
--- rustc-1.85.0+dfsg3/src/bootstrap/Cargo.toml 2025-02-17 18:17:27.000000000 +0000
+++ rustc-1.85.1+dfsg1/src/bootstrap/Cargo.toml 2025-03-15 16:27:19.000000000 +0000
@@ -36,7 +36,9 @@
# Most of the time updating these dependencies requires modifications to the
# bootstrap codebase(e.g., https://github.com/rust-lang/rust/issues/124565);
# otherwise, some targets will fail. That's why these dependencies are explicitly pinned.
-cc = "=1.2.0"
+#
+# Do not upgrade this crate unless https://github.com/rust-lang/cc-rs/issues/1317 is fixed.
+cc = "=1.1.22"
cmake = "=0.1.48"
build_helper = { path = "../build_helper" }
diff -Nru rustc-1.85.0+dfsg3/src/bootstrap/src/core/config/config.rs rustc-1.85.1+dfsg1/src/bootstrap/src/core/config/config.rs
--- rustc-1.85.0+dfsg3/src/bootstrap/src/core/config/config.rs 2025-02-17 18:17:27.000000000 +0000
+++ rustc-1.85.1+dfsg1/src/bootstrap/src/core/config/config.rs 2025-03-15 16:27:19.000000000 +0000
@@ -2668,7 +2668,7 @@
/// used instead to provide a nice error to the user if the submodule is
/// missing.
pub(crate) fn update_submodule(&self, relative_path: &str) {
- if !self.submodules() {
+ if self.rust_info.is_from_tarball() || !self.submodules() {
return;
}
diff -Nru rustc-1.85.0+dfsg3/src/bootstrap/src/lib.rs rustc-1.85.1+dfsg1/src/bootstrap/src/lib.rs
--- rustc-1.85.0+dfsg3/src/bootstrap/src/lib.rs 2025-02-17 18:17:27.000000000 +0000
+++ rustc-1.85.1+dfsg1/src/bootstrap/src/lib.rs 2025-03-15 16:27:19.000000000 +0000
@@ -471,6 +471,10 @@
/// The given `err_hint` will be shown to the user if the submodule is not
/// checked out and submodule management is disabled.
pub fn require_submodule(&self, submodule: &str, err_hint: Option<&str>) {
+ if self.rust_info().is_from_tarball() {
+ return;
+ }
+
// When testing bootstrap itself, it is much faster to ignore
// submodules. Almost all Steps work fine without their submodules.
if cfg!(test) && !self.config.submodules() {
diff -Nru rustc-1.85.0+dfsg3/src/ci/docker/scripts/rfl-build.sh rustc-1.85.1+dfsg1/src/ci/docker/scripts/rfl-build.sh
--- rustc-1.85.0+dfsg3/src/ci/docker/scripts/rfl-build.sh 2025-02-17 18:17:27.000000000 +0000
+++ rustc-1.85.1+dfsg1/src/ci/docker/scripts/rfl-build.sh 2025-03-15 16:27:19.000000000 +0000
@@ -8,16 +8,10 @@
../x.py build --stage 2 library rustdoc clippy rustfmt
../x.py build --stage 0 cargo
-# Install rustup so that we can use the built toolchain easily, and also
-# install bindgen in an easy way.
-curl --proto '=https' --tlsv1.2 -sSf -o rustup.sh https://sh.rustup.rs
-sh rustup.sh -y --default-toolchain none
-
-source /cargo/env
-
-BUILD_DIR=$(realpath ./build)
-rustup toolchain link local "${BUILD_DIR}"/x86_64-unknown-linux-gnu/stage2
-rustup default local
+BUILD_DIR=$(realpath ./build/x86_64-unknown-linux-gnu)
+
+# Provide path to rustc, rustdoc, clippy-driver and rustfmt to RfL
+export PATH=${PATH}:${BUILD_DIR}/stage2/bin
mkdir -p rfl
cd rfl
@@ -33,10 +27,14 @@
git -C linux checkout FETCH_HEAD
# Install bindgen
-"${BUILD_DIR}"/x86_64-unknown-linux-gnu/stage0/bin/cargo install \
+"${BUILD_DIR}"/stage0/bin/cargo install \
--version $(linux/scripts/min-tool-version.sh bindgen) \
+ --root ${BUILD_DIR}/bindgen \
bindgen-cli
+# Provide path to bindgen to RfL
+export PATH=${PATH}:${BUILD_DIR}/bindgen/bin
+
# Configure Rust for Linux
cat < linux/kernel/configs/rfl-for-rust-ci.config
# CONFIG_WERROR is not set
diff -Nru rustc-1.85.0+dfsg3/src/librustdoc/doctest/runner.rs rustc-1.85.1+dfsg1/src/librustdoc/doctest/runner.rs
--- rustc-1.85.0+dfsg3/src/librustdoc/doctest/runner.rs 2025-02-17 18:17:27.000000000 +0000
+++ rustc-1.85.1+dfsg1/src/librustdoc/doctest/runner.rs 2025-03-15 16:27:19.000000000 +0000
@@ -14,6 +14,7 @@
crate_attrs: FxIndexSet,
ids: String,
output: String,
+ output_merged_tests: String,
supports_color: bool,
nb_tests: usize,
}
@@ -24,6 +25,7 @@
crate_attrs: FxIndexSet::default(),
ids: String::new(),
output: String::new(),
+ output_merged_tests: String::new(),
supports_color: true,
nb_tests: 0,
}
@@ -55,7 +57,8 @@
scraped_test,
ignore,
self.nb_tests,
- &mut self.output
+ &mut self.output,
+ &mut self.output_merged_tests,
),
));
self.supports_color &= doctest.supports_color;
@@ -78,9 +81,11 @@
"
.to_string();
+ let mut code_prefix = String::new();
+
for crate_attr in &self.crate_attrs {
- code.push_str(crate_attr);
- code.push('\n');
+ code_prefix.push_str(crate_attr);
+ code_prefix.push('\n');
}
if opts.attrs.is_empty() {
@@ -88,15 +93,16 @@
// lints that are commonly triggered in doctests. The crate-level test attributes are
// commonly used to make tests fail in case they trigger warnings, so having this there in
// that case may cause some tests to pass when they shouldn't have.
- code.push_str("#![allow(unused)]\n");
+ code_prefix.push_str("#![allow(unused)]\n");
}
// Next, any attributes that came from the crate root via #![doc(test(attr(...)))].
for attr in &opts.attrs {
- code.push_str(&format!("#![{attr}]\n"));
+ code_prefix.push_str(&format!("#![{attr}]\n"));
}
code.push_str("extern crate test;\n");
+ writeln!(code, "extern crate doctest_bundle_{edition} as doctest_bundle;").unwrap();
let test_args = test_args.iter().fold(String::new(), |mut x, arg| {
write!(x, "{arg:?}.to_string(),").unwrap();
@@ -161,12 +167,12 @@
std::process::Termination::report(test::test_main(test_args, Vec::from(TESTS), None))
}}",
nb_tests = self.nb_tests,
- output = self.output,
+ output = self.output_merged_tests,
ids = self.ids,
)
.expect("failed to generate test code");
let runnable_test = RunnableDocTest {
- full_test_code: code,
+ full_test_code: format!("{code_prefix}{code}", code = self.output),
full_test_line_offset: 0,
test_opts: test_options,
global_opts: opts.clone(),
@@ -174,7 +180,7 @@
line: 0,
edition,
no_run: false,
- is_multiple_tests: true,
+ merged_test_code: Some(code),
};
let ret =
run_test(runnable_test, rustdoc_options, self.supports_color, |_: UnusedExterns| {});
@@ -189,14 +195,15 @@
ignore: bool,
id: usize,
output: &mut String,
+ output_merged_tests: &mut String,
) -> String {
let test_id = format!("__doctest_{id}");
if ignore {
// We generate nothing else.
- writeln!(output, "mod {test_id} {{\n").unwrap();
+ writeln!(output, "pub mod {test_id} {{}}\n").unwrap();
} else {
- writeln!(output, "mod {test_id} {{\n{}{}", doctest.crates, doctest.maybe_crate_attrs)
+ writeln!(output, "pub mod {test_id} {{\n{}{}", doctest.crates, doctest.maybe_crate_attrs)
.unwrap();
if doctest.has_main_fn {
output.push_str(&doctest.everything_else);
@@ -216,11 +223,17 @@
)
.unwrap();
}
+ writeln!(
+ output,
+ "\npub fn __main_fn() -> impl std::process::Termination {{ main() }} \n}}\n"
+ )
+ .unwrap();
}
let not_running = ignore || scraped_test.langstr.no_run;
writeln!(
- output,
+ output_merged_tests,
"
+mod {test_id} {{
pub const TEST: test::TestDescAndFn = test::TestDescAndFn::new_doctest(
{test_name:?}, {ignore}, {file:?}, {line}, {no_run}, {should_panic},
test::StaticTestFn(
@@ -242,7 +255,7 @@
if let Some(bin_path) = crate::__doctest_mod::doctest_path() {{
test::assert_test_result(crate::__doctest_mod::doctest_runner(bin_path, {id}))
}} else {{
- test::assert_test_result(self::main())
+ test::assert_test_result(doctest_bundle::{test_id}::__main_fn())
}}
",
)
diff -Nru rustc-1.85.0+dfsg3/src/librustdoc/doctest.rs rustc-1.85.1+dfsg1/src/librustdoc/doctest.rs
--- rustc-1.85.0+dfsg3/src/librustdoc/doctest.rs 2025-02-17 18:17:27.000000000 +0000
+++ rustc-1.85.1+dfsg1/src/librustdoc/doctest.rs 2025-03-15 16:27:19.000000000 +0000
@@ -95,7 +95,7 @@
.map_err(|error| format!("failed to create args file: {error:?}"))?;
// We now put the common arguments into the file we created.
- let mut content = vec!["--crate-type=bin".to_string()];
+ let mut content = vec![];
for cfg in &options.cfgs {
content.push(format!("--cfg={cfg}"));
@@ -488,12 +488,18 @@
line: usize,
edition: Edition,
no_run: bool,
- is_multiple_tests: bool,
+ merged_test_code: Option,
}
impl RunnableDocTest {
- fn path_for_merged_doctest(&self) -> PathBuf {
- self.test_opts.outdir.path().join(format!("doctest_{}.rs", self.edition))
+ fn path_for_merged_doctest_bundle(&self) -> PathBuf {
+ self.test_opts.outdir.path().join(format!("doctest_bundle_{}.rs", self.edition))
+ }
+ fn path_for_merged_doctest_runner(&self) -> PathBuf {
+ self.test_opts.outdir.path().join(format!("doctest_runner_{}.rs", self.edition))
+ }
+ fn is_multiple_tests(&self) -> bool {
+ self.merged_test_code.is_some()
}
}
@@ -512,91 +518,108 @@
let rust_out = add_exe_suffix("rust_out".to_owned(), &rustdoc_options.target);
let output_file = doctest.test_opts.outdir.path().join(rust_out);
- let rustc_binary = rustdoc_options
- .test_builder
- .as_deref()
- .unwrap_or_else(|| rustc_interface::util::rustc_path().expect("found rustc"));
- let mut compiler = wrapped_rustc_command(&rustdoc_options.test_builder_wrappers, rustc_binary);
+ // Common arguments used for compiling the doctest runner.
+ // On merged doctests, the compiler is invoked twice: once for the test code itself,
+ // and once for the runner wrapper (which needs to use `#![feature]` on stable).
+ let mut compiler_args = vec![];
- compiler.arg(format!("@{}", doctest.global_opts.args_file.display()));
+ compiler_args.push(format!("@{}", doctest.global_opts.args_file.display()));
if let Some(sysroot) = &rustdoc_options.maybe_sysroot {
- compiler.arg(format!("--sysroot={}", sysroot.display()));
+ compiler_args.push(format!("--sysroot={}", sysroot.display()));
}
- compiler.arg("--edition").arg(doctest.edition.to_string());
- if !doctest.is_multiple_tests {
- // Setting these environment variables is unneeded if this is a merged doctest.
- compiler.env("UNSTABLE_RUSTDOC_TEST_PATH", &doctest.test_opts.path);
- compiler.env(
- "UNSTABLE_RUSTDOC_TEST_LINE",
- format!("{}", doctest.line as isize - doctest.full_test_line_offset as isize),
- );
- }
- compiler.arg("-o").arg(&output_file);
+ compiler_args.extend_from_slice(&["--edition".to_owned(), doctest.edition.to_string()]);
if langstr.test_harness {
- compiler.arg("--test");
+ compiler_args.push("--test".to_owned());
}
if rustdoc_options.json_unused_externs.is_enabled() && !langstr.compile_fail {
- compiler.arg("--error-format=json");
- compiler.arg("--json").arg("unused-externs");
- compiler.arg("-W").arg("unused_crate_dependencies");
- compiler.arg("-Z").arg("unstable-options");
+ compiler_args.push("--error-format=json".to_owned());
+ compiler_args.extend_from_slice(&["--json".to_owned(), "unused-externs".to_owned()]);
+ compiler_args.extend_from_slice(&["-W".to_owned(), "unused_crate_dependencies".to_owned()]);
+ compiler_args.extend_from_slice(&["-Z".to_owned(), "unstable-options".to_owned()]);
}
if doctest.no_run && !langstr.compile_fail && rustdoc_options.persist_doctests.is_none() {
// FIXME: why does this code check if it *shouldn't* persist doctests
// -- shouldn't it be the negation?
- compiler.arg("--emit=metadata");
+ compiler_args.push("--emit=metadata".to_owned());
}
- compiler.arg("--target").arg(match &rustdoc_options.target {
- TargetTuple::TargetTuple(s) => s,
- TargetTuple::TargetJson { path_for_rustdoc, .. } => {
- path_for_rustdoc.to_str().expect("target path must be valid unicode")
- }
- });
+ compiler_args.extend_from_slice(&[
+ "--target".to_owned(),
+ match &rustdoc_options.target {
+ TargetTuple::TargetTuple(s) => s.clone(),
+ TargetTuple::TargetJson { path_for_rustdoc, .. } => {
+ path_for_rustdoc.to_str().expect("target path must be valid unicode").to_owned()
+ }
+ },
+ ]);
if let ErrorOutputType::HumanReadable(kind, color_config) = rustdoc_options.error_format {
let short = kind.short();
let unicode = kind == HumanReadableErrorType::Unicode;
if short {
- compiler.arg("--error-format").arg("short");
+ compiler_args.extend_from_slice(&["--error-format".to_owned(), "short".to_owned()]);
}
if unicode {
- compiler.arg("--error-format").arg("human-unicode");
+ compiler_args
+ .extend_from_slice(&["--error-format".to_owned(), "human-unicode".to_owned()]);
}
match color_config {
ColorConfig::Never => {
- compiler.arg("--color").arg("never");
+ compiler_args.extend_from_slice(&["--color".to_owned(), "never".to_owned()]);
}
ColorConfig::Always => {
- compiler.arg("--color").arg("always");
+ compiler_args.extend_from_slice(&["--color".to_owned(), "always".to_owned()]);
}
ColorConfig::Auto => {
- compiler.arg("--color").arg(if supports_color { "always" } else { "never" });
+ compiler_args.extend_from_slice(&[
+ "--color".to_owned(),
+ if supports_color { "always" } else { "never" }.to_owned(),
+ ]);
}
}
}
+ let rustc_binary = rustdoc_options
+ .test_builder
+ .as_deref()
+ .unwrap_or_else(|| rustc_interface::util::rustc_path().expect("found rustc"));
+ let mut compiler = wrapped_rustc_command(&rustdoc_options.test_builder_wrappers, rustc_binary);
+
+ compiler.args(&compiler_args);
+
// If this is a merged doctest, we need to write it into a file instead of using stdin
// because if the size of the merged doctests is too big, it'll simply break stdin.
- if doctest.is_multiple_tests {
+ if doctest.is_multiple_tests() {
// It makes the compilation failure much faster if it is for a combined doctest.
compiler.arg("--error-format=short");
- let input_file = doctest.path_for_merged_doctest();
+ let input_file = doctest.path_for_merged_doctest_bundle();
if std::fs::write(&input_file, &doctest.full_test_code).is_err() {
// If we cannot write this file for any reason, we leave. All combined tests will be
// tested as standalone tests.
return Err(TestFailure::CompileError);
}
- compiler.arg(input_file);
if !rustdoc_options.nocapture {
// If `nocapture` is disabled, then we don't display rustc's output when compiling
// the merged doctests.
compiler.stderr(Stdio::null());
}
+ // bundled tests are an rlib, loaded by a separate runner executable
+ compiler
+ .arg("--crate-type=lib")
+ .arg("--out-dir")
+ .arg(doctest.test_opts.outdir.path())
+ .arg(input_file);
} else {
+ compiler.arg("--crate-type=bin").arg("-o").arg(&output_file);
+ // Setting these environment variables is unneeded if this is a merged doctest.
+ compiler.env("UNSTABLE_RUSTDOC_TEST_PATH", &doctest.test_opts.path);
+ compiler.env(
+ "UNSTABLE_RUSTDOC_TEST_LINE",
+ format!("{}", doctest.line as isize - doctest.full_test_line_offset as isize),
+ );
compiler.arg("-");
compiler.stdin(Stdio::piped());
compiler.stderr(Stdio::piped());
@@ -605,8 +628,65 @@
debug!("compiler invocation for doctest: {compiler:?}");
let mut child = compiler.spawn().expect("Failed to spawn rustc process");
- let output = if doctest.is_multiple_tests {
+ let output = if let Some(merged_test_code) = &doctest.merged_test_code {
+ // compile-fail tests never get merged, so this should always pass
let status = child.wait().expect("Failed to wait");
+
+ // the actual test runner is a separate component, built with nightly-only features;
+ // build it now
+ let runner_input_file = doctest.path_for_merged_doctest_runner();
+
+ let mut runner_compiler =
+ wrapped_rustc_command(&rustdoc_options.test_builder_wrappers, rustc_binary);
+ // the test runner does not contain any user-written code, so this doesn't allow
+ // the user to exploit nightly-only features on stable
+ runner_compiler.env("RUSTC_BOOTSTRAP", "1");
+ runner_compiler.args(compiler_args);
+ runner_compiler.args(&["--crate-type=bin", "-o"]).arg(&output_file);
+ let mut extern_path = std::ffi::OsString::from(format!(
+ "--extern=doctest_bundle_{edition}=",
+ edition = doctest.edition
+ ));
+ for extern_str in &rustdoc_options.extern_strs {
+ if let Some((_cratename, path)) = extern_str.split_once('=') {
+ // Direct dependencies of the tests themselves are
+ // indirect dependencies of the test runner.
+ // They need to be in the library search path.
+ let dir = Path::new(path)
+ .parent()
+ .filter(|x| x.components().count() > 0)
+ .unwrap_or(Path::new("."));
+ runner_compiler.arg("-L").arg(dir);
+ }
+ }
+ let output_bundle_file = doctest
+ .test_opts
+ .outdir
+ .path()
+ .join(format!("libdoctest_bundle_{edition}.rlib", edition = doctest.edition));
+ extern_path.push(&output_bundle_file);
+ runner_compiler.arg(extern_path);
+ runner_compiler.arg(&runner_input_file);
+ if std::fs::write(&runner_input_file, &merged_test_code).is_err() {
+ // If we cannot write this file for any reason, we leave. All combined tests will be
+ // tested as standalone tests.
+ return Err(TestFailure::CompileError);
+ }
+ if !rustdoc_options.nocapture {
+ // If `nocapture` is disabled, then we don't display rustc's output when compiling
+ // the merged doctests.
+ runner_compiler.stderr(Stdio::null());
+ }
+ runner_compiler.arg("--error-format=short");
+ debug!("compiler invocation for doctest runner: {runner_compiler:?}");
+
+ let status = if !status.success() {
+ status
+ } else {
+ let mut child_runner = runner_compiler.spawn().expect("Failed to spawn rustc process");
+ child_runner.wait().expect("Failed to wait")
+ };
+
process::Output { status, stdout: Vec::new(), stderr: Vec::new() }
} else {
let stdin = child.stdin.as_mut().expect("Failed to open stdin");
@@ -683,7 +763,7 @@
cmd.arg(&output_file);
} else {
cmd = Command::new(&output_file);
- if doctest.is_multiple_tests {
+ if doctest.is_multiple_tests() {
cmd.env("RUSTDOC_DOCTEST_BIN_PATH", &output_file);
}
}
@@ -691,7 +771,7 @@
cmd.current_dir(run_directory);
}
- let result = if doctest.is_multiple_tests || rustdoc_options.nocapture {
+ let result = if doctest.is_multiple_tests() || rustdoc_options.nocapture {
cmd.status().map(|status| process::Output {
status,
stdout: Vec::new(),
@@ -977,7 +1057,7 @@
line: scraped_test.line,
edition: scraped_test.edition(&rustdoc_options),
no_run: scraped_test.no_run(&rustdoc_options),
- is_multiple_tests: false,
+ merged_test_code: None,
};
let res =
run_test(runnable_test, &rustdoc_options, doctest.supports_color, report_unused_externs);
diff -Nru rustc-1.85.0+dfsg3/src/version rustc-1.85.1+dfsg1/src/version
--- rustc-1.85.0+dfsg3/src/version 2025-02-17 18:17:27.000000000 +0000
+++ rustc-1.85.1+dfsg1/src/version 2025-03-15 16:27:19.000000000 +0000
@@ -1 +1 @@
-1.85.0
+1.85.1
diff -Nru rustc-1.85.0+dfsg3/tests/run-make/doctests-merge/rmake.rs rustc-1.85.1+dfsg1/tests/run-make/doctests-merge/rmake.rs
--- rustc-1.85.0+dfsg3/tests/run-make/doctests-merge/rmake.rs 2025-02-17 18:17:27.000000000 +0000
+++ rustc-1.85.1+dfsg1/tests/run-make/doctests-merge/rmake.rs 2025-03-15 16:27:19.000000000 +0000
@@ -8,7 +8,6 @@
let output = cmd
.input(input_file)
.arg("--test")
- .arg("-Zunstable-options")
.edition(edition)
.arg("--test-args=--test-threads=1")
.extern_("foo", dep.display().to_string())
diff -Nru rustc-1.85.0+dfsg3/tests/rustdoc-ui/doctest/doctest-output.rs rustc-1.85.1+dfsg1/tests/rustdoc-ui/doctest/doctest-output.rs
--- rustc-1.85.0+dfsg3/tests/rustdoc-ui/doctest/doctest-output.rs 2025-02-17 18:17:27.000000000 +0000
+++ rustc-1.85.1+dfsg1/tests/rustdoc-ui/doctest/doctest-output.rs 2025-03-15 16:27:19.000000000 +0000
@@ -2,7 +2,7 @@
//@[edition2015]edition:2015
//@[edition2015]aux-build:extern_macros.rs
//@[edition2015]compile-flags:--test --test-args=--test-threads=1
-//@[edition2024]edition:2015
+//@[edition2024]edition:2024
//@[edition2024]aux-build:extern_macros.rs
//@[edition2024]compile-flags:--test --test-args=--test-threads=1
//@ normalize-stdout: "tests/rustdoc-ui/doctest" -> "$$DIR"
diff -Nru rustc-1.85.0+dfsg3/tests/rustdoc-ui/doctest/failed-doctest-test-crate.edition2015.stdout rustc-1.85.1+dfsg1/tests/rustdoc-ui/doctest/failed-doctest-test-crate.edition2015.stdout
--- rustc-1.85.0+dfsg3/tests/rustdoc-ui/doctest/failed-doctest-test-crate.edition2015.stdout 1970-01-01 00:00:00.000000000 +0000
+++ rustc-1.85.1+dfsg1/tests/rustdoc-ui/doctest/failed-doctest-test-crate.edition2015.stdout 2025-03-15 16:27:19.000000000 +0000
@@ -0,0 +1,28 @@
+
+running 1 test
+test $DIR/failed-doctest-test-crate.rs - m (line 14) ... FAILED
+
+failures:
+
+---- $DIR/failed-doctest-test-crate.rs - m (line 14) stdout ----
+error[E0432]: unresolved import `test`
+ --> $DIR/failed-doctest-test-crate.rs:15:5
+ |
+LL | use test::*;
+ | ^^^^ you might be missing crate `test`
+ |
+help: consider importing the `test` crate
+ |
+LL + extern crate test;
+ |
+
+error: aborting due to 1 previous error
+
+For more information about this error, try `rustc --explain E0432`.
+Couldn't compile the test.
+
+failures:
+ $DIR/failed-doctest-test-crate.rs - m (line 14)
+
+test result: FAILED. 0 passed; 1 failed; 0 ignored; 0 measured; 0 filtered out; finished in $TIME
+
diff -Nru rustc-1.85.0+dfsg3/tests/rustdoc-ui/doctest/failed-doctest-test-crate.edition2024.stdout rustc-1.85.1+dfsg1/tests/rustdoc-ui/doctest/failed-doctest-test-crate.edition2024.stdout
--- rustc-1.85.0+dfsg3/tests/rustdoc-ui/doctest/failed-doctest-test-crate.edition2024.stdout 1970-01-01 00:00:00.000000000 +0000
+++ rustc-1.85.1+dfsg1/tests/rustdoc-ui/doctest/failed-doctest-test-crate.edition2024.stdout 2025-03-15 16:27:19.000000000 +0000
@@ -0,0 +1,23 @@
+
+running 1 test
+test $DIR/failed-doctest-test-crate.rs - m (line 14) ... FAILED
+
+failures:
+
+---- $DIR/failed-doctest-test-crate.rs - m (line 14) stdout ----
+error[E0432]: unresolved import `test`
+ --> $DIR/failed-doctest-test-crate.rs:15:5
+ |
+LL | use test::*;
+ | ^^^^ use of undeclared crate or module `test`
+
+error: aborting due to 1 previous error
+
+For more information about this error, try `rustc --explain E0432`.
+Couldn't compile the test.
+
+failures:
+ $DIR/failed-doctest-test-crate.rs - m (line 14)
+
+test result: FAILED. 0 passed; 1 failed; 0 ignored; 0 measured; 0 filtered out; finished in $TIME
+
diff -Nru rustc-1.85.0+dfsg3/tests/rustdoc-ui/doctest/failed-doctest-test-crate.rs rustc-1.85.1+dfsg1/tests/rustdoc-ui/doctest/failed-doctest-test-crate.rs
--- rustc-1.85.0+dfsg3/tests/rustdoc-ui/doctest/failed-doctest-test-crate.rs 1970-01-01 00:00:00.000000000 +0000
+++ rustc-1.85.1+dfsg1/tests/rustdoc-ui/doctest/failed-doctest-test-crate.rs 2025-03-15 16:27:19.000000000 +0000
@@ -0,0 +1,17 @@
+// FIXME: if/when the output of the test harness can be tested on its own, this test should be
+// adapted to use that, and that normalize line can go away
+
+//@ revisions: edition2015 edition2024
+//@[edition2015]edition:2015
+//@[edition2024]edition:2024
+//@ compile-flags:--test
+//@ normalize-stdout: "tests/rustdoc-ui/doctest" -> "$$DIR"
+//@ normalize-stdout: "finished in \d+\.\d+s" -> "finished in $$TIME"
+//@ failure-status: 101
+
+///
+///
+/// ```rust
+/// use test::*;
+/// ```
+pub mod m {}
diff -Nru rustc-1.85.0+dfsg3/tests/rustdoc-ui/target-feature-stability.rs rustc-1.85.1+dfsg1/tests/rustdoc-ui/target-feature-stability.rs
--- rustc-1.85.0+dfsg3/tests/rustdoc-ui/target-feature-stability.rs 1970-01-01 00:00:00.000000000 +0000
+++ rustc-1.85.1+dfsg1/tests/rustdoc-ui/target-feature-stability.rs 2025-03-15 16:27:19.000000000 +0000
@@ -0,0 +1,28 @@
+//! This is a regression test for , ensuring
+//! that we can use the `neon` target feature on ARM32 targets in rustdoc despite there
+//! being a "forbidden" feature of the same name for aarch64, and rustdoc merging the
+//! target features of all targets.
+//@ check-pass
+//@ revisions: arm aarch64
+//@[arm] compile-flags: --target armv7-unknown-linux-gnueabihf
+//@[arm] needs-llvm-components: arm
+//@[aarch64] compile-flags: --target aarch64-unknown-none-softfloat
+//@[aarch64] needs-llvm-components: aarch64
+
+#![crate_type = "lib"]
+#![feature(no_core, lang_items)]
+#![feature(arm_target_feature)]
+#![no_core]
+
+#[lang = "sized"]
+pub trait Sized {}
+
+// `fp-armv8` is "forbidden" on aarch64 as we tie it to `neon`.
+#[target_feature(enable = "fp-armv8")]
+pub fn fun1() {}
+
+// This would usually be rejected as it changes the ABI.
+// But we disable that check in rustdoc since we are building "for all targets" and the
+// check can't really handle that.
+#[target_feature(enable = "soft-float")]
+pub fn fun2() {}
diff -Nru rustc-1.85.0+dfsg3/vendor/cc-1.1.22/.cargo-checksum.json rustc-1.85.1+dfsg1/vendor/cc-1.1.22/.cargo-checksum.json
--- rustc-1.85.0+dfsg3/vendor/cc-1.1.22/.cargo-checksum.json 1970-01-01 00:00:00.000000000 +0000
+++ rustc-1.85.1+dfsg1/vendor/cc-1.1.22/.cargo-checksum.json 2025-03-15 16:27:19.000000000 +0000
@@ -0,0 +1 @@
+{"files":{"CHANGELOG.md":"92aeb6dec3e4b55e3951a4d00f6df20edc51545afca124d983454f7c05e37357","Cargo.lock":"565d86121026a1cade3014777f9a32c97dc76b843510f2c709cff3562ff04e1c","Cargo.toml":"1352b0476c28b89568e740579130ab017ad0f4b546083cf03ff61827d45361f3","LICENSE-APACHE":"a60eea817514531668d7e00765731449fe14d059d3249e0bc93b36de45f759f2","LICENSE-MIT":"378f5840b258e2779c39418f3f2d7b2ba96f1c7917dd6be0713f88305dbda397","README.md":"f1ddbede208a5b78333a25dac0a7598e678e9b601a7d99a791069bddaf180dfe","clippy.toml":"aa7850db4350883c8f373bd0d6b4d19bf3b75f13c1c238e24368c109cb52fb1d","src/command_helpers.rs":"0b54800fe5c89cd102a5f872fe1a843c1a58e026bc4bbc611e207914b8c84dda","src/detect_compiler_family.c":"97ca4b021495611e828becea6187add37414186a16dfedd26c2947cbce6e8b2f","src/lib.rs":"c80c94e82937980f711500cd3289842ab4bc42bcc4efd9febf64729e27410ecc","src/parallel/async_executor.rs":"4ce24435fff6b6555b43fee042c16bd65d4150d0346567f246b9190d85b45983","src/parallel/job_token.rs":"f4ed0a03d89a42bfd5527133d12b267af519b745f3f2b997ed293df15a2641b8","src/parallel/mod.rs":"55fb4c2d15e66677b2ed5ffa6d65ea161bcf1a1e1dc7910ee3bde06f2f67ab14","src/parallel/once_lock.rs":"d13e4cb82d6bca3297ca8671d83a40dd5affd7ac89191d733dd451867181bb02","src/parallel/stderr.rs":"74384d41198740a6fce0877f144262db09fb091225fa8fbfa771314bb11487c6","src/target_info.rs":"f939a570c99d897fdd37cd491a4ee0657e2c7480ec71acbd9cbee48732d4bfbc","src/tempfile.rs":"ebafb5b0e5d08b0706916ed911d4245240e60c3e2d0c9a1630c520842988a2b3","src/tool.rs":"2e6550062e021f2b394388172bbb01e86fe6a94d2395bcb3c85a9e86690da1a9","src/utilities.rs":"a13bb0a351fcef72823485b1b5dc4f514c533fa4feac95deb66ed9e5fbfe7b53","src/windows/com.rs":"a2800ddb81215fff2bf618336f5c4ff8e8bdb746dd18b795873c7304b3f2a5e3","src/windows/find_tools.rs":"dd6b2450909cd8334a2aa2ce856bcc72a9654d92422267d6345d5fabfcbf57c5","src/windows/mod.rs":"34cfa201cfbcac7ccaa3ea5295d3e4200439af3cc5c6433baf81502596040a89","src/windows/registry.rs":"c521b72c825e8095843e73482ffa810ed066ad8bb9f86e6db0c5c143c171aba1","src/windows/setup_config.rs":"754439cbab492afd44c9755abcbec1a41c9b2c358131cee2df13c0e996dbbec8","src/windows/vs_instances.rs":"946527cf8fd32c3472f6a2884dcdec290763101097334c7478f9c24c3950db6b","src/windows/winapi.rs":"250d51c1826d1a2329e9889dd9f058cfce253dbf2a678b076147c6cdb5db046c","src/windows/windows_sys.rs":"e2714c8307bfa083b9745eb0e46cadd7f98d7b88abf45a7637172019324e34b8","src/windows/windows_targets.rs":"5b4648ebc22b028caca9f4b4bf8881fe2d094b7bec217264ba2e6e2c49d1ccee"},"package":"9540e661f81799159abee814118cc139a2004b3a3aa3ea37724a1b66530b90e0"}
\ No newline at end of file
diff -Nru rustc-1.85.0+dfsg3/vendor/cc-1.1.22/CHANGELOG.md rustc-1.85.1+dfsg1/vendor/cc-1.1.22/CHANGELOG.md
--- rustc-1.85.0+dfsg3/vendor/cc-1.1.22/CHANGELOG.md 1970-01-01 00:00:00.000000000 +0000
+++ rustc-1.85.1+dfsg1/vendor/cc-1.1.22/CHANGELOG.md 2025-03-15 16:27:19.000000000 +0000
@@ -0,0 +1,187 @@
+# Changelog
+All notable changes to this project will be documented in this file.
+
+The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
+and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
+
+## [Unreleased]
+
+## [1.1.22](https://github.com/rust-lang/cc-rs/compare/cc-v1.1.21...cc-v1.1.22) - 2024-09-27
+
+### Other
+
+- Don't rerun if PATH changes ([#1215](https://github.com/rust-lang/cc-rs/pull/1215))
+
+## [1.1.21](https://github.com/rust-lang/cc-rs/compare/cc-v1.1.20...cc-v1.1.21) - 2024-09-18
+
+### Other
+
+- disable pic for targets that end in `-none` ([#1212](https://github.com/rust-lang/cc-rs/pull/1212))
+
+## [1.1.20](https://github.com/rust-lang/cc-rs/compare/cc-v1.1.19...cc-v1.1.20) - 2024-09-17
+
+### Other
+
+- Add buildcache as known Rust and C/C++ compiler wrapper ([#1209](https://github.com/rust-lang/cc-rs/pull/1209))
+
+## [1.1.19](https://github.com/rust-lang/cc-rs/compare/cc-v1.1.18...cc-v1.1.19) - 2024-09-15
+
+### Other
+
+- Add support arm64e-apple-darwin ([#1207](https://github.com/rust-lang/cc-rs/pull/1207))
+
+## [1.1.18](https://github.com/rust-lang/cc-rs/compare/cc-v1.1.17...cc-v1.1.18) - 2024-09-07
+
+### Other
+- Fixed unsoundness in `StderrForwarder::forward_available` ([#1203](https://github.com/rust-lang/cc-rs/pull/1203))
+
+## [1.1.17](https://github.com/rust-lang/cc-rs/compare/cc-v1.1.16...cc-v1.1.17) - 2024-09-06
+
+### Fixed
+- fix finding toolchains when invoked by msbuild ([#1201](https://github.com/rust-lang/cc-rs/pull/1201))
+
+## [1.1.16](https://github.com/rust-lang/cc-rs/compare/cc-v1.1.15...cc-v1.1.16) - 2024-09-04
+
+### Other
+- Treat VxWorks wr-cc as a Gnu compiler ([#1198](https://github.com/rust-lang/cc-rs/pull/1198))
+
+## [1.1.15](https://github.com/rust-lang/cc-rs/compare/cc-v1.1.14...cc-v1.1.15) - 2024-08-26
+
+### Other
+- Add -mfloat-abi=hard as a default argument when using any arm/thumb-none-eabihf target ([#1194](https://github.com/rust-lang/cc-rs/pull/1194))
+
+## [1.1.14](https://github.com/rust-lang/cc-rs/compare/cc-v1.1.13...cc-v1.1.14) - 2024-08-23
+
+### Other
+- allow finding tools from path if VisualStudioDir is set
+
+## [1.1.13](https://github.com/rust-lang/cc-rs/compare/cc-v1.1.12...cc-v1.1.13) - 2024-08-16
+
+### Other
+- Fix detect family: should detect emscripten as clang, closes [#1185](https://github.com/rust-lang/cc-rs/pull/1185) ([#1186](https://github.com/rust-lang/cc-rs/pull/1186))
+
+## [1.1.12](https://github.com/rust-lang/cc-rs/compare/cc-v1.1.11...cc-v1.1.12) - 2024-08-15
+
+### Other
+- improve docs ([#1183](https://github.com/rust-lang/cc-rs/pull/1183))
+
+## [1.1.11](https://github.com/rust-lang/cc-rs/compare/cc-v1.1.10...cc-v1.1.11) - 2024-08-14
+
+### Other
+- Add support for parsing shell encoded `*FLAGS` ([#1181](https://github.com/rust-lang/cc-rs/pull/1181))
+- Replace vector of tuples with BTreeMap which already is sorted and free of duplicates ([#1177](https://github.com/rust-lang/cc-rs/pull/1177))
+
+## [1.1.10](https://github.com/rust-lang/cc-rs/compare/cc-v1.1.9...cc-v1.1.10) - 2024-08-11
+
+### Other
+- Remap Windows targets triples to their LLVM counterparts ([#1176](https://github.com/rust-lang/cc-rs/pull/1176))
+
+## [1.1.9](https://github.com/rust-lang/cc-rs/compare/cc-v1.1.8...cc-v1.1.9) - 2024-08-11
+
+### Other
+- Add custom CC wrapper to the wrapper whitelist ([#1175](https://github.com/rust-lang/cc-rs/pull/1175))
+
+## [1.1.8](https://github.com/rust-lang/cc-rs/compare/cc-v1.1.7...cc-v1.1.8) - 2024-08-06
+
+### Other
+- Fix broken link in docs.rs ([#1173](https://github.com/rust-lang/cc-rs/pull/1173))
+
+## [1.1.7](https://github.com/rust-lang/cc-rs/compare/cc-v1.1.6...cc-v1.1.7) - 2024-07-29
+
+### Other
+- add `.objects` ([#1166](https://github.com/rust-lang/cc-rs/pull/1166))
+
+## [1.1.6](https://github.com/rust-lang/cc-rs/compare/cc-v1.1.5...cc-v1.1.6) - 2024-07-19
+
+### Other
+- Clippy fixes ([#1163](https://github.com/rust-lang/cc-rs/pull/1163))
+
+## [1.1.5](https://github.com/rust-lang/cc-rs/compare/cc-v1.1.4...cc-v1.1.5) - 2024-07-15
+
+### Other
+- Fix cyclic compilation: Use vendored once_cell ([#1154](https://github.com/rust-lang/cc-rs/pull/1154))
+
+## [1.1.4](https://github.com/rust-lang/cc-rs/compare/cc-v1.1.3...cc-v1.1.4) - 2024-07-14
+
+### Other
+- Support compiling on wasm targets (Supersede [#1068](https://github.com/rust-lang/cc-rs/pull/1068)) ([#1160](https://github.com/rust-lang/cc-rs/pull/1160))
+
+## [1.1.3](https://github.com/rust-lang/cc-rs/compare/cc-v1.1.2...cc-v1.1.3) - 2024-07-14
+
+### Other
+- Reduce msrv to 1.63 ([#1158](https://github.com/rust-lang/cc-rs/pull/1158))
+- Revert "Use raw-dylib for windows-sys ([#1137](https://github.com/rust-lang/cc-rs/pull/1137))" ([#1157](https://github.com/rust-lang/cc-rs/pull/1157))
+- Fix typos ([#1152](https://github.com/rust-lang/cc-rs/pull/1152))
+- Fix `doc_lazy_continuation` lints ([#1153](https://github.com/rust-lang/cc-rs/pull/1153))
+
+## [1.1.2](https://github.com/rust-lang/cc-rs/compare/cc-v1.1.1...cc-v1.1.2) - 2024-07-12
+
+### Other
+- Add empty `jobserver` feature. ([#1150](https://github.com/rust-lang/cc-rs/pull/1150))
+
+## [1.1.1](https://github.com/rust-lang/cc-rs/compare/cc-v1.1.0...cc-v1.1.1) - 2024-07-12
+
+### Other
+- Fix is_flag_supported not respecting emit_rerun_if_env_changed ([#1147](https://github.com/rust-lang/cc-rs/pull/1147)) ([#1148](https://github.com/rust-lang/cc-rs/pull/1148))
+
+## [1.1.0](https://github.com/rust-lang/cc-rs/compare/cc-v1.0.106...cc-v1.1.0) - 2024-07-08
+
+### Added
+- add cargo_output to eliminate last vestiges of stdout pollution ([#1141](https://github.com/rust-lang/cc-rs/pull/1141))
+
+## [1.0.106](https://github.com/rust-lang/cc-rs/compare/cc-v1.0.105...cc-v1.0.106) - 2024-07-08
+
+### Other
+- Drop support for Visual Studio 12 (2013) ([#1046](https://github.com/rust-lang/cc-rs/pull/1046))
+- Use raw-dylib for windows-sys ([#1137](https://github.com/rust-lang/cc-rs/pull/1137))
+- Bump msrv to 1.67 ([#1143](https://github.com/rust-lang/cc-rs/pull/1143))
+- Bump msrv to 1.65 ([#1140](https://github.com/rust-lang/cc-rs/pull/1140))
+- Fix clippy warnings ([#1138](https://github.com/rust-lang/cc-rs/pull/1138))
+
+## [1.0.105](https://github.com/rust-lang/cc-rs/compare/cc-v1.0.104...cc-v1.0.105) - 2024-07-07
+
+### Other
+- Regenerate windows sys bindings ([#1132](https://github.com/rust-lang/cc-rs/pull/1132))
+- Fix generate-windows-sys-bindings ([#1133](https://github.com/rust-lang/cc-rs/pull/1133))
+- Fix gen-windows-sys-binding ([#1130](https://github.com/rust-lang/cc-rs/pull/1130))
+- Fix gen-windows-sys-binding ([#1127](https://github.com/rust-lang/cc-rs/pull/1127))
+- Update windows-bindgen requirement from 0.57 to 0.58 ([#1123](https://github.com/rust-lang/cc-rs/pull/1123))
+
+## [1.0.104](https://github.com/rust-lang/cc-rs/compare/cc-v1.0.103...cc-v1.0.104) - 2024-07-01
+
+### Other
+- Fixed link break about compile-time-requirements ([#1118](https://github.com/rust-lang/cc-rs/pull/1118))
+
+## [1.0.103](https://github.com/rust-lang/cc-rs/compare/cc-v1.0.102...cc-v1.0.103) - 2024-06-30
+
+### Other
+- Fix compilation for wasm: env WASI_SYSROOT should be optional ([#1114](https://github.com/rust-lang/cc-rs/pull/1114))
+
+## [1.0.102](https://github.com/rust-lang/cc-rs/compare/cc-v1.0.101...cc-v1.0.102) - 2024-06-29
+
+### Other
+- Fix invalid wasi targets compatibility ([#1105](https://github.com/rust-lang/cc-rs/pull/1105))
+- Speedup regenerate-target-info and regenerate-windows-sys ([#1110](https://github.com/rust-lang/cc-rs/pull/1110))
+
+## [1.0.101](https://github.com/rust-lang/cc-rs/compare/cc-v1.0.100...cc-v1.0.101) - 2024-06-25
+
+### Other
+- Use `Build::getenv` instead of `env::var*` in anywhere that makes sense ([#1103](https://github.com/rust-lang/cc-rs/pull/1103))
+
+## [1.0.100](https://github.com/rust-lang/cc-rs/compare/cc-v1.0.99...cc-v1.0.100) - 2024-06-23
+
+### Other
+- Update publish.yml to use release-plz ([#1101](https://github.com/rust-lang/cc-rs/pull/1101))
+- Accept `OsStr` instead of `str` for flags ([#1100](https://github.com/rust-lang/cc-rs/pull/1100))
+- Use `dep:` syntax to avoid implicit features. ([#1099](https://github.com/rust-lang/cc-rs/pull/1099))
+- Minor clippy fixes. ([#1098](https://github.com/rust-lang/cc-rs/pull/1098))
+- Fix WASI compilation for C++ ([#1083](https://github.com/rust-lang/cc-rs/pull/1083))
+- Regenerate windows sys bindings ([#1096](https://github.com/rust-lang/cc-rs/pull/1096))
+- Rename regenerate-windows-sys to regenerate-windows-sys.yml ([#1095](https://github.com/rust-lang/cc-rs/pull/1095))
+- Create regenerate-windows-sys.yml ([#1094](https://github.com/rust-lang/cc-rs/pull/1094))
+- Update windows-bindgen requirement from 0.56 to 0.57 ([#1091](https://github.com/rust-lang/cc-rs/pull/1091))
+- Eagerly close tempfile to fix [#1082](https://github.com/rust-lang/cc-rs/pull/1082) ([#1087](https://github.com/rust-lang/cc-rs/pull/1087))
+- Output msvc.exe in the output directory ([#1090](https://github.com/rust-lang/cc-rs/pull/1090))
+- Fix clippy warnings on Windows ([#1088](https://github.com/rust-lang/cc-rs/pull/1088))
+- Don't try to free DLL on drop ([#1089](https://github.com/rust-lang/cc-rs/pull/1089))
+- Fix panic safety issue in StderrForwarder ([#1079](https://github.com/rust-lang/cc-rs/pull/1079))
diff -Nru rustc-1.85.0+dfsg3/vendor/cc-1.1.22/Cargo.lock rustc-1.85.1+dfsg1/vendor/cc-1.1.22/Cargo.lock
--- rustc-1.85.0+dfsg3/vendor/cc-1.1.22/Cargo.lock 1970-01-01 00:00:00.000000000 +0000
+++ rustc-1.85.1+dfsg1/vendor/cc-1.1.22/Cargo.lock 2025-03-15 16:27:19.000000000 +0000
@@ -0,0 +1,182 @@
+# This file is automatically @generated by Cargo.
+# It is not intended for manual editing.
+version = 3
+
+[[package]]
+name = "bitflags"
+version = "2.6.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "b048fb63fd8b5923fc5aa7b340d8e156aec7ec02f0c78fa8a6ddc2613f6f71de"
+
+[[package]]
+name = "cc"
+version = "1.1.22"
+dependencies = [
+ "jobserver",
+ "libc",
+ "shlex",
+ "tempfile",
+]
+
+[[package]]
+name = "cfg-if"
+version = "1.0.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd"
+
+[[package]]
+name = "errno"
+version = "0.3.9"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "534c5cf6194dfab3db3242765c03bbe257cf92f22b38f6bc0c58d59108a820ba"
+dependencies = [
+ "libc",
+ "windows-sys 0.52.0",
+]
+
+[[package]]
+name = "fastrand"
+version = "2.1.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "e8c02a5121d4ea3eb16a80748c74f5549a5665e4c21333c6098f283870fbdea6"
+
+[[package]]
+name = "jobserver"
+version = "0.1.32"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "48d1dbcbbeb6a7fec7e059840aa538bd62aaccf972c7346c4d9d2059312853d0"
+dependencies = [
+ "libc",
+]
+
+[[package]]
+name = "libc"
+version = "0.2.159"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "561d97a539a36e26a9a5fad1ea11a3039a67714694aaa379433e580854bc3dc5"
+
+[[package]]
+name = "linux-raw-sys"
+version = "0.4.14"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "78b3ae25bc7c8c38cec158d1f2757ee79e9b3740fbc7ccf0e59e4b08d793fa89"
+
+[[package]]
+name = "once_cell"
+version = "1.19.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "3fdb12b2476b595f9358c5161aa467c2438859caa136dec86c26fdd2efe17b92"
+
+[[package]]
+name = "rustix"
+version = "0.38.37"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "8acb788b847c24f28525660c4d7758620a7210875711f79e7f663cc152726811"
+dependencies = [
+ "bitflags",
+ "errno",
+ "libc",
+ "linux-raw-sys",
+ "windows-sys 0.52.0",
+]
+
+[[package]]
+name = "shlex"
+version = "1.3.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "0fda2ff0d084019ba4d7c6f371c95d8fd75ce3524c3cb8fb653a3023f6323e64"
+
+[[package]]
+name = "tempfile"
+version = "3.12.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "04cbcdd0c794ebb0d4cf35e88edd2f7d2c4c3e9a5a6dab322839b321c6a87a64"
+dependencies = [
+ "cfg-if",
+ "fastrand",
+ "once_cell",
+ "rustix",
+ "windows-sys 0.59.0",
+]
+
+[[package]]
+name = "windows-sys"
+version = "0.52.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "282be5f36a8ce781fad8c8ae18fa3f9beff57ec1b52cb3de0789201425d9a33d"
+dependencies = [
+ "windows-targets",
+]
+
+[[package]]
+name = "windows-sys"
+version = "0.59.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "1e38bc4d79ed67fd075bcc251a1c39b32a1776bbe92e5bef1f0bf1f8c531853b"
+dependencies = [
+ "windows-targets",
+]
+
+[[package]]
+name = "windows-targets"
+version = "0.52.6"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "9b724f72796e036ab90c1021d4780d4d3d648aca59e491e6b98e725b84e99973"
+dependencies = [
+ "windows_aarch64_gnullvm",
+ "windows_aarch64_msvc",
+ "windows_i686_gnu",
+ "windows_i686_gnullvm",
+ "windows_i686_msvc",
+ "windows_x86_64_gnu",
+ "windows_x86_64_gnullvm",
+ "windows_x86_64_msvc",
+]
+
+[[package]]
+name = "windows_aarch64_gnullvm"
+version = "0.52.6"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "32a4622180e7a0ec044bb555404c800bc9fd9ec262ec147edd5989ccd0c02cd3"
+
+[[package]]
+name = "windows_aarch64_msvc"
+version = "0.52.6"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "09ec2a7bb152e2252b53fa7803150007879548bc709c039df7627cabbd05d469"
+
+[[package]]
+name = "windows_i686_gnu"
+version = "0.52.6"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "8e9b5ad5ab802e97eb8e295ac6720e509ee4c243f69d781394014ebfe8bbfa0b"
+
+[[package]]
+name = "windows_i686_gnullvm"
+version = "0.52.6"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "0eee52d38c090b3caa76c563b86c3a4bd71ef1a819287c19d586d7334ae8ed66"
+
+[[package]]
+name = "windows_i686_msvc"
+version = "0.52.6"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "240948bc05c5e7c6dabba28bf89d89ffce3e303022809e73deaefe4f6ec56c66"
+
+[[package]]
+name = "windows_x86_64_gnu"
+version = "0.52.6"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "147a5c80aabfbf0c7d901cb5895d1de30ef2907eb21fbbab29ca94c5b08b1a78"
+
+[[package]]
+name = "windows_x86_64_gnullvm"
+version = "0.52.6"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "24d5b23dc417412679681396f2b49f3de8c1473deb516bd34410872eff51ed0d"
+
+[[package]]
+name = "windows_x86_64_msvc"
+version = "0.52.6"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "589f6da84c646204747d1270a2a5661ea66ed1cced2631d546fdfb155959f9ec"
diff -Nru rustc-1.85.0+dfsg3/vendor/cc-1.1.22/Cargo.toml rustc-1.85.1+dfsg1/vendor/cc-1.1.22/Cargo.toml
--- rustc-1.85.0+dfsg3/vendor/cc-1.1.22/Cargo.toml 1970-01-01 00:00:00.000000000 +0000
+++ rustc-1.85.1+dfsg1/vendor/cc-1.1.22/Cargo.toml 2025-03-15 16:27:19.000000000 +0000
@@ -0,0 +1,66 @@
+# THIS FILE IS AUTOMATICALLY GENERATED BY CARGO
+#
+# When uploading crates to the registry Cargo will automatically
+# "normalize" Cargo.toml files for maximal compatibility
+# with all versions of Cargo and also rewrite `path` dependencies
+# to registry (e.g., crates.io) dependencies.
+#
+# If you are reading this file be aware that the original Cargo.toml
+# will likely look very different (and much more reasonable).
+# See Cargo.toml.orig for the original contents.
+
+[package]
+edition = "2018"
+rust-version = "1.63"
+name = "cc"
+version = "1.1.22"
+authors = ["Alex Crichton "]
+build = false
+exclude = [
+ "/.github",
+ "tests",
+ "src/bin",
+]
+autobins = false
+autoexamples = false
+autotests = false
+autobenches = false
+description = """
+A build-time dependency for Cargo build scripts to assist in invoking the native
+C compiler to compile native C code into a static archive to be linked into Rust
+code.
+"""
+homepage = "https://github.com/rust-lang/cc-rs"
+documentation = "https://docs.rs/cc"
+readme = "README.md"
+keywords = ["build-dependencies"]
+categories = ["development-tools::build-utils"]
+license = "MIT OR Apache-2.0"
+repository = "https://github.com/rust-lang/cc-rs"
+
+[lib]
+name = "cc"
+path = "src/lib.rs"
+
+[dependencies.jobserver]
+version = "0.1.30"
+optional = true
+default-features = false
+
+[dependencies.shlex]
+version = "1.3.0"
+
+[dev-dependencies.tempfile]
+version = "3"
+
+[features]
+jobserver = []
+parallel = [
+ "dep:libc",
+ "dep:jobserver",
+]
+
+[target."cfg(unix)".dependencies.libc]
+version = "0.2.62"
+optional = true
+default-features = false
diff -Nru rustc-1.85.0+dfsg3/vendor/cc-1.1.22/LICENSE-APACHE rustc-1.85.1+dfsg1/vendor/cc-1.1.22/LICENSE-APACHE
--- rustc-1.85.0+dfsg3/vendor/cc-1.1.22/LICENSE-APACHE 1970-01-01 00:00:00.000000000 +0000
+++ rustc-1.85.1+dfsg1/vendor/cc-1.1.22/LICENSE-APACHE 2025-03-15 16:27:19.000000000 +0000
@@ -0,0 +1,201 @@
+ Apache License
+ Version 2.0, January 2004
+ http://www.apache.org/licenses/
+
+TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
+
+1. Definitions.
+
+ "License" shall mean the terms and conditions for use, reproduction,
+ and distribution as defined by Sections 1 through 9 of this document.
+
+ "Licensor" shall mean the copyright owner or entity authorized by
+ the copyright owner that is granting the License.
+
+ "Legal Entity" shall mean the union of the acting entity and all
+ other entities that control, are controlled by, or are under common
+ control with that entity. For the purposes of this definition,
+ "control" means (i) the power, direct or indirect, to cause the
+ direction or management of such entity, whether by contract or
+ otherwise, or (ii) ownership of fifty percent (50%) or more of the
+ outstanding shares, or (iii) beneficial ownership of such entity.
+
+ "You" (or "Your") shall mean an individual or Legal Entity
+ exercising permissions granted by this License.
+
+ "Source" form shall mean the preferred form for making modifications,
+ including but not limited to software source code, documentation
+ source, and configuration files.
+
+ "Object" form shall mean any form resulting from mechanical
+ transformation or translation of a Source form, including but
+ not limited to compiled object code, generated documentation,
+ and conversions to other media types.
+
+ "Work" shall mean the work of authorship, whether in Source or
+ Object form, made available under the License, as indicated by a
+ copyright notice that is included in or attached to the work
+ (an example is provided in the Appendix below).
+
+ "Derivative Works" shall mean any work, whether in Source or Object
+ form, that is based on (or derived from) the Work and for which the
+ editorial revisions, annotations, elaborations, or other modifications
+ represent, as a whole, an original work of authorship. For the purposes
+ of this License, Derivative Works shall not include works that remain
+ separable from, or merely link (or bind by name) to the interfaces of,
+ the Work and Derivative Works thereof.
+
+ "Contribution" shall mean any work of authorship, including
+ the original version of the Work and any modifications or additions
+ to that Work or Derivative Works thereof, that is intentionally
+ submitted to Licensor for inclusion in the Work by the copyright owner
+ or by an individual or Legal Entity authorized to submit on behalf of
+ the copyright owner. For the purposes of this definition, "submitted"
+ means any form of electronic, verbal, or written communication sent
+ to the Licensor or its representatives, including but not limited to
+ communication on electronic mailing lists, source code control systems,
+ and issue tracking systems that are managed by, or on behalf of, the
+ Licensor for the purpose of discussing and improving the Work, but
+ excluding communication that is conspicuously marked or otherwise
+ designated in writing by the copyright owner as "Not a Contribution."
+
+ "Contributor" shall mean Licensor and any individual or Legal Entity
+ on behalf of whom a Contribution has been received by Licensor and
+ subsequently incorporated within the Work.
+
+2. Grant of Copyright License. Subject to the terms and conditions of
+ this License, each Contributor hereby grants to You a perpetual,
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+ copyright license to reproduce, prepare Derivative Works of,
+ publicly display, publicly perform, sublicense, and distribute the
+ Work and such Derivative Works in Source or Object form.
+
+3. Grant of Patent License. Subject to the terms and conditions of
+ this License, each Contributor hereby grants to You a perpetual,
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+ (except as stated in this section) patent license to make, have made,
+ use, offer to sell, sell, import, and otherwise transfer the Work,
+ where such license applies only to those patent claims licensable
+ by such Contributor that are necessarily infringed by their
+ Contribution(s) alone or by combination of their Contribution(s)
+ with the Work to which such Contribution(s) was submitted. If You
+ institute patent litigation against any entity (including a
+ cross-claim or counterclaim in a lawsuit) alleging that the Work
+ or a Contribution incorporated within the Work constitutes direct
+ or contributory patent infringement, then any patent licenses
+ granted to You under this License for that Work shall terminate
+ as of the date such litigation is filed.
+
+4. Redistribution. You may reproduce and distribute copies of the
+ Work or Derivative Works thereof in any medium, with or without
+ modifications, and in Source or Object form, provided that You
+ meet the following conditions:
+
+ (a) You must give any other recipients of the Work or
+ Derivative Works a copy of this License; and
+
+ (b) You must cause any modified files to carry prominent notices
+ stating that You changed the files; and
+
+ (c) You must retain, in the Source form of any Derivative Works
+ that You distribute, all copyright, patent, trademark, and
+ attribution notices from the Source form of the Work,
+ excluding those notices that do not pertain to any part of
+ the Derivative Works; and
+
+ (d) If the Work includes a "NOTICE" text file as part of its
+ distribution, then any Derivative Works that You distribute must
+ include a readable copy of the attribution notices contained
+ within such NOTICE file, excluding those notices that do not
+ pertain to any part of the Derivative Works, in at least one
+ of the following places: within a NOTICE text file distributed
+ as part of the Derivative Works; within the Source form or
+ documentation, if provided along with the Derivative Works; or,
+ within a display generated by the Derivative Works, if and
+ wherever such third-party notices normally appear. The contents
+ of the NOTICE file are for informational purposes only and
+ do not modify the License. You may add Your own attribution
+ notices within Derivative Works that You distribute, alongside
+ or as an addendum to the NOTICE text from the Work, provided
+ that such additional attribution notices cannot be construed
+ as modifying the License.
+
+ You may add Your own copyright statement to Your modifications and
+ may provide additional or different license terms and conditions
+ for use, reproduction, or distribution of Your modifications, or
+ for any such Derivative Works as a whole, provided Your use,
+ reproduction, and distribution of the Work otherwise complies with
+ the conditions stated in this License.
+
+5. Submission of Contributions. Unless You explicitly state otherwise,
+ any Contribution intentionally submitted for inclusion in the Work
+ by You to the Licensor shall be under the terms and conditions of
+ this License, without any additional terms or conditions.
+ Notwithstanding the above, nothing herein shall supersede or modify
+ the terms of any separate license agreement you may have executed
+ with Licensor regarding such Contributions.
+
+6. Trademarks. This License does not grant permission to use the trade
+ names, trademarks, service marks, or product names of the Licensor,
+ except as required for reasonable and customary use in describing the
+ origin of the Work and reproducing the content of the NOTICE file.
+
+7. Disclaimer of Warranty. Unless required by applicable law or
+ agreed to in writing, Licensor provides the Work (and each
+ Contributor provides its Contributions) on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+ implied, including, without limitation, any warranties or conditions
+ of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
+ PARTICULAR PURPOSE. You are solely responsible for determining the
+ appropriateness of using or redistributing the Work and assume any
+ risks associated with Your exercise of permissions under this License.
+
+8. Limitation of Liability. In no event and under no legal theory,
+ whether in tort (including negligence), contract, or otherwise,
+ unless required by applicable law (such as deliberate and grossly
+ negligent acts) or agreed to in writing, shall any Contributor be
+ liable to You for damages, including any direct, indirect, special,
+ incidental, or consequential damages of any character arising as a
+ result of this License or out of the use or inability to use the
+ Work (including but not limited to damages for loss of goodwill,
+ work stoppage, computer failure or malfunction, or any and all
+ other commercial damages or losses), even if such Contributor
+ has been advised of the possibility of such damages.
+
+9. Accepting Warranty or Additional Liability. While redistributing
+ the Work or Derivative Works thereof, You may choose to offer,
+ and charge a fee for, acceptance of support, warranty, indemnity,
+ or other liability obligations and/or rights consistent with this
+ License. However, in accepting such obligations, You may act only
+ on Your own behalf and on Your sole responsibility, not on behalf
+ of any other Contributor, and only if You agree to indemnify,
+ defend, and hold each Contributor harmless for any liability
+ incurred by, or claims asserted against, such Contributor by reason
+ of your accepting any such warranty or additional liability.
+
+END OF TERMS AND CONDITIONS
+
+APPENDIX: How to apply the Apache License to your work.
+
+ To apply the Apache License to your work, attach the following
+ boilerplate notice, with the fields enclosed by brackets "[]"
+ replaced with your own identifying information. (Don't include
+ the brackets!) The text should be enclosed in the appropriate
+ comment syntax for the file format. We also recommend that a
+ file or class name and description of purpose be included on the
+ same "printed page" as the copyright notice for easier
+ identification within third-party archives.
+
+Copyright [yyyy] [name of copyright owner]
+
+Licensed under the Apache License, Version 2.0 (the "License");
+you may not use this file except in compliance with the License.
+You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
diff -Nru rustc-1.85.0+dfsg3/vendor/cc-1.1.22/LICENSE-MIT rustc-1.85.1+dfsg1/vendor/cc-1.1.22/LICENSE-MIT
--- rustc-1.85.0+dfsg3/vendor/cc-1.1.22/LICENSE-MIT 1970-01-01 00:00:00.000000000 +0000
+++ rustc-1.85.1+dfsg1/vendor/cc-1.1.22/LICENSE-MIT 2025-03-15 16:27:19.000000000 +0000
@@ -0,0 +1,25 @@
+Copyright (c) 2014 Alex Crichton
+
+Permission is hereby granted, free of charge, to any
+person obtaining a copy of this software and associated
+documentation files (the "Software"), to deal in the
+Software without restriction, including without
+limitation the rights to use, copy, modify, merge,
+publish, distribute, sublicense, and/or sell copies of
+the Software, and to permit persons to whom the Software
+is furnished to do so, subject to the following
+conditions:
+
+The above copyright notice and this permission notice
+shall be included in all copies or substantial portions
+of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF
+ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED
+TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
+PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT
+SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR
+IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+DEALINGS IN THE SOFTWARE.
diff -Nru rustc-1.85.0+dfsg3/vendor/cc-1.1.22/README.md rustc-1.85.1+dfsg1/vendor/cc-1.1.22/README.md
--- rustc-1.85.0+dfsg3/vendor/cc-1.1.22/README.md 1970-01-01 00:00:00.000000000 +0000
+++ rustc-1.85.1+dfsg1/vendor/cc-1.1.22/README.md 2025-03-15 16:27:19.000000000 +0000
@@ -0,0 +1,27 @@
+# cc-rs
+
+A library for [Cargo build scripts](https://doc.rust-lang.org/cargo/reference/build-scripts.html)
+to compile a set of C/C++/assembly/CUDA files into a static archive for Cargo
+to link into the crate being built. This crate does not compile code itself;
+it calls out to the default compiler for the platform. This crate will
+automatically detect situations such as cross compilation and
+various environment variables and will build code appropriately.
+
+Refer to the [documentation](https://docs.rs/cc) for detailed usage instructions.
+
+## License
+
+This project is licensed under either of
+
+ * Apache License, Version 2.0, ([LICENSE-APACHE](LICENSE-APACHE) or
+ https://www.apache.org/licenses/LICENSE-2.0)
+ * MIT license ([LICENSE-MIT](LICENSE-MIT) or
+ https://opensource.org/licenses/MIT)
+
+at your option.
+
+### Contribution
+
+Unless you explicitly state otherwise, any contribution intentionally submitted
+for inclusion in cc-rs by you, as defined in the Apache-2.0 license, shall be
+dual licensed as above, without any additional terms or conditions.
diff -Nru rustc-1.85.0+dfsg3/vendor/cc-1.1.22/clippy.toml rustc-1.85.1+dfsg1/vendor/cc-1.1.22/clippy.toml
--- rustc-1.85.0+dfsg3/vendor/cc-1.1.22/clippy.toml 1970-01-01 00:00:00.000000000 +0000
+++ rustc-1.85.1+dfsg1/vendor/cc-1.1.22/clippy.toml 2025-03-15 16:27:19.000000000 +0000
@@ -0,0 +1,5 @@
+disallowed-methods = [
+ { path = "std::env::var_os", reason = "Please use Build::getenv" },
+ { path = "std::env::var", reason = "Please use Build::getenv" },
+]
+doc-valid-idents = ["AppleClang", "OpenBSD", ".."]
diff -Nru rustc-1.85.0+dfsg3/vendor/cc-1.1.22/src/command_helpers.rs rustc-1.85.1+dfsg1/vendor/cc-1.1.22/src/command_helpers.rs
--- rustc-1.85.0+dfsg3/vendor/cc-1.1.22/src/command_helpers.rs 1970-01-01 00:00:00.000000000 +0000
+++ rustc-1.85.1+dfsg1/vendor/cc-1.1.22/src/command_helpers.rs 2025-03-15 16:27:19.000000000 +0000
@@ -0,0 +1,488 @@
+//! Miscellaneous helpers for running commands
+
+use std::{
+ collections::hash_map,
+ ffi::OsString,
+ fmt::Display,
+ fs,
+ hash::Hasher,
+ io::{self, Read, Write},
+ path::Path,
+ process::{Child, ChildStderr, Command, Stdio},
+ sync::{
+ atomic::{AtomicBool, Ordering},
+ Arc,
+ },
+};
+
+use crate::{Error, ErrorKind, Object};
+
+#[derive(Clone, Debug)]
+pub(crate) struct CargoOutput {
+ pub(crate) metadata: bool,
+ pub(crate) warnings: bool,
+ pub(crate) debug: bool,
+ pub(crate) output: OutputKind,
+ checked_dbg_var: Arc,
+}
+
+/// Different strategies for handling compiler output (to stdout)
+#[derive(Clone, Debug)]
+pub(crate) enum OutputKind {
+ /// Forward the output to this process' stdout ([`Stdio::inherit()`])
+ Forward,
+ /// Discard the output ([`Stdio::null()`])
+ Discard,
+ /// Capture the result (`[Stdio::piped()`])
+ Capture,
+}
+
+impl CargoOutput {
+ pub(crate) fn new() -> Self {
+ #[allow(clippy::disallowed_methods)]
+ Self {
+ metadata: true,
+ warnings: true,
+ output: OutputKind::Forward,
+ debug: std::env::var_os("CC_ENABLE_DEBUG_OUTPUT").is_some(),
+ checked_dbg_var: Arc::new(AtomicBool::new(false)),
+ }
+ }
+
+ pub(crate) fn print_metadata(&self, s: &dyn Display) {
+ if self.metadata {
+ println!("{}", s);
+ }
+ }
+
+ pub(crate) fn print_warning(&self, arg: &dyn Display) {
+ if self.warnings {
+ println!("cargo:warning={}", arg);
+ }
+ }
+
+ pub(crate) fn print_debug(&self, arg: &dyn Display) {
+ if self.metadata && !self.checked_dbg_var.load(Ordering::Relaxed) {
+ self.checked_dbg_var.store(true, Ordering::Relaxed);
+ println!("cargo:rerun-if-env-changed=CC_ENABLE_DEBUG_OUTPUT");
+ }
+ if self.debug {
+ println!("{}", arg);
+ }
+ }
+
+ fn stdio_for_warnings(&self) -> Stdio {
+ if self.warnings {
+ Stdio::piped()
+ } else {
+ Stdio::null()
+ }
+ }
+
+ fn stdio_for_output(&self) -> Stdio {
+ match self.output {
+ OutputKind::Capture => Stdio::piped(),
+ OutputKind::Forward => Stdio::inherit(),
+ OutputKind::Discard => Stdio::null(),
+ }
+ }
+}
+
+pub(crate) struct StderrForwarder {
+ inner: Option<(ChildStderr, Vec)>,
+ #[cfg(feature = "parallel")]
+ is_non_blocking: bool,
+ #[cfg(feature = "parallel")]
+ bytes_available_failed: bool,
+ /// number of bytes buffered in inner
+ bytes_buffered: usize,
+}
+
+const MIN_BUFFER_CAPACITY: usize = 100;
+
+impl StderrForwarder {
+ pub(crate) fn new(child: &mut Child) -> Self {
+ Self {
+ inner: child
+ .stderr
+ .take()
+ .map(|stderr| (stderr, Vec::with_capacity(MIN_BUFFER_CAPACITY))),
+ bytes_buffered: 0,
+ #[cfg(feature = "parallel")]
+ is_non_blocking: false,
+ #[cfg(feature = "parallel")]
+ bytes_available_failed: false,
+ }
+ }
+
+ fn forward_available(&mut self) -> bool {
+ if let Some((stderr, buffer)) = self.inner.as_mut() {
+ loop {
+ // For non-blocking we check to see if there is data available, so we should try to
+ // read at least that much. For blocking, always read at least the minimum amount.
+ #[cfg(not(feature = "parallel"))]
+ let to_reserve = MIN_BUFFER_CAPACITY;
+ #[cfg(feature = "parallel")]
+ let to_reserve = if self.is_non_blocking && !self.bytes_available_failed {
+ match crate::parallel::stderr::bytes_available(stderr) {
+ #[cfg(windows)]
+ Ok(0) => break false,
+ #[cfg(unix)]
+ Ok(0) => {
+ // On Unix, depending on the implementation, we may sometimes get 0 in a
+ // loop (either there is data available or the pipe is broken), so
+ // continue with the non-blocking read anyway.
+ MIN_BUFFER_CAPACITY
+ }
+ #[cfg(windows)]
+ Err(_) => {
+ // On Windows, if we get an error then the pipe is broken, so flush
+ // the buffer and bail.
+ if !buffer.is_empty() {
+ write_warning(&buffer[..]);
+ }
+ self.inner = None;
+ break true;
+ }
+ #[cfg(unix)]
+ Err(_) => {
+ // On Unix, depending on the implementation, we may get spurious
+ // errors so make a note not to use bytes_available again and try
+ // the non-blocking read anyway.
+ self.bytes_available_failed = true;
+ MIN_BUFFER_CAPACITY
+ }
+ #[cfg(target_family = "wasm")]
+ Err(_) => panic!("bytes_available should always succeed on wasm"),
+ Ok(bytes_available) => MIN_BUFFER_CAPACITY.max(bytes_available),
+ }
+ } else {
+ MIN_BUFFER_CAPACITY
+ };
+ if self.bytes_buffered + to_reserve > buffer.len() {
+ buffer.resize(self.bytes_buffered + to_reserve, 0);
+ }
+
+ match stderr.read(&mut buffer[self.bytes_buffered..]) {
+ Err(err) if err.kind() == std::io::ErrorKind::WouldBlock => {
+ // No data currently, yield back.
+ break false;
+ }
+ Err(err) if err.kind() == std::io::ErrorKind::Interrupted => {
+ // Interrupted, try again.
+ continue;
+ }
+ Ok(bytes_read) if bytes_read != 0 => {
+ self.bytes_buffered += bytes_read;
+ let mut consumed = 0;
+ for line in buffer[..self.bytes_buffered].split_inclusive(|&b| b == b'\n') {
+ // Only forward complete lines, leave the rest in the buffer.
+ if let Some((b'\n', line)) = line.split_last() {
+ consumed += line.len() + 1;
+ write_warning(line);
+ }
+ }
+ if consumed > 0 && consumed < self.bytes_buffered {
+ // Remove the consumed bytes from buffer
+ buffer.copy_within(consumed.., 0);
+ }
+ self.bytes_buffered -= consumed;
+ }
+ res => {
+ // End of stream: flush remaining data and bail.
+ if self.bytes_buffered > 0 {
+ write_warning(&buffer[..self.bytes_buffered]);
+ }
+ if let Err(err) = res {
+ write_warning(
+ format!("Failed to read from child stderr: {err}").as_bytes(),
+ );
+ }
+ self.inner.take();
+ break true;
+ }
+ }
+ }
+ } else {
+ true
+ }
+ }
+
+ #[cfg(feature = "parallel")]
+ pub(crate) fn set_non_blocking(&mut self) -> Result<(), Error> {
+ assert!(!self.is_non_blocking);
+
+ #[cfg(unix)]
+ if let Some((stderr, _)) = self.inner.as_ref() {
+ crate::parallel::stderr::set_non_blocking(stderr)?;
+ }
+
+ self.is_non_blocking = true;
+ Ok(())
+ }
+
+ #[cfg(feature = "parallel")]
+ fn forward_all(&mut self) {
+ while !self.forward_available() {}
+ }
+
+ #[cfg(not(feature = "parallel"))]
+ fn forward_all(&mut self) {
+ let forward_result = self.forward_available();
+ assert!(forward_result, "Should have consumed all data");
+ }
+}
+
+fn write_warning(line: &[u8]) {
+ let stdout = io::stdout();
+ let mut stdout = stdout.lock();
+ stdout.write_all(b"cargo:warning=").unwrap();
+ stdout.write_all(line).unwrap();
+ stdout.write_all(b"\n").unwrap();
+}
+
+fn wait_on_child(
+ cmd: &Command,
+ program: &Path,
+ child: &mut Child,
+ cargo_output: &CargoOutput,
+) -> Result<(), Error> {
+ StderrForwarder::new(child).forward_all();
+
+ let status = match child.wait() {
+ Ok(s) => s,
+ Err(e) => {
+ return Err(Error::new(
+ ErrorKind::ToolExecError,
+ format!(
+ "Failed to wait on spawned child process, command {:?} with args {}: {}.",
+ cmd,
+ program.display(),
+ e
+ ),
+ ));
+ }
+ };
+
+ cargo_output.print_debug(&status);
+
+ if status.success() {
+ Ok(())
+ } else {
+ Err(Error::new(
+ ErrorKind::ToolExecError,
+ format!(
+ "Command {:?} with args {} did not execute successfully (status code {}).",
+ cmd,
+ program.display(),
+ status
+ ),
+ ))
+ }
+}
+
+/// Find the destination object path for each file in the input source files,
+/// and store them in the output Object.
+pub(crate) fn objects_from_files(files: &[Arc], dst: &Path) -> Result, Error> {
+ let mut objects = Vec::with_capacity(files.len());
+ for file in files {
+ let basename = file
+ .file_name()
+ .ok_or_else(|| {
+ Error::new(
+ ErrorKind::InvalidArgument,
+ "No file_name for object file path!",
+ )
+ })?
+ .to_string_lossy();
+ let dirname = file
+ .parent()
+ .ok_or_else(|| {
+ Error::new(
+ ErrorKind::InvalidArgument,
+ "No parent for object file path!",
+ )
+ })?
+ .to_string_lossy();
+
+ // Hash the dirname. This should prevent conflicts if we have multiple
+ // object files with the same filename in different subfolders.
+ let mut hasher = hash_map::DefaultHasher::new();
+ hasher.write(dirname.to_string().as_bytes());
+ let obj = dst
+ .join(format!("{:016x}-{}", hasher.finish(), basename))
+ .with_extension("o");
+
+ match obj.parent() {
+ Some(s) => fs::create_dir_all(s)?,
+ None => {
+ return Err(Error::new(
+ ErrorKind::InvalidArgument,
+ "dst is an invalid path with no parent",
+ ));
+ }
+ };
+
+ objects.push(Object::new(file.to_path_buf(), obj));
+ }
+
+ Ok(objects)
+}
+
+pub(crate) fn run(
+ cmd: &mut Command,
+ program: impl AsRef,
+ cargo_output: &CargoOutput,
+) -> Result<(), Error> {
+ let program = program.as_ref();
+
+ let mut child = spawn(cmd, program, cargo_output)?;
+ wait_on_child(cmd, program, &mut child, cargo_output)
+}
+
+pub(crate) fn run_output(
+ cmd: &mut Command,
+ program: impl AsRef,
+ cargo_output: &CargoOutput,
+) -> Result, Error> {
+ let program = program.as_ref();
+
+ // We specifically need the output to be captured, so override default
+ let mut captured_cargo_output = cargo_output.clone();
+ captured_cargo_output.output = OutputKind::Capture;
+ let mut child = spawn(cmd, program, &captured_cargo_output)?;
+
+ let mut stdout = vec![];
+ child
+ .stdout
+ .take()
+ .unwrap()
+ .read_to_end(&mut stdout)
+ .unwrap();
+
+ // Don't care about this output, use the normal settings
+ wait_on_child(cmd, program, &mut child, cargo_output)?;
+
+ Ok(stdout)
+}
+
+pub(crate) fn spawn(
+ cmd: &mut Command,
+ program: &Path,
+ cargo_output: &CargoOutput,
+) -> Result {
+ struct ResetStderr<'cmd>(&'cmd mut Command);
+
+ impl Drop for ResetStderr<'_> {
+ fn drop(&mut self) {
+ // Reset stderr to default to release pipe_writer so that print thread will
+ // not block forever.
+ self.0.stderr(Stdio::inherit());
+ }
+ }
+
+ cargo_output.print_debug(&format_args!("running: {:?}", cmd));
+
+ let cmd = ResetStderr(cmd);
+ let child = cmd
+ .0
+ .stderr(cargo_output.stdio_for_warnings())
+ .stdout(cargo_output.stdio_for_output())
+ .spawn();
+ match child {
+ Ok(child) => Ok(child),
+ Err(ref e) if e.kind() == io::ErrorKind::NotFound => {
+ let extra = if cfg!(windows) {
+ " (see https://docs.rs/cc/latest/cc/#compile-time-requirements \
+for help)"
+ } else {
+ ""
+ };
+ Err(Error::new(
+ ErrorKind::ToolNotFound,
+ format!(
+ "Failed to find tool. Is `{}` installed?{}",
+ program.display(),
+ extra
+ ),
+ ))
+ }
+ Err(e) => Err(Error::new(
+ ErrorKind::ToolExecError,
+ format!(
+ "Command {:?} with args {} failed to start: {:?}",
+ cmd.0,
+ program.display(),
+ e
+ ),
+ )),
+ }
+}
+
+pub(crate) struct CmdAddOutputFileArgs {
+ pub(crate) cuda: bool,
+ pub(crate) is_assembler_msvc: bool,
+ pub(crate) msvc: bool,
+ pub(crate) clang: bool,
+ pub(crate) gnu: bool,
+ pub(crate) is_asm: bool,
+ pub(crate) is_arm: bool,
+}
+
+pub(crate) fn command_add_output_file(cmd: &mut Command, dst: &Path, args: CmdAddOutputFileArgs) {
+ if args.is_assembler_msvc
+ || !(!args.msvc || args.clang || args.gnu || args.cuda || (args.is_asm && args.is_arm))
+ {
+ let mut s = OsString::from("-Fo");
+ s.push(dst);
+ cmd.arg(s);
+ } else {
+ cmd.arg("-o").arg(dst);
+ }
+}
+
+#[cfg(feature = "parallel")]
+pub(crate) fn try_wait_on_child(
+ cmd: &Command,
+ program: &Path,
+ child: &mut Child,
+ stdout: &mut dyn io::Write,
+ stderr_forwarder: &mut StderrForwarder,
+) -> Result