From 44d6cd2344cd636f4ea371d56ae3d27aaa110ad6 Mon Sep 17 00:00:00 2001 From: Alan Somers Date: Thu, 5 Mar 2026 12:46:23 -0700 Subject: [PATCH 01/15] Fix environ on FreeBSD with cdylib targets that use -Wl,--no-undefined . Instead of relying on the linker to find the 'environ' symbol, use dlsym. Fixes #153451 Sponsored by: ConnectWise --- library/std/src/sys/env/unix.rs | 19 ++++++++++++++++++- 1 file changed, 18 insertions(+), 1 deletion(-) diff --git a/library/std/src/sys/env/unix.rs b/library/std/src/sys/env/unix.rs index 66805ce3fa71e..7a19f97b3ad50 100644 --- a/library/std/src/sys/env/unix.rs +++ b/library/std/src/sys/env/unix.rs @@ -38,8 +38,25 @@ pub unsafe fn environ() -> *mut *const *const c_char { unsafe { libc::_NSGetEnviron() as *mut *const *const c_char } } +// On FreeBSD, environ comes from CRT rather than libc +#[cfg(target_os = "freebsd")] +pub unsafe fn environ() -> *mut *const *const c_char { + use crate::sync::LazyLock; + + struct Environ(*mut *const *const c_char); + unsafe impl Send for Environ {} + unsafe impl Sync for Environ {} + + static ENVIRON: LazyLock = LazyLock::new(|| { + Environ(unsafe { + libc::dlsym(libc::RTLD_DEFAULT, c"environ".as_ptr()) as *mut *const *const c_char + }) + }); + ENVIRON.0 +} + // Use the `environ` static which is part of POSIX. -#[cfg(not(target_vendor = "apple"))] +#[cfg(not(any(target_os = "freebsd", target_vendor = "apple")))] pub unsafe fn environ() -> *mut *const *const c_char { unsafe extern "C" { static mut environ: *const *const c_char; From d2e3ab641ac3d4ea2e351724b22d6b9f20021b01 Mon Sep 17 00:00:00 2001 From: joboet Date: Mon, 9 Mar 2026 17:57:43 +0100 Subject: [PATCH 02/15] std: move `sys::pal::os` to `sys::paths` (rename/delete only) --- library/std/src/sys/pal/solid/os.rs | 56 ----------------- library/std/src/sys/pal/teeos/os.rs | 62 ------------------- library/std/src/sys/pal/xous/os.rs | 57 ----------------- library/std/src/sys/pal/zkvm/os.rs | 57 ----------------- .../sys/{pal/hermit/os.rs => paths/hermit.rs} | 0 .../sys/{pal/motor/os.rs => paths/motor.rs} | 0 .../src/sys/{pal/sgx/os.rs => paths/sgx.rs} | 0 .../src/sys/{pal/uefi/os.rs => paths/uefi.rs} | 0 .../src/sys/{pal/unix/os.rs => paths/unix.rs} | 0 .../os.rs => paths/unsupported.rs} | 0 .../src/sys/{pal/wasi/os.rs => paths/wasi.rs} | 0 .../{pal/windows/os.rs => paths/windows.rs} | 0 12 files changed, 232 deletions(-) delete mode 100644 library/std/src/sys/pal/solid/os.rs delete mode 100644 library/std/src/sys/pal/teeos/os.rs delete mode 100644 library/std/src/sys/pal/xous/os.rs delete mode 100644 library/std/src/sys/pal/zkvm/os.rs rename library/std/src/sys/{pal/hermit/os.rs => paths/hermit.rs} (100%) rename library/std/src/sys/{pal/motor/os.rs => paths/motor.rs} (100%) rename library/std/src/sys/{pal/sgx/os.rs => paths/sgx.rs} (100%) rename library/std/src/sys/{pal/uefi/os.rs => paths/uefi.rs} (100%) rename library/std/src/sys/{pal/unix/os.rs => paths/unix.rs} (100%) rename library/std/src/sys/{pal/unsupported/os.rs => paths/unsupported.rs} (100%) rename library/std/src/sys/{pal/wasi/os.rs => paths/wasi.rs} (100%) rename library/std/src/sys/{pal/windows/os.rs => paths/windows.rs} (100%) diff --git a/library/std/src/sys/pal/solid/os.rs b/library/std/src/sys/pal/solid/os.rs deleted file mode 100644 index 79bb91b179969..0000000000000 --- a/library/std/src/sys/pal/solid/os.rs +++ /dev/null @@ -1,56 +0,0 @@ -use super::unsupported; -use crate::ffi::{OsStr, OsString}; -use crate::path::{self, PathBuf}; -use crate::{fmt, io}; - -pub fn getcwd() -> io::Result { - unsupported() -} - -pub fn chdir(_: &path::Path) -> io::Result<()> { - unsupported() -} - -pub struct SplitPaths<'a>(&'a !); - -pub fn split_paths(_unparsed: &OsStr) -> SplitPaths<'_> { - panic!("unsupported") -} - -impl<'a> Iterator for SplitPaths<'a> { - type Item = PathBuf; - fn next(&mut self) -> Option { - *self.0 - } -} - -#[derive(Debug)] -pub struct JoinPathsError; - -pub fn join_paths(_paths: I) -> Result -where - I: Iterator, - T: AsRef, -{ - Err(JoinPathsError) -} - -impl fmt::Display for JoinPathsError { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - "not supported on this platform yet".fmt(f) - } -} - -impl crate::error::Error for JoinPathsError {} - -pub fn current_exe() -> io::Result { - unsupported() -} - -pub fn temp_dir() -> PathBuf { - panic!("no standard temporary directory on this platform") -} - -pub fn home_dir() -> Option { - None -} diff --git a/library/std/src/sys/pal/teeos/os.rs b/library/std/src/sys/pal/teeos/os.rs deleted file mode 100644 index c86fa555e4117..0000000000000 --- a/library/std/src/sys/pal/teeos/os.rs +++ /dev/null @@ -1,62 +0,0 @@ -//! Implementation of `std::os` functionality for teeos - -use core::marker::PhantomData; - -use super::unsupported; -use crate::ffi::{OsStr, OsString}; -use crate::path::PathBuf; -use crate::{fmt, io, path}; - -// Everything below are stubs and copied from unsupported.rs - -pub fn getcwd() -> io::Result { - unsupported() -} - -pub fn chdir(_: &path::Path) -> io::Result<()> { - unsupported() -} - -pub struct SplitPaths<'a>(!, PhantomData<&'a ()>); - -pub fn split_paths(_unparsed: &OsStr) -> SplitPaths<'_> { - panic!("unsupported") -} - -impl<'a> Iterator for SplitPaths<'a> { - type Item = PathBuf; - fn next(&mut self) -> Option { - self.0 - } -} - -#[derive(Debug)] -pub struct JoinPathsError; - -pub fn join_paths(_paths: I) -> Result -where - I: Iterator, - T: AsRef, -{ - Err(JoinPathsError) -} - -impl fmt::Display for JoinPathsError { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - "not supported on this platform yet".fmt(f) - } -} - -impl crate::error::Error for JoinPathsError {} - -pub fn current_exe() -> io::Result { - unsupported() -} - -pub fn temp_dir() -> PathBuf { - panic!("no filesystem on this platform") -} - -pub fn home_dir() -> Option { - None -} diff --git a/library/std/src/sys/pal/xous/os.rs b/library/std/src/sys/pal/xous/os.rs deleted file mode 100644 index fe8addeafd2bc..0000000000000 --- a/library/std/src/sys/pal/xous/os.rs +++ /dev/null @@ -1,57 +0,0 @@ -use super::unsupported; -use crate::ffi::{OsStr, OsString}; -use crate::marker::PhantomData; -use crate::path::{self, PathBuf}; -use crate::{fmt, io}; - -pub fn getcwd() -> io::Result { - unsupported() -} - -pub fn chdir(_: &path::Path) -> io::Result<()> { - unsupported() -} - -pub struct SplitPaths<'a>(!, PhantomData<&'a ()>); - -pub fn split_paths(_unparsed: &OsStr) -> SplitPaths<'_> { - panic!("unsupported") -} - -impl<'a> Iterator for SplitPaths<'a> { - type Item = PathBuf; - fn next(&mut self) -> Option { - self.0 - } -} - -#[derive(Debug)] -pub struct JoinPathsError; - -pub fn join_paths(_paths: I) -> Result -where - I: Iterator, - T: AsRef, -{ - Err(JoinPathsError) -} - -impl fmt::Display for JoinPathsError { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - "not supported on this platform yet".fmt(f) - } -} - -impl crate::error::Error for JoinPathsError {} - -pub fn current_exe() -> io::Result { - unsupported() -} - -pub fn temp_dir() -> PathBuf { - panic!("no filesystem on this platform") -} - -pub fn home_dir() -> Option { - None -} diff --git a/library/std/src/sys/pal/zkvm/os.rs b/library/std/src/sys/pal/zkvm/os.rs deleted file mode 100644 index fe8addeafd2bc..0000000000000 --- a/library/std/src/sys/pal/zkvm/os.rs +++ /dev/null @@ -1,57 +0,0 @@ -use super::unsupported; -use crate::ffi::{OsStr, OsString}; -use crate::marker::PhantomData; -use crate::path::{self, PathBuf}; -use crate::{fmt, io}; - -pub fn getcwd() -> io::Result { - unsupported() -} - -pub fn chdir(_: &path::Path) -> io::Result<()> { - unsupported() -} - -pub struct SplitPaths<'a>(!, PhantomData<&'a ()>); - -pub fn split_paths(_unparsed: &OsStr) -> SplitPaths<'_> { - panic!("unsupported") -} - -impl<'a> Iterator for SplitPaths<'a> { - type Item = PathBuf; - fn next(&mut self) -> Option { - self.0 - } -} - -#[derive(Debug)] -pub struct JoinPathsError; - -pub fn join_paths(_paths: I) -> Result -where - I: Iterator, - T: AsRef, -{ - Err(JoinPathsError) -} - -impl fmt::Display for JoinPathsError { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - "not supported on this platform yet".fmt(f) - } -} - -impl crate::error::Error for JoinPathsError {} - -pub fn current_exe() -> io::Result { - unsupported() -} - -pub fn temp_dir() -> PathBuf { - panic!("no filesystem on this platform") -} - -pub fn home_dir() -> Option { - None -} diff --git a/library/std/src/sys/pal/hermit/os.rs b/library/std/src/sys/paths/hermit.rs similarity index 100% rename from library/std/src/sys/pal/hermit/os.rs rename to library/std/src/sys/paths/hermit.rs diff --git a/library/std/src/sys/pal/motor/os.rs b/library/std/src/sys/paths/motor.rs similarity index 100% rename from library/std/src/sys/pal/motor/os.rs rename to library/std/src/sys/paths/motor.rs diff --git a/library/std/src/sys/pal/sgx/os.rs b/library/std/src/sys/paths/sgx.rs similarity index 100% rename from library/std/src/sys/pal/sgx/os.rs rename to library/std/src/sys/paths/sgx.rs diff --git a/library/std/src/sys/pal/uefi/os.rs b/library/std/src/sys/paths/uefi.rs similarity index 100% rename from library/std/src/sys/pal/uefi/os.rs rename to library/std/src/sys/paths/uefi.rs diff --git a/library/std/src/sys/pal/unix/os.rs b/library/std/src/sys/paths/unix.rs similarity index 100% rename from library/std/src/sys/pal/unix/os.rs rename to library/std/src/sys/paths/unix.rs diff --git a/library/std/src/sys/pal/unsupported/os.rs b/library/std/src/sys/paths/unsupported.rs similarity index 100% rename from library/std/src/sys/pal/unsupported/os.rs rename to library/std/src/sys/paths/unsupported.rs diff --git a/library/std/src/sys/pal/wasi/os.rs b/library/std/src/sys/paths/wasi.rs similarity index 100% rename from library/std/src/sys/pal/wasi/os.rs rename to library/std/src/sys/paths/wasi.rs diff --git a/library/std/src/sys/pal/windows/os.rs b/library/std/src/sys/paths/windows.rs similarity index 100% rename from library/std/src/sys/pal/windows/os.rs rename to library/std/src/sys/paths/windows.rs From f4a95d35d3804e6e238785ed7b4aa252ce10bc3f Mon Sep 17 00:00:00 2001 From: joboet Date: Mon, 9 Mar 2026 18:37:36 +0100 Subject: [PATCH 03/15] std: move leftover Windows error test --- library/std/src/sys/io/error/windows.rs | 3 +++ .../std/src/sys/{pal/windows/os => io/error/windows}/tests.rs | 2 +- 2 files changed, 4 insertions(+), 1 deletion(-) rename library/std/src/sys/{pal/windows/os => io/error/windows}/tests.rs (93%) diff --git a/library/std/src/sys/io/error/windows.rs b/library/std/src/sys/io/error/windows.rs index d7607082a30a0..c093443f30339 100644 --- a/library/std/src/sys/io/error/windows.rs +++ b/library/std/src/sys/io/error/windows.rs @@ -1,6 +1,9 @@ use crate::sys::pal::{api, c}; use crate::{io, ptr}; +#[cfg(test)] +mod tests; + pub fn errno() -> i32 { api::get_last_error().code as i32 } diff --git a/library/std/src/sys/pal/windows/os/tests.rs b/library/std/src/sys/io/error/windows/tests.rs similarity index 93% rename from library/std/src/sys/pal/windows/os/tests.rs rename to library/std/src/sys/io/error/windows/tests.rs index 458d6e11c2098..7fc545ad00666 100644 --- a/library/std/src/sys/pal/windows/os/tests.rs +++ b/library/std/src/sys/io/error/windows/tests.rs @@ -1,5 +1,5 @@ use crate::io::Error; -use crate::sys::c; +use crate::sys::pal::c; // tests `error_string` above #[test] From be5f0708e4f493c028120fd2bf1bbadbd4e3bef4 Mon Sep 17 00:00:00 2001 From: joboet Date: Mon, 9 Mar 2026 18:43:11 +0100 Subject: [PATCH 04/15] std: move `sys::pal::os` to `sys::paths` --- library/std/src/env.rs | 20 ++++---- library/std/src/sys/args/windows.rs | 2 +- library/std/src/sys/mod.rs | 1 + library/std/src/sys/pal/hermit/mod.rs | 1 - library/std/src/sys/pal/motor/mod.rs | 2 - library/std/src/sys/pal/sgx/mod.rs | 1 - library/std/src/sys/pal/solid/mod.rs | 1 - library/std/src/sys/pal/teeos/mod.rs | 1 - library/std/src/sys/pal/trusty/mod.rs | 2 - library/std/src/sys/pal/uefi/mod.rs | 1 - library/std/src/sys/pal/unix/mod.rs | 1 - library/std/src/sys/pal/unsupported/mod.rs | 2 - library/std/src/sys/pal/vexos/mod.rs | 3 -- library/std/src/sys/pal/wasi/mod.rs | 1 - library/std/src/sys/pal/wasm/mod.rs | 3 -- library/std/src/sys/pal/windows/mod.rs | 1 - library/std/src/sys/pal/xous/mod.rs | 1 - library/std/src/sys/pal/zkvm/mod.rs | 1 - library/std/src/sys/paths/hermit.rs | 51 +------------------ library/std/src/sys/paths/mod.rs | 59 ++++++++++++++++++++++ library/std/src/sys/paths/motor.rs | 48 +----------------- library/std/src/sys/paths/sgx.rs | 58 ++------------------- library/std/src/sys/paths/uefi.rs | 4 +- library/std/src/sys/paths/unix.rs | 6 +-- library/std/src/sys/paths/unsupported.rs | 2 +- library/std/src/sys/paths/wasi.rs | 48 ++---------------- library/std/src/sys/paths/windows.rs | 33 ++++-------- 27 files changed, 99 insertions(+), 255 deletions(-) create mode 100644 library/std/src/sys/paths/mod.rs diff --git a/library/std/src/env.rs b/library/std/src/env.rs index edf0127a665e3..d3e4417656e9a 100644 --- a/library/std/src/env.rs +++ b/library/std/src/env.rs @@ -15,7 +15,7 @@ use crate::ffi::{OsStr, OsString}; use crate::num::NonZero; use crate::ops::Try; use crate::path::{Path, PathBuf}; -use crate::sys::{env as env_imp, os as os_imp}; +use crate::sys::{env as env_imp, paths as paths_imp}; use crate::{array, fmt, io, sys}; /// Returns the current working directory as a [`PathBuf`]. @@ -51,7 +51,7 @@ use crate::{array, fmt, io, sys}; #[doc(alias = "GetCurrentDirectory")] #[stable(feature = "env", since = "1.0.0")] pub fn current_dir() -> io::Result { - os_imp::getcwd() + paths_imp::getcwd() } /// Changes the current working directory to the specified path. @@ -78,7 +78,7 @@ pub fn current_dir() -> io::Result { #[doc(alias = "chdir", alias = "SetCurrentDirectory", alias = "SetCurrentDirectoryW")] #[stable(feature = "env", since = "1.0.0")] pub fn set_current_dir>(path: P) -> io::Result<()> { - os_imp::chdir(path.as_ref()) + paths_imp::chdir(path.as_ref()) } /// An iterator over a snapshot of the environment variables of this process. @@ -444,7 +444,7 @@ pub unsafe fn remove_var>(key: K) { #[must_use = "iterators are lazy and do nothing unless consumed"] #[stable(feature = "env", since = "1.0.0")] pub struct SplitPaths<'a> { - inner: os_imp::SplitPaths<'a>, + inner: paths_imp::SplitPaths<'a>, } /// Parses input according to platform conventions for the `PATH` @@ -480,7 +480,7 @@ pub struct SplitPaths<'a> { /// ``` #[stable(feature = "env", since = "1.0.0")] pub fn split_paths + ?Sized>(unparsed: &T) -> SplitPaths<'_> { - SplitPaths { inner: os_imp::split_paths(unparsed.as_ref()) } + SplitPaths { inner: paths_imp::split_paths(unparsed.as_ref()) } } #[stable(feature = "env", since = "1.0.0")] @@ -508,7 +508,7 @@ impl fmt::Debug for SplitPaths<'_> { #[derive(Debug)] #[stable(feature = "env", since = "1.0.0")] pub struct JoinPathsError { - inner: os_imp::JoinPathsError, + inner: paths_imp::JoinPathsError, } /// Joins a collection of [`Path`]s appropriately for the `PATH` @@ -579,7 +579,7 @@ where I: IntoIterator, T: AsRef, { - os_imp::join_paths(paths.into_iter()).map_err(|e| JoinPathsError { inner: e }) + paths_imp::join_paths(paths.into_iter()).map_err(|e| JoinPathsError { inner: e }) } #[stable(feature = "env", since = "1.0.0")] @@ -641,7 +641,7 @@ impl Error for JoinPathsError { #[must_use] #[stable(feature = "env", since = "1.0.0")] pub fn home_dir() -> Option { - os_imp::home_dir() + paths_imp::home_dir() } /// Returns the path of a temporary directory. @@ -701,7 +701,7 @@ pub fn home_dir() -> Option { #[doc(alias = "GetTempPath", alias = "GetTempPath2")] #[stable(feature = "env", since = "1.0.0")] pub fn temp_dir() -> PathBuf { - os_imp::temp_dir() + paths_imp::temp_dir() } /// Returns the full filesystem path of the current running executable. @@ -752,7 +752,7 @@ pub fn temp_dir() -> PathBuf { /// ``` #[stable(feature = "env", since = "1.0.0")] pub fn current_exe() -> io::Result { - os_imp::current_exe() + paths_imp::current_exe() } /// An iterator over the arguments of a process, yielding a [`String`] value for diff --git a/library/std/src/sys/args/windows.rs b/library/std/src/sys/args/windows.rs index c1988657ff1b1..3c6995e372784 100644 --- a/library/std/src/sys/args/windows.rs +++ b/library/std/src/sys/args/windows.rs @@ -12,9 +12,9 @@ use crate::num::NonZero; use crate::os::windows::prelude::*; use crate::path::{Path, PathBuf}; use crate::sys::helpers::WStrUnits; -use crate::sys::pal::os::current_exe; use crate::sys::pal::{ensure_no_nuls, fill_utf16_buf}; use crate::sys::path::get_long_path; +use crate::sys::paths::current_exe; use crate::sys::{AsInner, c, to_u16s}; use crate::{io, iter, ptr}; diff --git a/library/std/src/sys/mod.rs b/library/std/src/sys/mod.rs index 5ad23972860bb..fe0c103952414 100644 --- a/library/std/src/sys/mod.rs +++ b/library/std/src/sys/mod.rs @@ -18,6 +18,7 @@ pub mod io; pub mod net; pub mod os_str; pub mod path; +pub mod paths; pub mod pipe; pub mod platform_version; pub mod process; diff --git a/library/std/src/sys/pal/hermit/mod.rs b/library/std/src/sys/pal/hermit/mod.rs index f10a090a6e919..b18dc5b103b59 100644 --- a/library/std/src/sys/pal/hermit/mod.rs +++ b/library/std/src/sys/pal/hermit/mod.rs @@ -22,7 +22,6 @@ use crate::os::raw::c_char; use crate::sys::env; pub mod futex; -pub mod os; pub mod time; pub fn unsupported() -> io::Result { diff --git a/library/std/src/sys/pal/motor/mod.rs b/library/std/src/sys/pal/motor/mod.rs index a520375a4bbff..705413cbe0a79 100644 --- a/library/std/src/sys/pal/motor/mod.rs +++ b/library/std/src/sys/pal/motor/mod.rs @@ -1,7 +1,5 @@ #![allow(unsafe_op_in_unsafe_fn)] -pub mod os; - pub use moto_rt::futex; use crate::io; diff --git a/library/std/src/sys/pal/sgx/mod.rs b/library/std/src/sys/pal/sgx/mod.rs index 1de3ca4a5d79c..2b284cc40b94b 100644 --- a/library/std/src/sys/pal/sgx/mod.rs +++ b/library/std/src/sys/pal/sgx/mod.rs @@ -10,7 +10,6 @@ use crate::sync::atomic::{Atomic, AtomicBool, Ordering}; pub mod abi; mod libunwind_integration; -pub mod os; pub mod thread_parking; pub mod waitqueue; diff --git a/library/std/src/sys/pal/solid/mod.rs b/library/std/src/sys/pal/solid/mod.rs index 1376af8304cf6..c3f9e47945901 100644 --- a/library/std/src/sys/pal/solid/mod.rs +++ b/library/std/src/sys/pal/solid/mod.rs @@ -19,7 +19,6 @@ pub mod itron { // `error` is `pub(crate)` so that it can be accessed by `itron/error.rs` as // `crate::sys::error` pub(crate) mod error; -pub mod os; pub use self::itron::thread_parking; // SAFETY: must be called only once during runtime initialization. diff --git a/library/std/src/sys/pal/teeos/mod.rs b/library/std/src/sys/pal/teeos/mod.rs index 7d2ecdbf7ec4b..5caed277dbf59 100644 --- a/library/std/src/sys/pal/teeos/mod.rs +++ b/library/std/src/sys/pal/teeos/mod.rs @@ -7,7 +7,6 @@ #![allow(dead_code)] pub mod conf; -pub mod os; #[path = "../unix/time.rs"] pub mod time; diff --git a/library/std/src/sys/pal/trusty/mod.rs b/library/std/src/sys/pal/trusty/mod.rs index b785c2dbb7892..ec2d938ed8367 100644 --- a/library/std/src/sys/pal/trusty/mod.rs +++ b/library/std/src/sys/pal/trusty/mod.rs @@ -3,7 +3,5 @@ #[path = "../unsupported/common.rs"] #[deny(unsafe_op_in_unsafe_fn)] mod common; -#[path = "../unsupported/os.rs"] -pub mod os; pub use common::*; diff --git a/library/std/src/sys/pal/uefi/mod.rs b/library/std/src/sys/pal/uefi/mod.rs index e4a8f50e4274d..67499d2c6f17c 100644 --- a/library/std/src/sys/pal/uefi/mod.rs +++ b/library/std/src/sys/pal/uefi/mod.rs @@ -14,7 +14,6 @@ #![forbid(unsafe_op_in_unsafe_fn)] pub mod helpers; -pub mod os; pub mod system_time; #[cfg(test)] diff --git a/library/std/src/sys/pal/unix/mod.rs b/library/std/src/sys/pal/unix/mod.rs index 9931b4de0b9bf..0be150a0bfaa8 100644 --- a/library/std/src/sys/pal/unix/mod.rs +++ b/library/std/src/sys/pal/unix/mod.rs @@ -8,7 +8,6 @@ pub mod fuchsia; pub mod futex; #[cfg(target_os = "linux")] pub mod linux; -pub mod os; pub mod stack_overflow; pub mod sync; pub mod thread_parking; diff --git a/library/std/src/sys/pal/unsupported/mod.rs b/library/std/src/sys/pal/unsupported/mod.rs index 0f157819d5a66..c4b14ab44436f 100644 --- a/library/std/src/sys/pal/unsupported/mod.rs +++ b/library/std/src/sys/pal/unsupported/mod.rs @@ -1,6 +1,4 @@ #![deny(unsafe_op_in_unsafe_fn)] -pub mod os; - mod common; pub use common::*; diff --git a/library/std/src/sys/pal/vexos/mod.rs b/library/std/src/sys/pal/vexos/mod.rs index d1380ab8dff14..61bbe78f718af 100644 --- a/library/std/src/sys/pal/vexos/mod.rs +++ b/library/std/src/sys/pal/vexos/mod.rs @@ -1,6 +1,3 @@ -#[path = "../unsupported/os.rs"] -pub mod os; - #[expect(dead_code)] #[path = "../unsupported/common.rs"] mod unsupported_common; diff --git a/library/std/src/sys/pal/wasi/mod.rs b/library/std/src/sys/pal/wasi/mod.rs index 66d91078a5d54..6f60993509253 100644 --- a/library/std/src/sys/pal/wasi/mod.rs +++ b/library/std/src/sys/pal/wasi/mod.rs @@ -10,7 +10,6 @@ pub mod conf; #[allow(unused)] #[path = "../wasm/atomics/futex.rs"] pub mod futex; -pub mod os; pub mod stack_overflow; #[path = "../unix/time.rs"] pub mod time; diff --git a/library/std/src/sys/pal/wasm/mod.rs b/library/std/src/sys/pal/wasm/mod.rs index 5f56eddd6a819..24a2ab8eca30f 100644 --- a/library/std/src/sys/pal/wasm/mod.rs +++ b/library/std/src/sys/pal/wasm/mod.rs @@ -16,9 +16,6 @@ #![deny(unsafe_op_in_unsafe_fn)] -#[path = "../unsupported/os.rs"] -pub mod os; - #[cfg(target_feature = "atomics")] #[path = "atomics/futex.rs"] pub mod futex; diff --git a/library/std/src/sys/pal/windows/mod.rs b/library/std/src/sys/pal/windows/mod.rs index 0cd9152614716..b67ba37749789 100644 --- a/library/std/src/sys/pal/windows/mod.rs +++ b/library/std/src/sys/pal/windows/mod.rs @@ -18,7 +18,6 @@ pub mod c; #[cfg(not(target_vendor = "win7"))] pub mod futex; pub mod handle; -pub mod os; pub mod time; cfg_select! { // We don't care about printing nice error messages for panic=immediate-abort diff --git a/library/std/src/sys/pal/xous/mod.rs b/library/std/src/sys/pal/xous/mod.rs index 9b22fb88c998d..b5b3fd91b4fa6 100644 --- a/library/std/src/sys/pal/xous/mod.rs +++ b/library/std/src/sys/pal/xous/mod.rs @@ -1,6 +1,5 @@ #![forbid(unsafe_op_in_unsafe_fn)] -pub mod os; pub mod params; #[path = "../unsupported/common.rs"] diff --git a/library/std/src/sys/pal/zkvm/mod.rs b/library/std/src/sys/pal/zkvm/mod.rs index 1b18adb811d95..1a64d3c93d701 100644 --- a/library/std/src/sys/pal/zkvm/mod.rs +++ b/library/std/src/sys/pal/zkvm/mod.rs @@ -11,7 +11,6 @@ pub const WORD_SIZE: usize = size_of::(); pub mod abi; -pub mod os; use crate::io as std_io; diff --git a/library/std/src/sys/paths/hermit.rs b/library/std/src/sys/paths/hermit.rs index 188caded55d48..36f667d300539 100644 --- a/library/std/src/sys/paths/hermit.rs +++ b/library/std/src/sys/paths/hermit.rs @@ -1,57 +1,10 @@ -use crate::ffi::{OsStr, OsString}; -use crate::marker::PhantomData; -use crate::path::{self, PathBuf}; -use crate::sys::unsupported; -use crate::{fmt, io}; +use crate::io; +use crate::path::PathBuf; pub fn getcwd() -> io::Result { Ok(PathBuf::from("/")) } -pub fn chdir(_: &path::Path) -> io::Result<()> { - unsupported() -} - -pub struct SplitPaths<'a>(!, PhantomData<&'a ()>); - -pub fn split_paths(_unparsed: &OsStr) -> SplitPaths<'_> { - panic!("unsupported") -} - -impl<'a> Iterator for SplitPaths<'a> { - type Item = PathBuf; - fn next(&mut self) -> Option { - self.0 - } -} - -#[derive(Debug)] -pub struct JoinPathsError; - -pub fn join_paths(_paths: I) -> Result -where - I: Iterator, - T: AsRef, -{ - Err(JoinPathsError) -} - -impl fmt::Display for JoinPathsError { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - "not supported on hermit yet".fmt(f) - } -} - -impl crate::error::Error for JoinPathsError {} - -pub fn current_exe() -> io::Result { - unsupported() -} - pub fn temp_dir() -> PathBuf { PathBuf::from("/tmp") } - -pub fn home_dir() -> Option { - None -} diff --git a/library/std/src/sys/paths/mod.rs b/library/std/src/sys/paths/mod.rs new file mode 100644 index 0000000000000..8880a837af7f9 --- /dev/null +++ b/library/std/src/sys/paths/mod.rs @@ -0,0 +1,59 @@ +cfg_select! { + target_os = "hermit" => { + mod hermit; + #[expect(dead_code)] + mod unsupported; + mod imp { + pub use super::hermit::{getcwd, temp_dir}; + pub use super::unsupported::{chdir, SplitPaths, split_paths, JoinPathsError, join_paths, current_exe, home_dir}; + } + } + target_os = "motor" => { + mod motor; + #[expect(dead_code)] + mod unsupported; + mod imp { + pub use super::motor::{getcwd, chdir, current_exe, temp_dir}; + pub use super::unsupported::{SplitPaths, split_paths, JoinPathsError, join_paths, home_dir}; + } + } + all(target_vendor = "fortanix", target_env = "sgx") => { + mod sgx; + #[expect(dead_code)] + mod unsupported; + mod imp { + pub use super::sgx::chdir; + pub use super::unsupported::{getcwd, SplitPaths, split_paths, JoinPathsError, join_paths, current_exe, temp_dir, home_dir}; + } + } + target_os = "uefi" => { + mod uefi; + use uefi as imp; + } + target_family = "unix" => { + mod unix; + use unix as imp; + } + target_os = "wasi" => { + mod wasi; + #[expect(dead_code)] + mod unsupported; + mod imp { + pub use super::wasi::{getcwd, chdir, temp_dir}; + pub use super::unsupported::{current_exe, SplitPaths, split_paths, JoinPathsError, join_paths, home_dir}; + } + } + target_os = "windows" => { + mod windows; + use windows as imp; + } + _ => { + mod unsupported; + use unsupported as imp; + } +} + +pub use imp::{ + JoinPathsError, SplitPaths, chdir, current_exe, getcwd, home_dir, join_paths, split_paths, + temp_dir, +}; diff --git a/library/std/src/sys/paths/motor.rs b/library/std/src/sys/paths/motor.rs index 0af579303306e..33d746b13d592 100644 --- a/library/std/src/sys/paths/motor.rs +++ b/library/std/src/sys/paths/motor.rs @@ -1,10 +1,7 @@ -use super::map_motor_error; -use crate::error::Error as StdError; -use crate::ffi::{OsStr, OsString}; -use crate::marker::PhantomData; +use crate::io; use crate::os::motor::ffi::OsStrExt; use crate::path::{self, PathBuf}; -use crate::{fmt, io}; +use crate::sys::pal::map_motor_error; pub fn getcwd() -> io::Result { moto_rt::fs::getcwd().map(PathBuf::from).map_err(map_motor_error) @@ -14,43 +11,6 @@ pub fn chdir(path: &path::Path) -> io::Result<()> { moto_rt::fs::chdir(path.as_os_str().as_str()).map_err(map_motor_error) } -pub struct SplitPaths<'a>(!, PhantomData<&'a ()>); - -pub fn split_paths(_unparsed: &OsStr) -> SplitPaths<'_> { - panic!("unsupported") -} - -impl<'a> Iterator for SplitPaths<'a> { - type Item = PathBuf; - fn next(&mut self) -> Option { - self.0 - } -} - -#[derive(Debug)] -pub struct JoinPathsError; - -pub fn join_paths(_paths: I) -> Result -where - I: Iterator, - T: AsRef, -{ - Err(JoinPathsError) -} - -impl fmt::Display for JoinPathsError { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - "not supported on this platform yet".fmt(f) - } -} - -impl StdError for JoinPathsError { - #[allow(deprecated)] - fn description(&self) -> &str { - "not supported on this platform yet" - } -} - pub fn current_exe() -> io::Result { moto_rt::process::current_exe().map(PathBuf::from).map_err(map_motor_error) } @@ -58,7 +18,3 @@ pub fn current_exe() -> io::Result { pub fn temp_dir() -> PathBuf { PathBuf::from(moto_rt::fs::TEMP_DIR) } - -pub fn home_dir() -> Option { - None -} diff --git a/library/std/src/sys/paths/sgx.rs b/library/std/src/sys/paths/sgx.rs index 5b0af37a3d373..6a4cbe93b1b88 100644 --- a/library/std/src/sys/paths/sgx.rs +++ b/library/std/src/sys/paths/sgx.rs @@ -1,57 +1,7 @@ -use crate::ffi::{OsStr, OsString}; -use crate::marker::PhantomData; -use crate::path::{self, PathBuf}; -use crate::sys::{sgx_ineffective, unsupported}; -use crate::{fmt, io}; +use crate::io; +use crate::path::Path; +use crate::sys::pal::sgx_ineffective; -pub fn getcwd() -> io::Result { - unsupported() -} - -pub fn chdir(_: &path::Path) -> io::Result<()> { +pub fn chdir(_: &Path) -> io::Result<()> { sgx_ineffective(()) } - -pub struct SplitPaths<'a>(!, PhantomData<&'a ()>); - -pub fn split_paths(_unparsed: &OsStr) -> SplitPaths<'_> { - panic!("unsupported") -} - -impl<'a> Iterator for SplitPaths<'a> { - type Item = PathBuf; - fn next(&mut self) -> Option { - self.0 - } -} - -#[derive(Debug)] -pub struct JoinPathsError; - -pub fn join_paths(_paths: I) -> Result -where - I: Iterator, - T: AsRef, -{ - Err(JoinPathsError) -} - -impl fmt::Display for JoinPathsError { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - "not supported in SGX yet".fmt(f) - } -} - -impl crate::error::Error for JoinPathsError {} - -pub fn current_exe() -> io::Result { - unsupported() -} - -pub fn temp_dir() -> PathBuf { - panic!("no filesystem in SGX") -} - -pub fn home_dir() -> Option { - None -} diff --git a/library/std/src/sys/paths/uefi.rs b/library/std/src/sys/paths/uefi.rs index b25be430a3f83..7fddcfdff7724 100644 --- a/library/std/src/sys/paths/uefi.rs +++ b/library/std/src/sys/paths/uefi.rs @@ -1,9 +1,9 @@ use r_efi::efi::protocols::{device_path, loaded_image_device_path}; -use super::{helpers, unsupported_err}; use crate::ffi::{OsStr, OsString}; use crate::os::uefi::ffi::{OsStrExt, OsStringExt}; use crate::path::{self, PathBuf}; +use crate::sys::pal::{helpers, unsupported_err}; use crate::{fmt, io}; const PATHS_SEP: u16 = b';' as u16; @@ -115,7 +115,7 @@ pub fn current_exe() -> io::Result { } pub fn temp_dir() -> PathBuf { - panic!("no filesystem on this platform") + panic!("UEFI doesn't have a dedicated temp directory") } pub fn home_dir() -> Option { diff --git a/library/std/src/sys/paths/unix.rs b/library/std/src/sys/paths/unix.rs index f69614c2077cd..544d495340db7 100644 --- a/library/std/src/sys/paths/unix.rs +++ b/library/std/src/sys/paths/unix.rs @@ -7,8 +7,8 @@ use libc::{c_char, c_int, c_void}; use crate::ffi::{CStr, OsStr, OsString}; use crate::os::unix::prelude::*; use crate::path::{self, PathBuf}; -use crate::sys::cvt; use crate::sys::helpers::run_path_with_cstr; +use crate::sys::pal::cvt; use crate::{fmt, io, iter, mem, ptr, slice, str}; const PATH_SEPARATOR: u8 = b':'; @@ -47,7 +47,7 @@ pub fn getcwd() -> io::Result { #[cfg(target_os = "espidf")] pub fn chdir(_p: &path::Path) -> io::Result<()> { - super::unsupported::unsupported() + crate::sys::pal::unsupported::unsupported() } #[cfg(not(target_os = "espidf"))] @@ -372,7 +372,7 @@ pub fn current_exe() -> io::Result { #[cfg(any(target_os = "espidf", target_os = "horizon", target_os = "vita"))] pub fn current_exe() -> io::Result { - super::unsupported::unsupported() + crate::sys::pal::unsupported::unsupported() } #[cfg(target_os = "fuchsia")] diff --git a/library/std/src/sys/paths/unsupported.rs b/library/std/src/sys/paths/unsupported.rs index fe8addeafd2bc..024830a254fd7 100644 --- a/library/std/src/sys/paths/unsupported.rs +++ b/library/std/src/sys/paths/unsupported.rs @@ -1,7 +1,7 @@ -use super::unsupported; use crate::ffi::{OsStr, OsString}; use crate::marker::PhantomData; use crate::path::{self, PathBuf}; +use crate::sys::pal::unsupported; use crate::{fmt, io}; pub fn getcwd() -> io::Result { diff --git a/library/std/src/sys/paths/wasi.rs b/library/std/src/sys/paths/wasi.rs index b1c26acc68cb9..1e1f951cd6793 100644 --- a/library/std/src/sys/paths/wasi.rs +++ b/library/std/src/sys/paths/wasi.rs @@ -1,12 +1,10 @@ #![forbid(unsafe_op_in_unsafe_fn)] -use crate::ffi::{CStr, OsStr, OsString}; -use crate::marker::PhantomData; +use crate::ffi::{CStr, OsString}; +use crate::io; use crate::os::wasi::prelude::*; use crate::path::{self, PathBuf}; use crate::sys::helpers::run_path_with_cstr; -use crate::sys::unsupported; -use crate::{fmt, io}; pub fn getcwd() -> io::Result { let mut buf = Vec::with_capacity(512); @@ -42,46 +40,6 @@ pub fn chdir(p: &path::Path) -> io::Result<()> { } } -pub struct SplitPaths<'a>(!, PhantomData<&'a ()>); - -pub fn split_paths(_unparsed: &OsStr) -> SplitPaths<'_> { - panic!("unsupported") -} - -impl<'a> Iterator for SplitPaths<'a> { - type Item = PathBuf; - fn next(&mut self) -> Option { - self.0 - } -} - -#[derive(Debug)] -pub struct JoinPathsError; - -pub fn join_paths(_paths: I) -> Result -where - I: Iterator, - T: AsRef, -{ - Err(JoinPathsError) -} - -impl fmt::Display for JoinPathsError { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - "not supported on wasm yet".fmt(f) - } -} - -impl crate::error::Error for JoinPathsError {} - -pub fn current_exe() -> io::Result { - unsupported() -} - pub fn temp_dir() -> PathBuf { - panic!("no filesystem on wasm") -} - -pub fn home_dir() -> Option { - None + panic!("not supported by WASI yet") } diff --git a/library/std/src/sys/paths/windows.rs b/library/std/src/sys/paths/windows.rs index 30cad2a05683c..cfdc93847a97a 100644 --- a/library/std/src/sys/paths/windows.rs +++ b/library/std/src/sys/paths/windows.rs @@ -2,17 +2,13 @@ #![allow(nonstandard_style)] -#[cfg(test)] -mod tests; - -use super::api; -#[cfg(not(target_vendor = "uwp"))] -use super::api::WinError; use crate::ffi::{OsStr, OsString}; use crate::os::windows::ffi::EncodeWide; use crate::os::windows::prelude::*; use crate::path::{self, PathBuf}; -use crate::sys::pal::{c, cvt}; +#[cfg(not(target_vendor = "uwp"))] +use crate::sys::pal::api::WinError; +use crate::sys::pal::{api, c, cvt, fill_utf16_buf, os2path}; use crate::{fmt, io, ptr}; pub struct SplitPaths<'a> { @@ -56,11 +52,7 @@ impl<'a> Iterator for SplitPaths<'a> { } } - if !must_yield && in_progress.is_empty() { - None - } else { - Some(super::os2path(&in_progress)) - } + if !must_yield && in_progress.is_empty() { None } else { Some(os2path(&in_progress)) } } } @@ -104,14 +96,11 @@ impl fmt::Display for JoinPathsError { impl crate::error::Error for JoinPathsError {} pub fn current_exe() -> io::Result { - super::fill_utf16_buf( - |buf, sz| unsafe { c::GetModuleFileNameW(ptr::null_mut(), buf, sz) }, - super::os2path, - ) + fill_utf16_buf(|buf, sz| unsafe { c::GetModuleFileNameW(ptr::null_mut(), buf, sz) }, os2path) } pub fn getcwd() -> io::Result { - super::fill_utf16_buf(|buf, sz| unsafe { c::GetCurrentDirectoryW(sz, buf) }, super::os2path) + fill_utf16_buf(|buf, sz| unsafe { c::GetCurrentDirectoryW(sz, buf) }, os2path) } pub fn chdir(p: &path::Path) -> io::Result<()> { @@ -123,7 +112,7 @@ pub fn chdir(p: &path::Path) -> io::Result<()> { } pub fn temp_dir() -> PathBuf { - super::fill_utf16_buf(|buf, sz| unsafe { c::GetTempPath2W(sz, buf) }, super::os2path).unwrap() + fill_utf16_buf(|buf, sz| unsafe { c::GetTempPath2W(sz, buf) }, os2path).unwrap() } #[cfg(all(not(target_vendor = "uwp"), not(target_vendor = "win7")))] @@ -132,7 +121,7 @@ fn home_dir_crt() -> Option { // Defined in processthreadsapi.h. const CURRENT_PROCESS_TOKEN: usize = -4_isize as usize; - super::fill_utf16_buf( + fill_utf16_buf( |buf, mut sz| { // GetUserProfileDirectoryW does not quite use the usual protocol for // negotiating the buffer size, so we have to translate. @@ -146,7 +135,7 @@ fn home_dir_crt() -> Option { _ => sz - 1, // sz includes the null terminator } }, - super::os2path, + os2path, ) .ok() } @@ -163,7 +152,7 @@ fn home_dir_crt() -> Option { return None; } let _handle = Handle::from_raw_handle(token); - super::fill_utf16_buf( + fill_utf16_buf( |buf, mut sz| { match c::GetUserProfileDirectoryW(token, buf, &mut sz) { 0 if api::get_last_error() != WinError::INSUFFICIENT_BUFFER => 0, @@ -171,7 +160,7 @@ fn home_dir_crt() -> Option { _ => sz - 1, // sz includes the null terminator } }, - super::os2path, + os2path, ) .ok() } From 0e0babcc5e5d3b0a0bf33b875731fb11a4e62f4b Mon Sep 17 00:00:00 2001 From: Tony Kan Date: Tue, 10 Mar 2026 01:03:35 -0700 Subject: [PATCH 05/15] docs(fs): Clarify that File::lock coordinates across processes --- library/std/src/fs.rs | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/library/std/src/fs.rs b/library/std/src/fs.rs index 885bf376b98ad..9643d3fcae662 100644 --- a/library/std/src/fs.rs +++ b/library/std/src/fs.rs @@ -815,7 +815,8 @@ impl File { /// Acquire an exclusive lock on the file. Blocks until the lock can be acquired. /// - /// This acquires an exclusive lock; no other file handle to this file may acquire another lock. + /// This acquires an exclusive lock; no other file handle to this file, in this or any other + /// process, may acquire another lock. /// /// This lock may be advisory or mandatory. This lock is meant to interact with [`lock`], /// [`try_lock`], [`lock_shared`], [`try_lock_shared`], and [`unlock`]. Its interactions with @@ -868,8 +869,8 @@ impl File { /// Acquire a shared (non-exclusive) lock on the file. Blocks until the lock can be acquired. /// - /// This acquires a shared lock; more than one file handle may hold a shared lock, but none may - /// hold an exclusive lock at the same time. + /// This acquires a shared lock; more than one file handle, in this or any other process, may + /// hold a shared lock, but none may hold an exclusive lock at the same time. /// /// This lock may be advisory or mandatory. This lock is meant to interact with [`lock`], /// [`try_lock`], [`lock_shared`], [`try_lock_shared`], and [`unlock`]. Its interactions with @@ -923,7 +924,8 @@ impl File { /// Returns `Err(TryLockError::WouldBlock)` if a different lock is already held on this file /// (via another handle/descriptor). /// - /// This acquires an exclusive lock; no other file handle to this file may acquire another lock. + /// This acquires an exclusive lock; no other file handle to this file, in this or any other + /// process, may acquire another lock. /// /// This lock may be advisory or mandatory. This lock is meant to interact with [`lock`], /// [`try_lock`], [`lock_shared`], [`try_lock_shared`], and [`unlock`]. Its interactions with @@ -987,8 +989,8 @@ impl File { /// Returns `Err(TryLockError::WouldBlock)` if a different lock is already held on this file /// (via another handle/descriptor). /// - /// This acquires a shared lock; more than one file handle may hold a shared lock, but none may - /// hold an exclusive lock at the same time. + /// This acquires a shared lock; more than one file handle, in this or any other process, may + /// hold a shared lock, but none may hold an exclusive lock at the same time. /// /// This lock may be advisory or mandatory. This lock is meant to interact with [`lock`], /// [`try_lock`], [`lock_shared`], [`try_lock_shared`], and [`unlock`]. Its interactions with From e108da9dc263aa28fed4b5a51d5e08311be2355f Mon Sep 17 00:00:00 2001 From: James Kay Date: Wed, 11 Mar 2026 02:25:56 +0000 Subject: [PATCH 06/15] `std`: include `dlmalloc` for all non-wasi Wasm targets Currently, building std for a custom Wasm target with an OS other than `unknown` will fail, because `sys/alloc/mod.rs` will attempt to use `sys/alloc/wasm.rs`, the dlmalloc-based allocator used on `wasm32-unknown-unknown`. However, currently dlmalloc is only pulled in when `target_os = "unknown"`. Instead, we should make `Cargo.toml` and `alloc/mod.rs` match: either - disable `wasm.rs` in `alloc/mod.rs` where `not(target_os = "unknown")`, or - pull in `dlmalloc` for all Wasm targets with `target_family = "wasm32"` that aren't covered by the [upper branches of `alloc/mod.rs`](https://github.com/rust-lang/rust/blob/main/library/std/src/sys/alloc/mod.rs#L72-L100). This PR takes the latter approach, because it allows more code to compile without a custom allocator. --- library/std/Cargo.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/library/std/Cargo.toml b/library/std/Cargo.toml index 1b7a41d697367..740d37617547c 100644 --- a/library/std/Cargo.toml +++ b/library/std/Cargo.toml @@ -62,7 +62,7 @@ path = "../windows_link" rand = { version = "0.9.0", default-features = false, features = ["alloc"] } rand_xorshift = "0.4.0" -[target.'cfg(any(all(target_family = "wasm", target_os = "unknown"), target_os = "xous", target_os = "vexos", all(target_vendor = "fortanix", target_env = "sgx")))'.dependencies] +[target.'cfg(any(all(target_family = "wasm", not(target_os = "wasi")), target_os = "xous", target_os = "vexos", all(target_vendor = "fortanix", target_env = "sgx")))'.dependencies] dlmalloc = { version = "0.2.10", features = ['rustc-dep-of-std'] } [target.x86_64-fortanix-unknown-sgx.dependencies] From e2923eb86a18b2e288e88605a61c21fcc38f8c82 Mon Sep 17 00:00:00 2001 From: James Kay Date: Wed, 11 Mar 2026 16:49:12 +0000 Subject: [PATCH 07/15] `std`: don't depend on `dlmalloc` when `cfg(unix)` --- library/std/Cargo.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/library/std/Cargo.toml b/library/std/Cargo.toml index 740d37617547c..7a8ccdbc5043b 100644 --- a/library/std/Cargo.toml +++ b/library/std/Cargo.toml @@ -62,7 +62,7 @@ path = "../windows_link" rand = { version = "0.9.0", default-features = false, features = ["alloc"] } rand_xorshift = "0.4.0" -[target.'cfg(any(all(target_family = "wasm", not(target_os = "wasi")), target_os = "xous", target_os = "vexos", all(target_vendor = "fortanix", target_env = "sgx")))'.dependencies] +[target.'cfg(any(all(target_family = "wasm", not(any(unix, target_os = "wasi"))), target_os = "xous", target_os = "vexos", all(target_vendor = "fortanix", target_env = "sgx")))'.dependencies] dlmalloc = { version = "0.2.10", features = ['rustc-dep-of-std'] } [target.x86_64-fortanix-unknown-sgx.dependencies] From 425df0dedb4e20be0bab9d028e6444a7339ea937 Mon Sep 17 00:00:00 2001 From: Zakarum Date: Thu, 19 Feb 2026 15:17:01 +0100 Subject: [PATCH 08/15] Do not emit separator as before elements --- library/core/src/iter/adapters/intersperse.rs | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/library/core/src/iter/adapters/intersperse.rs b/library/core/src/iter/adapters/intersperse.rs index bb94ed0a0a170..f33a67a983103 100644 --- a/library/core/src/iter/adapters/intersperse.rs +++ b/library/core/src/iter/adapters/intersperse.rs @@ -57,8 +57,9 @@ where } } } else { - self.started = true; - self.iter.next() + let item = self.iter.next(); + self.started = item.is_some(); + item } } @@ -173,8 +174,9 @@ where } } } else { - self.started = true; - self.iter.next() + let item = self.iter.next(); + self.started = item.is_some(); + item } } From 800d9ea8e85087f1d2bbe9eddad94614367904b4 Mon Sep 17 00:00:00 2001 From: Mahdi Ali-Raihan Date: Sat, 14 Mar 2026 13:00:55 -0400 Subject: [PATCH 09/15] Lifted intersperse and intersperse_with Fused restrictions and updated documentation + tests --- library/core/src/iter/adapters/intersperse.rs | 25 +--- library/core/src/iter/traits/iterator.rs | 44 ++++-- .../tests/iter/adapters/intersperse.rs | 126 ++++++++---------- 3 files changed, 95 insertions(+), 100 deletions(-) diff --git a/library/core/src/iter/adapters/intersperse.rs b/library/core/src/iter/adapters/intersperse.rs index f33a67a983103..f64dea2df862c 100644 --- a/library/core/src/iter/adapters/intersperse.rs +++ b/library/core/src/iter/adapters/intersperse.rs @@ -1,5 +1,4 @@ use crate::fmt; -use crate::iter::{Fuse, FusedIterator}; /// An iterator adapter that places a separator between all elements. /// @@ -14,15 +13,7 @@ where started: bool, separator: I::Item, next_item: Option, - iter: Fuse, -} - -#[unstable(feature = "iter_intersperse", issue = "79524")] -impl FusedIterator for Intersperse -where - I: FusedIterator, - I::Item: Clone, -{ + iter: I, } impl Intersperse @@ -30,7 +21,7 @@ where I::Item: Clone, { pub(in crate::iter) fn new(iter: I, separator: I::Item) -> Self { - Self { started: false, separator, next_item: None, iter: iter.fuse() } + Self { started: false, separator, next_item: None, iter } } } @@ -96,15 +87,7 @@ where started: bool, separator: G, next_item: Option, - iter: Fuse, -} - -#[unstable(feature = "iter_intersperse", issue = "79524")] -impl FusedIterator for IntersperseWith -where - I: FusedIterator, - G: FnMut() -> I::Item, -{ + iter: I, } #[unstable(feature = "iter_intersperse", issue = "79524")] @@ -147,7 +130,7 @@ where G: FnMut() -> I::Item, { pub(in crate::iter) fn new(iter: I, separator: G) -> Self { - Self { started: false, separator, next_item: None, iter: iter.fuse() } + Self { started: false, separator, next_item: None, iter } } } diff --git a/library/core/src/iter/traits/iterator.rs b/library/core/src/iter/traits/iterator.rs index 2e82f45771823..11b1c04ce0e20 100644 --- a/library/core/src/iter/traits/iterator.rs +++ b/library/core/src/iter/traits/iterator.rs @@ -635,11 +635,24 @@ pub const trait Iterator { /// of the original iterator. /// /// Specifically on fused iterators, it is guaranteed that the new iterator - /// places a copy of `separator` between adjacent `Some(_)` items. However, - /// for non-fused iterators, [`intersperse`] will create a new iterator that - /// is a fused version of the original iterator and place a copy of `separator` - /// between adjacent `Some(_)` items. This behavior for non-fused iterators - /// is subject to change. + /// places a copy of `separator` between *adjacent* `Some(_)` items. For non-fused iterators, + /// it is guaranteed that [`intersperse`] will create a new iterator that places a copy + /// of `separator` between `Some(_)` items, particularly just right before the subsequent + /// `Some(_)` item. + /// + /// For example, consider the following non-fused iterator: + /// + /// ```text + /// Some(1) -> Some(2) -> None -> Some(3) -> Some(4) -> ... + /// ``` + /// + /// If this non-fused iterator were to be interspersed with `0`, + /// then the interspersed iterator will produce: + /// + /// ```text + /// Some(1) -> Some(0) -> Some(2) -> None -> Some(0) -> Some(3) -> Some(0) -> + /// Some(4) -> ... + /// ``` /// /// In case `separator` does not implement [`Clone`] or needs to be /// computed every time, use [`intersperse_with`]. @@ -688,10 +701,23 @@ pub const trait Iterator { /// /// Specifically on fused iterators, it is guaranteed that the new iterator /// places an item generated by `separator` between adjacent `Some(_)` items. - /// However, for non-fused iterators, [`intersperse_with`] will create a new - /// iterator that is a fused version of the original iterator and place an item - /// generated by `separator` between adjacent `Some(_)` items. This - /// behavior for non-fused iterators is subject to change. + /// For non-fused iterators, it is guaranteed that [`intersperse_with`] will + /// create a new iterator that places an item generated by `separator` between `Some(_)` + /// items, particularly just right before the subsequent `Some(_)` item. + /// + /// For example, consider the following non-fused iterator: + /// + /// ```text + /// Some(1) -> Some(2) -> None -> Some(3) -> Some(4) -> ... + /// ``` + /// + /// If this non-fused iterator were to be interspersed with a `separator` closure + /// that returns `0` repeatedly, the interspersed iterator will produce: + /// + /// ```text + /// Some(1) -> Some(0) -> Some(2) -> None -> Some(0) -> Some(3) -> Some(0) -> + /// Some(4) -> ... + /// ``` /// /// The `separator` closure will be called exactly once each time an item /// is placed between two adjacent items from the underlying iterator; diff --git a/library/coretests/tests/iter/adapters/intersperse.rs b/library/coretests/tests/iter/adapters/intersperse.rs index df6be79308be7..bcb7709077cd7 100644 --- a/library/coretests/tests/iter/adapters/intersperse.rs +++ b/library/coretests/tests/iter/adapters/intersperse.rs @@ -153,10 +153,6 @@ fn test_try_fold_specialization_intersperse_err() { assert_eq!(iter.next(), None); } -// FIXME(iter_intersperse): `intersperse` current behavior may change for -// non-fused iterators, so this test will likely have to -// be adjusted; see PR #152855 and issue #79524 -// if `intersperse` doesn't change, remove this FIXME. #[test] fn test_non_fused_iterator_intersperse() { #[derive(Debug)] @@ -183,24 +179,26 @@ fn test_non_fused_iterator_intersperse() { } let counter = 0; - // places a 2 between `Some(_)` items + // places a 1 between `Some(_)` items let non_fused_iter = TestCounter { counter }; - let mut intersperse_iter = non_fused_iter.intersperse(2); - // Since `intersperse` currently transforms the original - // iterator into a fused iterator, this intersperse_iter - // should always have `None` - for _ in 0..counter + 6 { - assert_eq!(intersperse_iter.next(), None); - } + let mut intersperse_iter = non_fused_iter.intersperse(1); + // Interspersed iter produces: + // `None` -> `Some(2)` -> `None` -> `Some(1)` -> Some(4)` -> `None` -> `Some(1)` -> + // `Some(6)` -> and then `None` endlessly + assert_eq!(intersperse_iter.next(), None); + assert_eq!(intersperse_iter.next(), Some(2)); + assert_eq!(intersperse_iter.next(), None); + assert_eq!(intersperse_iter.next(), Some(1)); + assert_eq!(intersperse_iter.next(), Some(4)); + assert_eq!(intersperse_iter.next(), None); + assert_eq!(intersperse_iter.next(), Some(1)); + assert_eq!(intersperse_iter.next(), Some(6)); + assert_eq!(intersperse_iter.next(), None); - // Extra check to make sure it is `None` after processing 6 items + // Extra check to make sure it is `None` after processing all items assert_eq!(intersperse_iter.next(), None); } -// FIXME(iter_intersperse): `intersperse` current behavior may change for -// non-fused iterators, so this test will likely have to -// be adjusted; see PR #152855 and issue #79524 -// if `intersperse` doesn't change, remove this FIXME. #[test] fn test_non_fused_iterator_intersperse_2() { #[derive(Debug)] @@ -228,35 +226,26 @@ fn test_non_fused_iterator_intersperse_2() { } let counter = 0; - // places a 2 between `Some(_)` items + // places a 100 between `Some(_)` items let non_fused_iter = TestCounter { counter }; - let mut intersperse_iter = non_fused_iter.intersperse(2); - // Since `intersperse` currently transforms the original - // iterator into a fused iterator, this interspersed iter - // will be `Some(1)` -> `Some(2)` -> `Some(2)` -> and then - // `None` endlessly - let mut items_processed = 0; - for num in 0..counter + 6 { - if num < 3 { - if num % 2 != 0 { - assert_eq!(intersperse_iter.next(), Some(2)); - } else { - items_processed += 1; - assert_eq!(intersperse_iter.next(), Some(items_processed)); - } - } else { - assert_eq!(intersperse_iter.next(), None); - } - } + let mut intersperse_iter = non_fused_iter.intersperse(100); + // Interspersed iter produces: + // `Some(1)` -> `Some(100)` -> `Some(2)` -> `None` -> `Some(100)` + // -> `Some(4)` -> `Some(100)` -> `Some(5)` -> `None` endlessly + assert_eq!(intersperse_iter.next(), Some(1)); + assert_eq!(intersperse_iter.next(), Some(100)); + assert_eq!(intersperse_iter.next(), Some(2)); + assert_eq!(intersperse_iter.next(), None); + assert_eq!(intersperse_iter.next(), Some(100)); + assert_eq!(intersperse_iter.next(), Some(4)); + assert_eq!(intersperse_iter.next(), Some(100)); + assert_eq!(intersperse_iter.next(), Some(5)); + assert_eq!(intersperse_iter.next(), None); // Extra check to make sure it is `None` after processing 6 items assert_eq!(intersperse_iter.next(), None); } -// FIXME(iter_intersperse): `intersperse_with` current behavior may change for -// non-fused iterators, so this test will likely have to -// be adjusted; see PR #152855 and issue #79524 -// if `intersperse_with` doesn't change, remove this FIXME. #[test] fn test_non_fused_iterator_intersperse_with() { #[derive(Debug)] @@ -285,22 +274,24 @@ fn test_non_fused_iterator_intersperse_with() { let counter = 0; let non_fused_iter = TestCounter { counter }; // places a 2 between `Some(_)` items - let mut intersperse_iter = non_fused_iter.intersperse_with(|| 2); - // Since `intersperse` currently transforms the original - // iterator into a fused iterator, this intersperse_iter - // should always have `None` - for _ in 0..counter + 6 { - assert_eq!(intersperse_iter.next(), None); - } + let mut intersperse_iter = non_fused_iter.intersperse_with(|| 1); + // Interspersed iter produces: + // `None` -> `Some(2)` -> `None` -> `Some(1)` -> Some(4)` -> `None` -> `Some(1)` -> + // `Some(6)` -> and then `None` endlessly + assert_eq!(intersperse_iter.next(), None); + assert_eq!(intersperse_iter.next(), Some(2)); + assert_eq!(intersperse_iter.next(), None); + assert_eq!(intersperse_iter.next(), Some(1)); + assert_eq!(intersperse_iter.next(), Some(4)); + assert_eq!(intersperse_iter.next(), None); + assert_eq!(intersperse_iter.next(), Some(1)); + assert_eq!(intersperse_iter.next(), Some(6)); + assert_eq!(intersperse_iter.next(), None); // Extra check to make sure it is `None` after processing 6 items assert_eq!(intersperse_iter.next(), None); } -// FIXME(iter_intersperse): `intersperse_with` current behavior may change for -// non-fused iterators, so this test will likely have to -// be adjusted; see PR #152855 and issue #79524 -// if `intersperse_with` doesn't change, remove this FIXME. #[test] fn test_non_fused_iterator_intersperse_with_2() { #[derive(Debug)] @@ -328,26 +319,21 @@ fn test_non_fused_iterator_intersperse_with_2() { } let counter = 0; - // places a 2 between `Some(_)` items + // places a 100 between `Some(_)` items let non_fused_iter = TestCounter { counter }; - let mut intersperse_iter = non_fused_iter.intersperse(2); - // Since `intersperse` currently transforms the original - // iterator into a fused iterator, this interspersed iter - // will be `Some(1)` -> `Some(2)` -> `Some(2)` -> and then - // `None` endlessly - let mut items_processed = 0; - for num in 0..counter + 6 { - if num < 3 { - if num % 2 != 0 { - assert_eq!(intersperse_iter.next(), Some(2)); - } else { - items_processed += 1; - assert_eq!(intersperse_iter.next(), Some(items_processed)); - } - } else { - assert_eq!(intersperse_iter.next(), None); - } - } + let mut intersperse_iter = non_fused_iter.intersperse_with(|| 100); + // Interspersed iter produces: + // `Some(1)` -> `Some(100)` -> `Some(2)` -> `None` -> `Some(100)` + // -> `Some(4)` -> `Some(100)` -> `Some(5)` -> `None` endlessly + assert_eq!(intersperse_iter.next(), Some(1)); + assert_eq!(intersperse_iter.next(), Some(100)); + assert_eq!(intersperse_iter.next(), Some(2)); + assert_eq!(intersperse_iter.next(), None); + assert_eq!(intersperse_iter.next(), Some(100)); + assert_eq!(intersperse_iter.next(), Some(4)); + assert_eq!(intersperse_iter.next(), Some(100)); + assert_eq!(intersperse_iter.next(), Some(5)); + assert_eq!(intersperse_iter.next(), None); // Extra check to make sure it is `None` after processing 6 items assert_eq!(intersperse_iter.next(), None); From a893257ceab1ea549112935c83c979daa123ebb8 Mon Sep 17 00:00:00 2001 From: cyrgani Date: Sun, 15 Mar 2026 22:11:26 +0000 Subject: [PATCH 10/15] remove usages of to-be-deprecated numeric constants --- compiler/rustc_middle/src/dep_graph/serialized.rs | 2 +- library/coretests/tests/array.rs | 2 +- library/coretests/tests/num/int_macros.rs | 3 ++- library/coretests/tests/num/uint_macros.rs | 15 +++++++-------- library/stdarch/crates/core_arch/src/mips/msa.rs | 1 - src/tools/rustfmt/src/vertical.rs | 2 +- tests/ui/consts/issue-90762.rs | 2 +- 7 files changed, 13 insertions(+), 14 deletions(-) diff --git a/compiler/rustc_middle/src/dep_graph/serialized.rs b/compiler/rustc_middle/src/dep_graph/serialized.rs index 8a4ac4b5e5acd..2f3d9eac7386c 100644 --- a/compiler/rustc_middle/src/dep_graph/serialized.rs +++ b/compiler/rustc_middle/src/dep_graph/serialized.rs @@ -43,7 +43,7 @@ use std::cell::RefCell; use std::cmp::max; use std::sync::Arc; use std::sync::atomic::Ordering; -use std::{iter, mem, u64}; +use std::{iter, mem}; use rustc_data_structures::fingerprint::{Fingerprint, PackedFingerprint}; use rustc_data_structures::fx::FxHashMap; diff --git a/library/coretests/tests/array.rs b/library/coretests/tests/array.rs index 2b4429092e98b..5a24f02cbf3d9 100644 --- a/library/coretests/tests/array.rs +++ b/library/coretests/tests/array.rs @@ -646,7 +646,7 @@ fn array_mixed_equality_integers() { #[test] fn array_mixed_equality_nans() { - let array3: [f32; 3] = [1.0, std::f32::NAN, 3.0]; + let array3: [f32; 3] = [1.0, f32::NAN, 3.0]; let slice3: &[f32] = &{ array3 }; assert!(!(array3 == slice3)); diff --git a/library/coretests/tests/num/int_macros.rs b/library/coretests/tests/num/int_macros.rs index 37336f49ef1b6..2b641f595eba4 100644 --- a/library/coretests/tests/num/int_macros.rs +++ b/library/coretests/tests/num/int_macros.rs @@ -2,7 +2,8 @@ macro_rules! int_module { ($T:ident, $U:ident) => { use core::num::ParseIntError; use core::ops::{BitAnd, BitOr, BitXor, Not, Shl, Shr}; - use core::$T::*; + const MAX: $T = $T::MAX; + const MIN: $T = $T::MIN; const UMAX: $U = $U::MAX; diff --git a/library/coretests/tests/num/uint_macros.rs b/library/coretests/tests/num/uint_macros.rs index 240c66fd5c715..8dfa0924bd369 100644 --- a/library/coretests/tests/num/uint_macros.rs +++ b/library/coretests/tests/num/uint_macros.rs @@ -2,15 +2,14 @@ macro_rules! uint_module { ($T:ident) => { use core::num::ParseIntError; use core::ops::{BitAnd, BitOr, BitXor, Not, Shl, Shr}; - use core::$T::*; use crate::num; #[test] fn test_overflows() { - assert!(MAX > 0); - assert!(MIN <= 0); - assert!((MIN + MAX).wrapping_add(1) == 0); + assert!($T::MAX > 0); + assert!($T::MIN <= 0); + assert!(($T::MIN + $T::MAX).wrapping_add(1) == 0); } #[test] @@ -25,7 +24,7 @@ macro_rules! uint_module { assert!(0b0110 as $T == (0b1100 as $T).bitxor(0b1010 as $T)); assert!(0b1110 as $T == (0b0111 as $T).shl(1)); assert!(0b0111 as $T == (0b1110 as $T).shr(1)); - assert!(MAX - (0b1011 as $T) == (0b1011 as $T).not()); + assert!($T::MAX - (0b1011 as $T) == (0b1011 as $T).not()); } const A: $T = 0b0101100; @@ -361,7 +360,7 @@ macro_rules! uint_module { assert_eq_const_safe!($T: R.wrapping_pow(2), 1 as $T); assert_eq_const_safe!(Option<$T>: R.checked_pow(2), None); assert_eq_const_safe!(($T, bool): R.overflowing_pow(2), (1 as $T, true)); - assert_eq_const_safe!($T: R.saturating_pow(2), MAX); + assert_eq_const_safe!($T: R.saturating_pow(2), $T::MAX); } } @@ -468,14 +467,14 @@ macro_rules! uint_module { fn test_next_multiple_of() { assert_eq_const_safe!($T: (16 as $T).next_multiple_of(8), 16); assert_eq_const_safe!($T: (23 as $T).next_multiple_of(8), 24); - assert_eq_const_safe!($T: MAX.next_multiple_of(1), MAX); + assert_eq_const_safe!($T: $T::MAX.next_multiple_of(1), $T::MAX); } fn test_checked_next_multiple_of() { assert_eq_const_safe!(Option<$T>: (16 as $T).checked_next_multiple_of(8), Some(16)); assert_eq_const_safe!(Option<$T>: (23 as $T).checked_next_multiple_of(8), Some(24)); assert_eq_const_safe!(Option<$T>: (1 as $T).checked_next_multiple_of(0), None); - assert_eq_const_safe!(Option<$T>: MAX.checked_next_multiple_of(2), None); + assert_eq_const_safe!(Option<$T>: $T::MAX.checked_next_multiple_of(2), None); } fn test_is_next_multiple_of() { diff --git a/library/stdarch/crates/core_arch/src/mips/msa.rs b/library/stdarch/crates/core_arch/src/mips/msa.rs index 563e121a7badb..6246433da5585 100644 --- a/library/stdarch/crates/core_arch/src/mips/msa.rs +++ b/library/stdarch/crates/core_arch/src/mips/msa.rs @@ -9187,7 +9187,6 @@ mod tests { core_arch::{mips::msa::*, simd::*}, mem, }; - use std::{f32, f64}; use stdarch_test::simd_test; #[simd_test(enable = "msa")] diff --git a/src/tools/rustfmt/src/vertical.rs b/src/tools/rustfmt/src/vertical.rs index 21e34d29710fb..fd9a4a7db6a78 100644 --- a/src/tools/rustfmt/src/vertical.rs +++ b/src/tools/rustfmt/src/vertical.rs @@ -198,7 +198,7 @@ fn struct_field_prefix_max_min_width( .rewrite_prefix(context, shape) .map(|field_str| trimmed_last_line_width(&field_str)) }) - .fold_ok((0, ::std::usize::MAX), |(max_len, min_len), len| { + .fold_ok((0, usize::MAX), |(max_len, min_len), len| { (cmp::max(max_len, len), cmp::min(min_len, len)) }) .unwrap_or((0, 0)) diff --git a/tests/ui/consts/issue-90762.rs b/tests/ui/consts/issue-90762.rs index db40e50d4995f..cc060366b80bf 100644 --- a/tests/ui/consts/issue-90762.rs +++ b/tests/ui/consts/issue-90762.rs @@ -27,5 +27,5 @@ fn main() { for (i, b) in FOO.iter().enumerate() { assert!(b.load(Ordering::Relaxed), "{} not set", i); } - assert_eq!(BAR.fetch_add(1, Ordering::Relaxed), usize::max_value()); + assert_eq!(BAR.fetch_add(1, Ordering::Relaxed), usize::MAX); } From cab72ae27878f7433c446a358981c061d75b4257 Mon Sep 17 00:00:00 2001 From: usamoi Date: Wed, 18 Mar 2026 02:03:31 +0800 Subject: [PATCH 11/15] implement `BinaryHeap::as_mut_slice` --- .../alloc/src/collections/binary_heap/mod.rs | 31 +++++++++++++++++++ 1 file changed, 31 insertions(+) diff --git a/library/alloc/src/collections/binary_heap/mod.rs b/library/alloc/src/collections/binary_heap/mod.rs index 4ddfcde57280e..d46b1972b5b00 100644 --- a/library/alloc/src/collections/binary_heap/mod.rs +++ b/library/alloc/src/collections/binary_heap/mod.rs @@ -1364,6 +1364,37 @@ impl BinaryHeap { self.data.as_slice() } + /// Returns a mutable slice of all values in the underlying vector. + /// + /// # Safety + /// + /// The caller must ensure that the slice remains a max-heap, i.e. for all indices + /// `0 < i < slice.len()`, `slice[(i - 1) / 2] >= slice[i]`, before the borrow ends + /// and the binary heap is used. + /// + /// # Examples + /// + /// Basic usage: + /// + /// ``` + /// #![feature(binary_heap_as_mut_slice)] + /// + /// use std::collections::BinaryHeap; + /// + /// let mut heap = BinaryHeap::::from([1, 2, 3, 4, 5, 6, 7]); + /// + /// unsafe { + /// for value in heap.as_mut_slice() { + /// *value = (*value).saturating_mul(2); + /// } + /// } + /// ``` + #[must_use] + #[unstable(feature = "binary_heap_as_mut_slice", issue = "154009")] + pub unsafe fn as_mut_slice(&mut self) -> &mut [T] { + self.data.as_mut_slice() + } + /// Consumes the `BinaryHeap` and returns the underlying vector /// in arbitrary order. /// From 577dba9093034117b63e4c29147d29ceae1c32c6 Mon Sep 17 00:00:00 2001 From: Daniel Tang Date: Sun, 15 Mar 2026 22:00:52 -0400 Subject: [PATCH 12/15] Skip stack_start_aligned for immediate-abort This improves startup performance by 16%, shown by an optimized hello-world program. glibc's `pthread_getattr_np` performs expensive syscalls when reading `/proc/self/maps`. That is all wasted with `panic = immediate-abort` active because `init()` immediately discards the return value from `install_main_guard()`. A similar improvement can be seen in environments that don't have `/proc`. This change is safe because the immediately succeeding comment says that we rely on Linux's "own stack-guard mechanism". --- library/std/src/sys/pal/unix/stack_overflow.rs | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/library/std/src/sys/pal/unix/stack_overflow.rs b/library/std/src/sys/pal/unix/stack_overflow.rs index 632f619655b37..5d53de7fb7e21 100644 --- a/library/std/src/sys/pal/unix/stack_overflow.rs +++ b/library/std/src/sys/pal/unix/stack_overflow.rs @@ -429,6 +429,11 @@ mod imp { #[forbid(unsafe_op_in_unsafe_fn)] unsafe fn install_main_guard_linux(page_size: usize) -> Option> { + // See the corresponding conditional in init(). + // Avoid stack_start_aligned, which makes slow syscalls to read /proc/self/maps + if cfg!(panic = "immediate-abort") { + return None; + } // Linux doesn't allocate the whole stack right away, and // the kernel has its own stack-guard mechanism to fault // when growing too close to an existing mapping. If we map @@ -456,6 +461,10 @@ mod imp { #[forbid(unsafe_op_in_unsafe_fn)] #[cfg(target_os = "freebsd")] unsafe fn install_main_guard_freebsd(page_size: usize) -> Option> { + // See the corresponding conditional in install_main_guard_linux(). + if cfg!(panic = "immediate-abort") { + return None; + } // FreeBSD's stack autogrows, and optionally includes a guard page // at the bottom. If we try to remap the bottom of the stack // ourselves, FreeBSD's guard page moves upwards. So we'll just use @@ -489,6 +498,10 @@ mod imp { #[forbid(unsafe_op_in_unsafe_fn)] unsafe fn install_main_guard_bsds(page_size: usize) -> Option> { + // See the corresponding conditional in install_main_guard_linux(). + if cfg!(panic = "immediate-abort") { + return None; + } // OpenBSD stack already includes a guard page, and stack is // immutable. // NetBSD stack includes the guard page. From 9b7dff982eb2f2084e2e1ceee2d1c6d832963e7a Mon Sep 17 00:00:00 2001 From: ujjwalVishwakarma2006 <2023ucs0116@iitjammu.ac.in> Date: Sun, 22 Mar 2026 00:06:06 +0530 Subject: [PATCH 13/15] Move and rename LTO-specific test files from tests/ui/issues/ to tests/ui/lto/ --- tests/ui/{issues/issue-44056.rs => lto/lto-avx-target-feature.rs} | 0 .../ui/{issues/issue-51947.rs => lto/lto-weak-merge-functions.rs} | 0 2 files changed, 0 insertions(+), 0 deletions(-) rename tests/ui/{issues/issue-44056.rs => lto/lto-avx-target-feature.rs} (100%) rename tests/ui/{issues/issue-51947.rs => lto/lto-weak-merge-functions.rs} (100%) diff --git a/tests/ui/issues/issue-44056.rs b/tests/ui/lto/lto-avx-target-feature.rs similarity index 100% rename from tests/ui/issues/issue-44056.rs rename to tests/ui/lto/lto-avx-target-feature.rs diff --git a/tests/ui/issues/issue-51947.rs b/tests/ui/lto/lto-weak-merge-functions.rs similarity index 100% rename from tests/ui/issues/issue-51947.rs rename to tests/ui/lto/lto-weak-merge-functions.rs From dd2b2084c9914fdb123d8b8e3b77e5c751c42ef8 Mon Sep 17 00:00:00 2001 From: ujjwalVishwakarma2006 <2023ucs0116@iitjammu.ac.in> Date: Sun, 22 Mar 2026 15:18:42 +0530 Subject: [PATCH 14/15] Add comment at the top in two test files referencing the issue they originate from --- tests/ui/lto/lto-avx-target-feature.rs | 1 + tests/ui/lto/lto-weak-merge-functions.rs | 1 + 2 files changed, 2 insertions(+) diff --git a/tests/ui/lto/lto-avx-target-feature.rs b/tests/ui/lto/lto-avx-target-feature.rs index 37d7b00cf7f0e..37a8ce67dcfcf 100644 --- a/tests/ui/lto/lto-avx-target-feature.rs +++ b/tests/ui/lto/lto-avx-target-feature.rs @@ -1,3 +1,4 @@ +//! regression test for //@ build-pass (FIXME(55996): should be run on targets supporting avx) //@ only-x86_64 //@ no-prefer-dynamic diff --git a/tests/ui/lto/lto-weak-merge-functions.rs b/tests/ui/lto/lto-weak-merge-functions.rs index eda48aa5cf47a..bf16fbc834354 100644 --- a/tests/ui/lto/lto-weak-merge-functions.rs +++ b/tests/ui/lto/lto-weak-merge-functions.rs @@ -1,3 +1,4 @@ +//! regression test for //@ build-pass #![crate_type = "lib"] From 6458ca5349136c740dcb1fd99ec7e4f1eb2dbd99 Mon Sep 17 00:00:00 2001 From: Mark Rousskov Date: Fri, 2 Jan 2026 17:28:27 -0500 Subject: [PATCH 15/15] Unknown -> Unsupported compression algorithm Both zstd and zlib are *known* compression algorithms, they just may not be supported by the backend. We shouldn't mislead users into e.g. thinking they made a typo. --- compiler/rustc_codegen_llvm/src/back/write.rs | 6 +++--- compiler/rustc_codegen_llvm/src/errors.rs | 4 ++-- tests/run-make/compressed-debuginfo/rmake.rs | 2 +- 3 files changed, 6 insertions(+), 6 deletions(-) diff --git a/compiler/rustc_codegen_llvm/src/back/write.rs b/compiler/rustc_codegen_llvm/src/back/write.rs index ffa582737ca8c..faa14a6c573e3 100644 --- a/compiler/rustc_codegen_llvm/src/back/write.rs +++ b/compiler/rustc_codegen_llvm/src/back/write.rs @@ -36,7 +36,7 @@ use crate::builder::gpu_offload::scalar_width; use crate::common::AsCCharPtr; use crate::errors::{ CopyBitcode, FromLlvmDiag, FromLlvmOptimizationDiag, LlvmError, ParseTargetMachineConfig, - UnknownCompression, WithLlvmError, WriteBytecode, + UnsupportedCompression, WithLlvmError, WriteBytecode, }; use crate::llvm::diagnostic::OptimizationDiagnosticKind::*; use crate::llvm::{self, DiagnosticInfo}; @@ -248,7 +248,7 @@ pub(crate) fn target_machine_factory( if llvm::LLVMRustLLVMHasZlibCompression() { llvm::CompressionKind::Zlib } else { - sess.dcx().emit_warn(UnknownCompression { algorithm: "zlib" }); + sess.dcx().emit_warn(UnsupportedCompression { algorithm: "zlib" }); llvm::CompressionKind::None } } @@ -256,7 +256,7 @@ pub(crate) fn target_machine_factory( if llvm::LLVMRustLLVMHasZstdCompression() { llvm::CompressionKind::Zstd } else { - sess.dcx().emit_warn(UnknownCompression { algorithm: "zstd" }); + sess.dcx().emit_warn(UnsupportedCompression { algorithm: "zstd" }); llvm::CompressionKind::None } } diff --git a/compiler/rustc_codegen_llvm/src/errors.rs b/compiler/rustc_codegen_llvm/src/errors.rs index 9fb406516f66a..880abb3fbc248 100644 --- a/compiler/rustc_codegen_llvm/src/errors.rs +++ b/compiler/rustc_codegen_llvm/src/errors.rs @@ -182,9 +182,9 @@ pub(crate) struct CopyBitcode { #[derive(Diagnostic)] #[diag( - "unknown debuginfo compression algorithm {$algorithm} - will fall back to uncompressed debuginfo" + "unsupported debuginfo compression algorithm {$algorithm} - will fall back to uncompressed debuginfo" )] -pub(crate) struct UnknownCompression { +pub(crate) struct UnsupportedCompression { pub algorithm: &'static str, } diff --git a/tests/run-make/compressed-debuginfo/rmake.rs b/tests/run-make/compressed-debuginfo/rmake.rs index 5ba1a1852d51b..c8bde9cfa221f 100644 --- a/tests/run-make/compressed-debuginfo/rmake.rs +++ b/tests/run-make/compressed-debuginfo/rmake.rs @@ -23,7 +23,7 @@ fn check_compression(compression: &str, to_find: &str) { } else { assert_contains( stderr, - format!("unknown debuginfo compression algorithm {compression}"), + format!("unsupported debuginfo compression algorithm {compression}"), ); } });