From 01485c9fe9a50b48fd4c78e7116dcaa2aeb87a40 Mon Sep 17 00:00:00 2001 From: Thalia Archibald Date: Mon, 21 Apr 2025 22:24:02 -0700 Subject: [PATCH] Unify owned `Env` types between platforms Also, update the same pattern of reuse in `sys::args` to match. --- library/std/src/sys/args/mod.rs | 10 ++++++ library/std/src/sys/args/uefi.rs | 5 +-- library/std/src/sys/args/unix.rs | 5 +-- library/std/src/sys/args/wasi.rs | 5 +-- library/std/src/sys/args/windows.rs | 5 +-- library/std/src/sys/args/xous.rs | 5 +-- library/std/src/sys/env/common.rs | 48 +++++++++++++++++++++++++ library/std/src/sys/env/hermit.rs | 52 +++------------------------ library/std/src/sys/env/mod.rs | 11 ++++++ library/std/src/sys/env/sgx.rs | 55 +++-------------------------- library/std/src/sys/env/solid.rs | 50 ++------------------------ library/std/src/sys/env/uefi.rs | 42 ++-------------------- library/std/src/sys/env/unix.rs | 50 ++------------------------ library/std/src/sys/env/wasi.rs | 50 ++------------------------ library/std/src/sys/env/xous.rs | 53 +++------------------------ 15 files changed, 98 insertions(+), 348 deletions(-) create mode 100644 library/std/src/sys/env/common.rs diff --git a/library/std/src/sys/args/mod.rs b/library/std/src/sys/args/mod.rs index 6a37b32d2293..0011f55dc14e 100644 --- a/library/std/src/sys/args/mod.rs +++ b/library/std/src/sys/args/mod.rs @@ -2,6 +2,16 @@ #![forbid(unsafe_op_in_unsafe_fn)] +#[cfg(any( + all(target_family = "unix", not(any(target_os = "espidf", target_os = "vita"))), + target_family = "windows", + target_os = "hermit", + target_os = "uefi", + target_os = "wasi", + target_os = "xous", +))] +mod common; + cfg_if::cfg_if! { if #[cfg(any( all(target_family = "unix", not(any(target_os = "espidf", target_os = "vita"))), diff --git a/library/std/src/sys/args/uefi.rs b/library/std/src/sys/args/uefi.rs index 84406c7f69df..02dada382eff 100644 --- a/library/std/src/sys/args/uefi.rs +++ b/library/std/src/sys/args/uefi.rs @@ -1,14 +1,11 @@ use r_efi::protocols::loaded_image; +pub use super::common::Args; use crate::env::current_exe; use crate::ffi::OsString; use crate::iter::Iterator; use crate::sys::pal::helpers; -#[path = "common.rs"] -mod common; -pub use common::Args; - pub fn args() -> Args { let lazy_current_exe = || Vec::from([current_exe().map(Into::into).unwrap_or_default()]); diff --git a/library/std/src/sys/args/unix.rs b/library/std/src/sys/args/unix.rs index c087fd629651..a7b79ad396e7 100644 --- a/library/std/src/sys/args/unix.rs +++ b/library/std/src/sys/args/unix.rs @@ -5,16 +5,13 @@ #![allow(dead_code)] // runtime init functions not used during testing +pub use super::common::Args; use crate::ffi::CStr; #[cfg(target_os = "hermit")] use crate::os::hermit::ffi::OsStringExt; #[cfg(not(target_os = "hermit"))] use crate::os::unix::ffi::OsStringExt; -#[path = "common.rs"] -mod common; -pub use common::Args; - /// One-time global initialization. pub unsafe fn init(argc: isize, argv: *const *const u8) { unsafe { imp::init(argc, argv) } diff --git a/library/std/src/sys/args/wasi.rs b/library/std/src/sys/args/wasi.rs index 4795789e4c71..72063a87dc9f 100644 --- a/library/std/src/sys/args/wasi.rs +++ b/library/std/src/sys/args/wasi.rs @@ -1,12 +1,9 @@ #![forbid(unsafe_op_in_unsafe_fn)] +pub use super::common::Args; use crate::ffi::{CStr, OsStr, OsString}; use crate::os::wasi::ffi::OsStrExt; -#[path = "common.rs"] -mod common; -pub use common::Args; - /// Returns the command line arguments pub fn args() -> Args { Args::new(maybe_args().unwrap_or(Vec::new())) diff --git a/library/std/src/sys/args/windows.rs b/library/std/src/sys/args/windows.rs index 47f0e5f2d05f..81c44fabdcc6 100644 --- a/library/std/src/sys/args/windows.rs +++ b/library/std/src/sys/args/windows.rs @@ -6,6 +6,7 @@ #[cfg(test)] mod tests; +pub use super::common::Args; use crate::ffi::{OsStr, OsString}; use crate::num::NonZero; use crate::os::windows::prelude::*; @@ -18,10 +19,6 @@ use crate::sys_common::AsInner; use crate::sys_common::wstr::WStrUnits; use crate::{io, iter, ptr}; -#[path = "common.rs"] -mod common; -pub use common::Args; - pub fn args() -> Args { // SAFETY: `GetCommandLineW` returns a pointer to a null terminated UTF-16 // string so it's safe for `WStrUnits` to use. diff --git a/library/std/src/sys/args/xous.rs b/library/std/src/sys/args/xous.rs index 09a47283d657..2010bad14d1f 100644 --- a/library/std/src/sys/args/xous.rs +++ b/library/std/src/sys/args/xous.rs @@ -1,10 +1,7 @@ +pub use super::common::Args; use crate::sys::pal::os::get_application_parameters; use crate::sys::pal::os::params::ArgumentList; -#[path = "common.rs"] -mod common; -pub use common::Args; - pub fn args() -> Args { let Some(params) = get_application_parameters() else { return Args::new(vec![]); diff --git a/library/std/src/sys/env/common.rs b/library/std/src/sys/env/common.rs new file mode 100644 index 000000000000..f161ff073f3d --- /dev/null +++ b/library/std/src/sys/env/common.rs @@ -0,0 +1,48 @@ +use crate::ffi::OsString; +use crate::{fmt, vec}; + +pub struct Env { + iter: vec::IntoIter<(OsString, OsString)>, +} + +// FIXME(https://github.com/rust-lang/rust/issues/114583): Remove this when ::fmt matches ::fmt. +pub struct EnvStrDebug<'a> { + slice: &'a [(OsString, OsString)], +} + +impl fmt::Debug for EnvStrDebug<'_> { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + f.debug_list() + .entries(self.slice.iter().map(|(a, b)| (a.to_str().unwrap(), b.to_str().unwrap()))) + .finish() + } +} + +impl Env { + pub(super) fn new(env: Vec<(OsString, OsString)>) -> Self { + Env { iter: env.into_iter() } + } + + pub fn str_debug(&self) -> impl fmt::Debug + '_ { + EnvStrDebug { slice: self.iter.as_slice() } + } +} + +impl fmt::Debug for Env { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + f.debug_list().entries(self.iter.as_slice()).finish() + } +} + +impl !Send for Env {} +impl !Sync for Env {} + +impl Iterator for Env { + type Item = (OsString, OsString); + fn next(&mut self) -> Option<(OsString, OsString)> { + self.iter.next() + } + fn size_hint(&self) -> (usize, Option) { + self.iter.size_hint() + } +} diff --git a/library/std/src/sys/env/hermit.rs b/library/std/src/sys/env/hermit.rs index 4c7d7e80a350..445ecdeb6a39 100644 --- a/library/std/src/sys/env/hermit.rs +++ b/library/std/src/sys/env/hermit.rs @@ -1,10 +1,11 @@ use core::slice::memchr; +pub use super::common::Env; use crate::collections::HashMap; use crate::ffi::{CStr, OsStr, OsString, c_char}; +use crate::io; use crate::os::hermit::ffi::OsStringExt; use crate::sync::Mutex; -use crate::{fmt, io, vec}; static ENV: Mutex>> = Mutex::new(None); @@ -44,60 +45,15 @@ pub fn init(env: *const *const c_char) { } } -pub struct Env { - iter: vec::IntoIter<(OsString, OsString)>, -} - -// FIXME(https://github.com/rust-lang/rust/issues/114583): Remove this when ::fmt matches ::fmt. -pub struct EnvStrDebug<'a> { - slice: &'a [(OsString, OsString)], -} - -impl fmt::Debug for EnvStrDebug<'_> { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - let Self { slice } = self; - f.debug_list() - .entries(slice.iter().map(|(a, b)| (a.to_str().unwrap(), b.to_str().unwrap()))) - .finish() - } -} - -impl Env { - pub fn str_debug(&self) -> impl fmt::Debug + '_ { - let Self { iter } = self; - EnvStrDebug { slice: iter.as_slice() } - } -} - -impl fmt::Debug for Env { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - let Self { iter } = self; - f.debug_list().entries(iter.as_slice()).finish() - } -} - -impl !Send for Env {} -impl !Sync for Env {} - -impl Iterator for Env { - type Item = (OsString, OsString); - fn next(&mut self) -> Option<(OsString, OsString)> { - self.iter.next() - } - fn size_hint(&self) -> (usize, Option) { - self.iter.size_hint() - } -} - /// Returns a vector of (variable, value) byte-vector pairs for all the /// environment variables of the current process. pub fn env() -> Env { let guard = ENV.lock().unwrap(); let env = guard.as_ref().unwrap(); - let result = env.iter().map(|(key, value)| (key.clone(), value.clone())).collect::>(); + let result = env.iter().map(|(key, value)| (key.clone(), value.clone())).collect(); - Env { iter: result.into_iter() } + Env::new(result) } pub fn getenv(k: &OsStr) -> Option { diff --git a/library/std/src/sys/env/mod.rs b/library/std/src/sys/env/mod.rs index 0ae7ef53addb..d81ff875c830 100644 --- a/library/std/src/sys/env/mod.rs +++ b/library/std/src/sys/env/mod.rs @@ -2,6 +2,17 @@ #![forbid(unsafe_op_in_unsafe_fn)] +#[cfg(any( + target_family = "unix", + target_os = "hermit", + all(target_vendor = "fortanix", target_env = "sgx"), + target_os = "solid_asp3", + target_os = "uefi", + target_os = "wasi", + target_os = "xous", +))] +mod common; + cfg_if::cfg_if! { if #[cfg(target_family = "unix")] { mod unix; diff --git a/library/std/src/sys/env/sgx.rs b/library/std/src/sys/env/sgx.rs index 7a48fb1872ba..85be9cd6ad41 100644 --- a/library/std/src/sys/env/sgx.rs +++ b/library/std/src/sys/env/sgx.rs @@ -1,10 +1,11 @@ #![allow(fuzzy_provenance_casts)] // FIXME: this module systematically confuses pointers and integers +pub use super::common::Env; use crate::collections::HashMap; use crate::ffi::{OsStr, OsString}; +use crate::io; use crate::sync::atomic::{AtomicUsize, Ordering}; use crate::sync::{Mutex, Once}; -use crate::{fmt, io, vec}; // Specifying linkage/symbol name is solely to ensure a single instance between this crate and its unit tests #[cfg_attr(test, linkage = "available_externally")] @@ -27,61 +28,13 @@ fn create_env_store() -> &'static EnvStore { unsafe { &*(ENV.load(Ordering::Relaxed) as *const EnvStore) } } -pub struct Env { - iter: vec::IntoIter<(OsString, OsString)>, -} - -// FIXME(https://github.com/rust-lang/rust/issues/114583): Remove this when ::fmt matches ::fmt. -pub struct EnvStrDebug<'a> { - slice: &'a [(OsString, OsString)], -} - -impl fmt::Debug for EnvStrDebug<'_> { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - let Self { slice } = self; - f.debug_list() - .entries(slice.iter().map(|(a, b)| (a.to_str().unwrap(), b.to_str().unwrap()))) - .finish() - } -} - -impl Env { - pub fn str_debug(&self) -> impl fmt::Debug + '_ { - let Self { iter } = self; - EnvStrDebug { slice: iter.as_slice() } - } -} - -impl fmt::Debug for Env { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - let Self { iter } = self; - f.debug_list().entries(iter.as_slice()).finish() - } -} - -impl !Send for Env {} -impl !Sync for Env {} - -impl Iterator for Env { - type Item = (OsString, OsString); - fn next(&mut self) -> Option<(OsString, OsString)> { - self.iter.next() - } - fn size_hint(&self) -> (usize, Option) { - self.iter.size_hint() - } -} - pub fn env() -> Env { let clone_to_vec = |map: &HashMap| -> Vec<_> { map.iter().map(|(k, v)| (k.clone(), v.clone())).collect() }; - let iter = get_env_store() - .map(|env| clone_to_vec(&env.lock().unwrap())) - .unwrap_or_default() - .into_iter(); - Env { iter } + let env = get_env_store().map(|env| clone_to_vec(&env.lock().unwrap())).unwrap_or_default(); + Env::new(env) } pub fn getenv(k: &OsStr) -> Option { diff --git a/library/std/src/sys/env/solid.rs b/library/std/src/sys/env/solid.rs index 0eb801c996ad..ea77fc3c1193 100644 --- a/library/std/src/sys/env/solid.rs +++ b/library/std/src/sys/env/solid.rs @@ -1,11 +1,12 @@ use core::slice::memchr; +pub use super::common::Env; use crate::ffi::{CStr, OsStr, OsString}; +use crate::io; use crate::os::raw::{c_char, c_int}; use crate::os::solid::ffi::{OsStrExt, OsStringExt}; use crate::sync::{PoisonError, RwLock}; use crate::sys::common::small_c_string::run_with_cstr; -use crate::{fmt, io, vec}; static ENV_LOCK: RwLock<()> = RwLock::new(()); @@ -13,51 +14,6 @@ pub fn env_read_lock() -> impl Drop { ENV_LOCK.read().unwrap_or_else(PoisonError::into_inner) } -pub struct Env { - iter: vec::IntoIter<(OsString, OsString)>, -} - -// FIXME(https://github.com/rust-lang/rust/issues/114583): Remove this when ::fmt matches ::fmt. -pub struct EnvStrDebug<'a> { - slice: &'a [(OsString, OsString)], -} - -impl fmt::Debug for EnvStrDebug<'_> { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - let Self { slice } = self; - f.debug_list() - .entries(slice.iter().map(|(a, b)| (a.to_str().unwrap(), b.to_str().unwrap()))) - .finish() - } -} - -impl Env { - pub fn str_debug(&self) -> impl fmt::Debug + '_ { - let Self { iter } = self; - EnvStrDebug { slice: iter.as_slice() } - } -} - -impl fmt::Debug for Env { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - let Self { iter } = self; - f.debug_list().entries(iter.as_slice()).finish() - } -} - -impl !Send for Env {} -impl !Sync for Env {} - -impl Iterator for Env { - type Item = (OsString, OsString); - fn next(&mut self) -> Option<(OsString, OsString)> { - self.iter.next() - } - fn size_hint(&self) -> (usize, Option) { - self.iter.size_hint() - } -} - /// Returns a vector of (variable, value) byte-vector pairs for all the /// environment variables of the current process. pub fn env() -> Env { @@ -76,7 +32,7 @@ pub fn env() -> Env { environ = environ.add(1); } } - return Env { iter: result.into_iter() }; + return Env::new(result); } fn parse(input: &[u8]) -> Option<(OsString, OsString)> { diff --git a/library/std/src/sys/env/uefi.rs b/library/std/src/sys/env/uefi.rs index a26305acf8e0..1561df41cac3 100644 --- a/library/std/src/sys/env/uefi.rs +++ b/library/std/src/sys/env/uefi.rs @@ -1,46 +1,10 @@ +pub use super::common::Env; use crate::ffi::{OsStr, OsString}; -use crate::{fmt, io}; - -pub struct EnvStrDebug<'a> { - iter: &'a [(OsString, OsString)], -} - -impl fmt::Debug for EnvStrDebug<'_> { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - let mut list = f.debug_list(); - for (a, b) in self.iter { - list.entry(&(a.to_str().unwrap(), b.to_str().unwrap())); - } - list.finish() - } -} - -pub struct Env(crate::vec::IntoIter<(OsString, OsString)>); - -impl Env { - // FIXME(https://github.com/rust-lang/rust/issues/114583): Remove this when ::fmt matches ::fmt. - pub fn str_debug(&self) -> impl fmt::Debug + '_ { - EnvStrDebug { iter: self.0.as_slice() } - } -} - -impl Iterator for Env { - type Item = (OsString, OsString); - - fn next(&mut self) -> Option<(OsString, OsString)> { - self.0.next() - } -} - -impl fmt::Debug for Env { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - self.0.fmt(f) - } -} +use crate::io; pub fn env() -> Env { let env = uefi_env::get_all().expect("not supported on this platform"); - Env(env.into_iter()) + Env::new(env) } pub fn getenv(key: &OsStr) -> Option { diff --git a/library/std/src/sys/env/unix.rs b/library/std/src/sys/env/unix.rs index 73aacfcad3b4..78c7af65f9e3 100644 --- a/library/std/src/sys/env/unix.rs +++ b/library/std/src/sys/env/unix.rs @@ -2,57 +2,13 @@ use core::slice::memchr; use libc::c_char; +pub use super::common::Env; use crate::ffi::{CStr, OsStr, OsString}; +use crate::io; use crate::os::unix::prelude::*; use crate::sync::{PoisonError, RwLock}; use crate::sys::common::small_c_string::run_with_cstr; use crate::sys::cvt; -use crate::{fmt, io, vec}; - -pub struct Env { - iter: vec::IntoIter<(OsString, OsString)>, -} - -// FIXME(https://github.com/rust-lang/rust/issues/114583): Remove this when ::fmt matches ::fmt. -pub struct EnvStrDebug<'a> { - slice: &'a [(OsString, OsString)], -} - -impl fmt::Debug for EnvStrDebug<'_> { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - let Self { slice } = self; - f.debug_list() - .entries(slice.iter().map(|(a, b)| (a.to_str().unwrap(), b.to_str().unwrap()))) - .finish() - } -} - -impl Env { - pub fn str_debug(&self) -> impl fmt::Debug + '_ { - let Self { iter } = self; - EnvStrDebug { slice: iter.as_slice() } - } -} - -impl fmt::Debug for Env { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - let Self { iter } = self; - f.debug_list().entries(iter.as_slice()).finish() - } -} - -impl !Send for Env {} -impl !Sync for Env {} - -impl Iterator for Env { - type Item = (OsString, OsString); - fn next(&mut self) -> Option<(OsString, OsString)> { - self.iter.next() - } - fn size_hint(&self) -> (usize, Option) { - self.iter.size_hint() - } -} // Use `_NSGetEnviron` on Apple platforms. // @@ -112,7 +68,7 @@ pub fn env() -> Env { environ = environ.add(1); } } - return Env { iter: result.into_iter() }; + return Env::new(result); } fn parse(input: &[u8]) -> Option<(OsString, OsString)> { diff --git a/library/std/src/sys/env/wasi.rs b/library/std/src/sys/env/wasi.rs index 6bdb2d5a547a..3719f9db51eb 100644 --- a/library/std/src/sys/env/wasi.rs +++ b/library/std/src/sys/env/wasi.rs @@ -1,55 +1,11 @@ use core::slice::memchr; +pub use super::common::Env; use crate::ffi::{CStr, OsStr, OsString}; +use crate::io; use crate::os::wasi::prelude::*; use crate::sys::common::small_c_string::run_with_cstr; use crate::sys::pal::os::{cvt, libc}; -use crate::{fmt, io, vec}; - -pub struct Env { - iter: vec::IntoIter<(OsString, OsString)>, -} - -// FIXME(https://github.com/rust-lang/rust/issues/114583): Remove this when ::fmt matches ::fmt. -pub struct EnvStrDebug<'a> { - slice: &'a [(OsString, OsString)], -} - -impl fmt::Debug for EnvStrDebug<'_> { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - let Self { slice } = self; - f.debug_list() - .entries(slice.iter().map(|(a, b)| (a.to_str().unwrap(), b.to_str().unwrap()))) - .finish() - } -} - -impl Env { - pub fn str_debug(&self) -> impl fmt::Debug + '_ { - let Self { iter } = self; - EnvStrDebug { slice: iter.as_slice() } - } -} - -impl fmt::Debug for Env { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - let Self { iter } = self; - f.debug_list().entries(iter.as_slice()).finish() - } -} - -impl !Send for Env {} -impl !Sync for Env {} - -impl Iterator for Env { - type Item = (OsString, OsString); - fn next(&mut self) -> Option<(OsString, OsString)> { - self.iter.next() - } - fn size_hint(&self) -> (usize, Option) { - self.iter.size_hint() - } -} cfg_if::cfg_if! { if #[cfg(target_feature = "atomics")] { @@ -91,7 +47,7 @@ pub fn env() -> Env { environ = environ.add(1); } } - return Env { iter: result.into_iter() }; + return Env::new(result); } // See src/libstd/sys/pal/unix/os.rs, same as that diff --git a/library/std/src/sys/env/xous.rs b/library/std/src/sys/env/xous.rs index d5b8a1c7fb45..232a3dafb0be 100644 --- a/library/std/src/sys/env/xous.rs +++ b/library/std/src/sys/env/xous.rs @@ -1,9 +1,10 @@ +pub use super::common::Env; use crate::collections::HashMap; use crate::ffi::{OsStr, OsString}; +use crate::io; use crate::sync::atomic::{AtomicUsize, Ordering}; use crate::sync::{Mutex, Once}; use crate::sys::pal::os::{get_application_parameters, params}; -use crate::{fmt, io, vec}; static ENV: AtomicUsize = AtomicUsize::new(0); static ENV_INIT: Once = Once::new(); @@ -28,59 +29,13 @@ fn get_env_store() -> &'static EnvStore { unsafe { &*core::ptr::with_exposed_provenance::(ENV.load(Ordering::Relaxed)) } } -pub struct Env { - iter: vec::IntoIter<(OsString, OsString)>, -} - -// FIXME(https://github.com/rust-lang/rust/issues/114583): Remove this when ::fmt matches ::fmt. -pub struct EnvStrDebug<'a> { - slice: &'a [(OsString, OsString)], -} - -impl fmt::Debug for EnvStrDebug<'_> { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - let Self { slice } = self; - f.debug_list() - .entries(slice.iter().map(|(a, b)| (a.to_str().unwrap(), b.to_str().unwrap()))) - .finish() - } -} - -impl Env { - // FIXME(https://github.com/rust-lang/rust/issues/114583): Remove this when ::fmt matches ::fmt. - pub fn str_debug(&self) -> impl fmt::Debug + '_ { - let Self { iter } = self; - EnvStrDebug { slice: iter.as_slice() } - } -} - -impl fmt::Debug for Env { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - let Self { iter } = self; - f.debug_list().entries(iter.as_slice()).finish() - } -} - -impl !Send for Env {} -impl !Sync for Env {} - -impl Iterator for Env { - type Item = (OsString, OsString); - fn next(&mut self) -> Option<(OsString, OsString)> { - self.iter.next() - } - fn size_hint(&self) -> (usize, Option) { - self.iter.size_hint() - } -} - pub fn env() -> Env { let clone_to_vec = |map: &HashMap| -> Vec<_> { map.iter().map(|(k, v)| (k.clone(), v.clone())).collect() }; - let iter = clone_to_vec(&*get_env_store().lock().unwrap()).into_iter(); - Env { iter } + let env = clone_to_vec(&*get_env_store().lock().unwrap()); + Env::new(env) } pub fn getenv(k: &OsStr) -> Option {