diff options
Diffstat (limited to 'library/std/src')
176 files changed, 2967 insertions, 2454 deletions
diff --git a/library/std/src/alloc.rs b/library/std/src/alloc.rs index 5d2a304b41c..b574e9f3a25 100644 --- a/library/std/src/alloc.rs +++ b/library/std/src/alloc.rs @@ -57,7 +57,7 @@ #![stable(feature = "alloc_module", since = "1.28.0")] use core::ptr::NonNull; -use core::sync::atomic::{AtomicPtr, Ordering}; +use core::sync::atomic::{Atomic, AtomicPtr, Ordering}; use core::{hint, mem, ptr}; #[stable(feature = "alloc_module", since = "1.28.0")] @@ -287,7 +287,7 @@ unsafe impl Allocator for System { } } -static HOOK: AtomicPtr<()> = AtomicPtr::new(ptr::null_mut()); +static HOOK: Atomic<*mut ()> = AtomicPtr::new(ptr::null_mut()); /// Registers a custom allocation error hook, replacing any that was previously registered. /// @@ -348,7 +348,7 @@ fn default_alloc_error_hook(layout: Layout) { unsafe extern "Rust" { // This symbol is emitted by rustc next to __rust_alloc_error_handler. // Its value depends on the -Zoom={panic,abort} compiler option. - #[cfg_attr(not(bootstrap), rustc_std_internal_symbol)] + #[rustc_std_internal_symbol] static __rust_alloc_error_handler_should_panic: u8; } diff --git a/library/std/src/backtrace.rs b/library/std/src/backtrace.rs index 3e641ac5d90..c3fcb0e2e42 100644 --- a/library/std/src/backtrace.rs +++ b/library/std/src/backtrace.rs @@ -92,8 +92,8 @@ use crate::backtrace_rs::{self, BytesOrWideString}; use crate::ffi::c_void; use crate::panic::UnwindSafe; use crate::sync::LazyLock; -use crate::sync::atomic::AtomicU8; use crate::sync::atomic::Ordering::Relaxed; +use crate::sync::atomic::{Atomic, AtomicU8}; use crate::sys::backtrace::{lock, output_filename, set_image_base}; use crate::{env, fmt}; @@ -254,7 +254,7 @@ impl Backtrace { // Cache the result of reading the environment variables to make // backtrace captures speedy, because otherwise reading environment // variables every time can be somewhat slow. - static ENABLED: AtomicU8 = AtomicU8::new(0); + static ENABLED: Atomic<u8> = AtomicU8::new(0); match ENABLED.load(Relaxed) { 0 => {} 1 => return false, @@ -432,7 +432,7 @@ mod helper { use super::*; pub(super) type LazyResolve = impl (FnOnce() -> Capture) + Send + Sync + UnwindSafe; - #[cfg_attr(not(bootstrap), define_opaque(LazyResolve))] + #[define_opaque(LazyResolve)] pub(super) fn lazy_resolve(mut capture: Capture) -> LazyResolve { move || { // Use the global backtrace lock to synchronize this as it's a diff --git a/library/std/src/collections/hash/map.rs b/library/std/src/collections/hash/map.rs index 2487f5a2a50..9ad26e5d28e 100644 --- a/library/std/src/collections/hash/map.rs +++ b/library/std/src/collections/hash/map.rs @@ -683,7 +683,7 @@ impl<K, V, S> HashMap<K, V, S> { /// ``` #[inline] #[rustc_lint_query_instability] - #[stable(feature = "hash_extract_if", since = "CURRENT_RUSTC_VERSION")] + #[stable(feature = "hash_extract_if", since = "1.87.0")] pub fn extract_if<F>(&mut self, pred: F) -> ExtractIf<'_, K, V, F> where F: FnMut(&K, &mut V) -> bool, @@ -973,6 +973,9 @@ where /// Returns an array of length `N` with the results of each query. For soundness, at most one /// mutable reference will be returned to any value. `None` will be used if the key is missing. /// + /// This method performs a check to ensure there are no duplicate keys, which currently has a time-complexity of O(n^2), + /// so be careful when passing many keys. + /// /// # Panics /// /// Panics if any keys are overlapping. @@ -1677,7 +1680,7 @@ impl<'a, K, V> Drain<'a, K, V> { /// ]); /// let iter = map.extract_if(|_k, v| *v % 2 == 0); /// ``` -#[stable(feature = "hash_extract_if", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "hash_extract_if", since = "1.87.0")] #[must_use = "iterators are lazy and do nothing unless consumed"] pub struct ExtractIf<'a, K, V, F> where @@ -2294,7 +2297,7 @@ where } } -#[stable(feature = "hash_extract_if", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "hash_extract_if", since = "1.87.0")] impl<K, V, F> Iterator for ExtractIf<'_, K, V, F> where F: FnMut(&K, &mut V) -> bool, @@ -2311,10 +2314,10 @@ where } } -#[stable(feature = "hash_extract_if", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "hash_extract_if", since = "1.87.0")] impl<K, V, F> FusedIterator for ExtractIf<'_, K, V, F> where F: FnMut(&K, &mut V) -> bool {} -#[stable(feature = "hash_extract_if", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "hash_extract_if", since = "1.87.0")] impl<'a, K, V, F> fmt::Debug for ExtractIf<'a, K, V, F> where F: FnMut(&K, &mut V) -> bool, diff --git a/library/std/src/collections/hash/set.rs b/library/std/src/collections/hash/set.rs index a547a9943c1..7be000594bc 100644 --- a/library/std/src/collections/hash/set.rs +++ b/library/std/src/collections/hash/set.rs @@ -308,7 +308,7 @@ impl<T, S> HashSet<T, S> { /// ``` #[inline] #[rustc_lint_query_instability] - #[stable(feature = "hash_extract_if", since = "CURRENT_RUSTC_VERSION")] + #[stable(feature = "hash_extract_if", since = "1.87.0")] pub fn extract_if<F>(&mut self, pred: F) -> ExtractIf<'_, T, F> where F: FnMut(&T) -> bool, @@ -1390,7 +1390,7 @@ pub struct Drain<'a, K: 'a> { /// /// let mut extract_ifed = a.extract_if(|v| v % 2 == 0); /// ``` -#[stable(feature = "hash_extract_if", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "hash_extract_if", since = "1.87.0")] pub struct ExtractIf<'a, K, F> where F: FnMut(&K) -> bool, @@ -1673,7 +1673,7 @@ impl<K: fmt::Debug> fmt::Debug for Drain<'_, K> { } } -#[stable(feature = "hash_extract_if", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "hash_extract_if", since = "1.87.0")] impl<K, F> Iterator for ExtractIf<'_, K, F> where F: FnMut(&K) -> bool, @@ -1690,10 +1690,10 @@ where } } -#[stable(feature = "hash_extract_if", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "hash_extract_if", since = "1.87.0")] impl<K, F> FusedIterator for ExtractIf<'_, K, F> where F: FnMut(&K) -> bool {} -#[stable(feature = "hash_extract_if", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "hash_extract_if", since = "1.87.0")] impl<'a, K, F> fmt::Debug for ExtractIf<'a, K, F> where F: FnMut(&K) -> bool, diff --git a/library/std/src/env.rs b/library/std/src/env.rs index 05bd4345ea8..1593969e114 100644 --- a/library/std/src/env.rs +++ b/library/std/src/env.rs @@ -13,7 +13,7 @@ use crate::error::Error; use crate::ffi::{OsStr, OsString}; use crate::path::{Path, PathBuf}; -use crate::sys::os as os_imp; +use crate::sys::{env as env_imp, os as os_imp}; use crate::{fmt, io, sys}; /// Returns the current working directory as a [`PathBuf`]. @@ -96,7 +96,7 @@ pub struct Vars { /// [`env::vars_os()`]: vars_os #[stable(feature = "env", since = "1.0.0")] pub struct VarsOs { - inner: os_imp::Env, + inner: env_imp::Env, } /// Returns an iterator of (variable, value) pairs of strings, for all the @@ -150,7 +150,7 @@ pub fn vars() -> Vars { #[must_use] #[stable(feature = "env", since = "1.0.0")] pub fn vars_os() -> VarsOs { - VarsOs { inner: os_imp::env() } + VarsOs { inner: env_imp::env() } } #[stable(feature = "env", since = "1.0.0")] @@ -259,7 +259,7 @@ pub fn var_os<K: AsRef<OsStr>>(key: K) -> Option<OsString> { } fn _var_os(key: &OsStr) -> Option<OsString> { - os_imp::getenv(key) + env_imp::getenv(key) } /// The error type for operations interacting with environment variables. @@ -363,7 +363,7 @@ impl Error for VarError { #[stable(feature = "env", since = "1.0.0")] pub unsafe fn set_var<K: AsRef<OsStr>, V: AsRef<OsStr>>(key: K, value: V) { let (key, value) = (key.as_ref(), value.as_ref()); - unsafe { os_imp::setenv(key, value) }.unwrap_or_else(|e| { + unsafe { env_imp::setenv(key, value) }.unwrap_or_else(|e| { panic!("failed to set environment variable `{key:?}` to `{value:?}`: {e}") }) } @@ -434,7 +434,7 @@ pub unsafe fn set_var<K: AsRef<OsStr>, V: AsRef<OsStr>>(key: K, value: V) { #[stable(feature = "env", since = "1.0.0")] pub unsafe fn remove_var<K: AsRef<OsStr>>(key: K) { let key = key.as_ref(); - unsafe { os_imp::unsetenv(key) } + unsafe { env_imp::unsetenv(key) } .unwrap_or_else(|e| panic!("failed to remove environment variable `{key:?}`: {e}")) } @@ -950,7 +950,7 @@ impl fmt::Debug for ArgsOs { /// Constants associated with the current target #[stable(feature = "env", since = "1.0.0")] pub mod consts { - use crate::sys::env::os; + use crate::sys::env_consts::os; /// A string describing the architecture of the CPU that is currently in use. /// An example value may be: `"x86"`, `"arm"` or `"riscv64"`. diff --git a/library/std/src/f128.rs b/library/std/src/f128.rs index ede21969051..2b416b13fa5 100644 --- a/library/std/src/f128.rs +++ b/library/std/src/f128.rs @@ -22,7 +22,11 @@ impl f128 { /// /// ``` /// #![feature(f128)] - /// # #[cfg(reliable_f128_math)] { + /// # #![cfg_attr(not(bootstrap), feature(cfg_target_has_reliable_f16_f128))] + /// # #![cfg_attr(not(bootstrap), expect(internal_features))] + /// # #[cfg(not(miri))] + /// # #[cfg(not(bootstrap))] + /// # #[cfg(target_has_reliable_f128_math)] { /// /// let f = 3.7_f128; /// let g = 3.0_f128; @@ -49,7 +53,11 @@ impl f128 { /// /// ``` /// #![feature(f128)] - /// # #[cfg(reliable_f128_math)] { + /// # #![cfg_attr(not(bootstrap), feature(cfg_target_has_reliable_f16_f128))] + /// # #![cfg_attr(not(bootstrap), expect(internal_features))] + /// # #[cfg(not(miri))] + /// # #[cfg(not(bootstrap))] + /// # #[cfg(target_has_reliable_f128_math)] { /// /// let f = 3.01_f128; /// let g = 4.0_f128; @@ -76,7 +84,11 @@ impl f128 { /// /// ``` /// #![feature(f128)] - /// # #[cfg(reliable_f128_math)] { + /// # #![cfg_attr(not(bootstrap), feature(cfg_target_has_reliable_f16_f128))] + /// # #![cfg_attr(not(bootstrap), expect(internal_features))] + /// # #[cfg(not(miri))] + /// # #[cfg(not(bootstrap))] + /// # #[cfg(target_has_reliable_f128_math)] { /// /// let f = 3.3_f128; /// let g = -3.3_f128; @@ -108,7 +120,11 @@ impl f128 { /// /// ``` /// #![feature(f128)] - /// # #[cfg(reliable_f128_math)] { + /// # #![cfg_attr(not(bootstrap), feature(cfg_target_has_reliable_f16_f128))] + /// # #![cfg_attr(not(bootstrap), expect(internal_features))] + /// # #[cfg(not(miri))] + /// # #[cfg(not(bootstrap))] + /// # #[cfg(target_has_reliable_f128_math)] { /// /// let f = 3.3_f128; /// let g = -3.3_f128; @@ -138,7 +154,11 @@ impl f128 { /// /// ``` /// #![feature(f128)] - /// # #[cfg(reliable_f128_math)] { + /// # #![cfg_attr(not(bootstrap), feature(cfg_target_has_reliable_f16_f128))] + /// # #![cfg_attr(not(bootstrap), expect(internal_features))] + /// # #[cfg(not(miri))] + /// # #[cfg(not(bootstrap))] + /// # #[cfg(target_has_reliable_f128_math)] { /// /// let f = 3.7_f128; /// let g = 3.0_f128; @@ -166,7 +186,11 @@ impl f128 { /// /// ``` /// #![feature(f128)] - /// # #[cfg(reliable_f128_math)] { + /// # #![cfg_attr(not(bootstrap), feature(cfg_target_has_reliable_f16_f128))] + /// # #![cfg_attr(not(bootstrap), expect(internal_features))] + /// # #[cfg(not(miri))] + /// # #[cfg(not(bootstrap))] + /// # #[cfg(target_has_reliable_f128_math)] { /// /// let x = 3.6_f128; /// let y = -3.6_f128; @@ -203,7 +227,11 @@ impl f128 { /// /// ``` /// #![feature(f128)] - /// # #[cfg(reliable_f128_math)] { + /// # #![cfg_attr(not(bootstrap), feature(cfg_target_has_reliable_f16_f128))] + /// # #![cfg_attr(not(bootstrap), expect(internal_features))] + /// # #[cfg(not(miri))] + /// # #[cfg(not(bootstrap))] + /// # #[cfg(target_has_reliable_f128_math)] { /// /// let m = 10.0_f128; /// let x = 4.0_f128; @@ -247,7 +275,11 @@ impl f128 { /// /// ``` /// #![feature(f128)] - /// # #[cfg(reliable_f128_math)] { + /// # #![cfg_attr(not(bootstrap), feature(cfg_target_has_reliable_f16_f128))] + /// # #![cfg_attr(not(bootstrap), expect(internal_features))] + /// # #[cfg(not(miri))] + /// # #[cfg(not(bootstrap))] + /// # #[cfg(target_has_reliable_f128_math)] { /// /// let a: f128 = 7.0; /// let b = 4.0; @@ -289,7 +321,11 @@ impl f128 { /// /// ``` /// #![feature(f128)] - /// # #[cfg(reliable_f128_math)] { + /// # #![cfg_attr(not(bootstrap), feature(cfg_target_has_reliable_f16_f128))] + /// # #![cfg_attr(not(bootstrap), expect(internal_features))] + /// # #[cfg(not(miri))] + /// # #[cfg(not(bootstrap))] + /// # #[cfg(target_has_reliable_f128_math)] { /// /// let a: f128 = 7.0; /// let b = 4.0; @@ -326,7 +362,11 @@ impl f128 { /// /// ``` /// #![feature(f128)] - /// # #[cfg(reliable_f128_math)] { + /// # #![cfg_attr(not(bootstrap), feature(cfg_target_has_reliable_f16_f128))] + /// # #![cfg_attr(not(bootstrap), expect(internal_features))] + /// # #[cfg(not(miri))] + /// # #[cfg(not(bootstrap))] + /// # #[cfg(target_has_reliable_f128_math)] { /// /// let x = 2.0_f128; /// let abs_difference = (x.powi(2) - (x * x)).abs(); @@ -354,7 +394,11 @@ impl f128 { /// /// ``` /// #![feature(f128)] - /// # #[cfg(reliable_f128_math)] { + /// # #![cfg_attr(not(bootstrap), feature(cfg_target_has_reliable_f16_f128))] + /// # #![cfg_attr(not(bootstrap), expect(internal_features))] + /// # #[cfg(not(miri))] + /// # #[cfg(not(bootstrap))] + /// # #[cfg(target_has_reliable_f128_math)] { /// /// let x = 2.0_f128; /// let abs_difference = (x.powf(2.0) - (x * x)).abs(); @@ -386,7 +430,11 @@ impl f128 { /// /// ``` /// #![feature(f128)] - /// # #[cfg(reliable_f128_math)] { + /// # #![cfg_attr(not(bootstrap), feature(cfg_target_has_reliable_f16_f128))] + /// # #![cfg_attr(not(bootstrap), expect(internal_features))] + /// # #[cfg(not(miri))] + /// # #[cfg(not(bootstrap))] + /// # #[cfg(target_has_reliable_f128_math)] { /// /// let positive = 4.0_f128; /// let negative = -4.0_f128; @@ -417,7 +465,11 @@ impl f128 { /// /// ``` /// #![feature(f128)] - /// # #[cfg(reliable_f128_math)] { + /// # #![cfg_attr(not(bootstrap), feature(cfg_target_has_reliable_f16_f128))] + /// # #![cfg_attr(not(bootstrap), expect(internal_features))] + /// # #[cfg(not(miri))] + /// # #[cfg(not(bootstrap))] + /// # #[cfg(target_has_reliable_f128_math)] { /// /// let one = 1.0f128; /// // e^1 @@ -448,7 +500,11 @@ impl f128 { /// /// ``` /// #![feature(f128)] - /// # #[cfg(reliable_f128_math)] { + /// # #![cfg_attr(not(bootstrap), feature(cfg_target_has_reliable_f16_f128))] + /// # #![cfg_attr(not(bootstrap), expect(internal_features))] + /// # #[cfg(not(miri))] + /// # #[cfg(not(bootstrap))] + /// # #[cfg(target_has_reliable_f128_math)] { /// /// let f = 2.0f128; /// @@ -479,7 +535,11 @@ impl f128 { /// /// ``` /// #![feature(f128)] - /// # #[cfg(reliable_f128_math)] { + /// # #![cfg_attr(not(bootstrap), feature(cfg_target_has_reliable_f16_f128))] + /// # #![cfg_attr(not(bootstrap), expect(internal_features))] + /// # #[cfg(not(miri))] + /// # #[cfg(not(bootstrap))] + /// # #[cfg(target_has_reliable_f128_math)] { /// /// let one = 1.0f128; /// // e^1 @@ -495,7 +555,11 @@ impl f128 { /// Non-positive values: /// ``` /// #![feature(f128)] - /// # #[cfg(reliable_f128_math)] { + /// # #![cfg_attr(not(bootstrap), feature(cfg_target_has_reliable_f16_f128))] + /// # #![cfg_attr(not(bootstrap), expect(internal_features))] + /// # #[cfg(not(miri))] + /// # #[cfg(not(bootstrap))] + /// # #[cfg(target_has_reliable_f128_math)] { /// /// assert_eq!(0_f128.ln(), f128::NEG_INFINITY); /// assert!((-42_f128).ln().is_nan()); @@ -526,7 +590,11 @@ impl f128 { /// /// ``` /// #![feature(f128)] - /// # #[cfg(reliable_f128_math)] { + /// # #![cfg_attr(not(bootstrap), feature(cfg_target_has_reliable_f16_f128))] + /// # #![cfg_attr(not(bootstrap), expect(internal_features))] + /// # #[cfg(not(miri))] + /// # #[cfg(not(bootstrap))] + /// # #[cfg(target_has_reliable_f128_math)] { /// /// let five = 5.0f128; /// @@ -540,7 +608,11 @@ impl f128 { /// Non-positive values: /// ``` /// #![feature(f128)] - /// # #[cfg(reliable_f128_math)] { + /// # #![cfg_attr(not(bootstrap), feature(cfg_target_has_reliable_f16_f128))] + /// # #![cfg_attr(not(bootstrap), expect(internal_features))] + /// # #[cfg(not(miri))] + /// # #[cfg(not(bootstrap))] + /// # #[cfg(target_has_reliable_f128_math)] { /// /// assert_eq!(0_f128.log(10.0), f128::NEG_INFINITY); /// assert!((-42_f128).log(10.0).is_nan()); @@ -567,7 +639,11 @@ impl f128 { /// /// ``` /// #![feature(f128)] - /// # #[cfg(reliable_f128_math)] { + /// # #![cfg_attr(not(bootstrap), feature(cfg_target_has_reliable_f16_f128))] + /// # #![cfg_attr(not(bootstrap), expect(internal_features))] + /// # #[cfg(not(miri))] + /// # #[cfg(not(bootstrap))] + /// # #[cfg(target_has_reliable_f128_math)] { /// /// let two = 2.0f128; /// @@ -581,7 +657,11 @@ impl f128 { /// Non-positive values: /// ``` /// #![feature(f128)] - /// # #[cfg(reliable_f128_math)] { + /// # #![cfg_attr(not(bootstrap), feature(cfg_target_has_reliable_f16_f128))] + /// # #![cfg_attr(not(bootstrap), expect(internal_features))] + /// # #[cfg(not(miri))] + /// # #[cfg(not(bootstrap))] + /// # #[cfg(target_has_reliable_f128_math)] { /// /// assert_eq!(0_f128.log2(), f128::NEG_INFINITY); /// assert!((-42_f128).log2().is_nan()); @@ -608,7 +688,11 @@ impl f128 { /// /// ``` /// #![feature(f128)] - /// # #[cfg(reliable_f128_math)] { + /// # #![cfg_attr(not(bootstrap), feature(cfg_target_has_reliable_f16_f128))] + /// # #![cfg_attr(not(bootstrap), expect(internal_features))] + /// # #[cfg(not(miri))] + /// # #[cfg(not(bootstrap))] + /// # #[cfg(target_has_reliable_f128_math)] { /// /// let ten = 10.0f128; /// @@ -622,7 +706,11 @@ impl f128 { /// Non-positive values: /// ``` /// #![feature(f128)] - /// # #[cfg(reliable_f128_math)] { + /// # #![cfg_attr(not(bootstrap), feature(cfg_target_has_reliable_f16_f128))] + /// # #![cfg_attr(not(bootstrap), expect(internal_features))] + /// # #[cfg(not(miri))] + /// # #[cfg(not(bootstrap))] + /// # #[cfg(target_has_reliable_f128_math)] { /// /// assert_eq!(0_f128.log10(), f128::NEG_INFINITY); /// assert!((-42_f128).log10().is_nan()); @@ -651,7 +739,11 @@ impl f128 { /// /// ``` /// #![feature(f128)] - /// # #[cfg(reliable_f128_math)] { + /// # #![cfg_attr(not(bootstrap), feature(cfg_target_has_reliable_f16_f128))] + /// # #![cfg_attr(not(bootstrap), expect(internal_features))] + /// # #[cfg(not(miri))] + /// # #[cfg(not(bootstrap))] + /// # #[cfg(target_has_reliable_f128_math)] { /// /// let x = 8.0f128; /// @@ -666,7 +758,7 @@ impl f128 { #[unstable(feature = "f128", issue = "116909")] #[must_use = "method returns a new number and does not mutate the original value"] pub fn cbrt(self) -> f128 { - unsafe { cmath::cbrtf128(self) } + cmath::cbrtf128(self) } /// Compute the distance between the origin and a point (`x`, `y`) on the @@ -687,7 +779,11 @@ impl f128 { /// /// ``` /// #![feature(f128)] - /// # #[cfg(reliable_f128_math)] { + /// # #![cfg_attr(not(bootstrap), feature(cfg_target_has_reliable_f16_f128))] + /// # #![cfg_attr(not(bootstrap), expect(internal_features))] + /// # #[cfg(not(miri))] + /// # #[cfg(not(bootstrap))] + /// # #[cfg(target_has_reliable_f128_math)] { /// /// let x = 2.0f128; /// let y = 3.0f128; @@ -703,7 +799,7 @@ impl f128 { #[unstable(feature = "f128", issue = "116909")] #[must_use = "method returns a new number and does not mutate the original value"] pub fn hypot(self, other: f128) -> f128 { - unsafe { cmath::hypotf128(self, other) } + cmath::hypotf128(self, other) } /// Computes the sine of a number (in radians). @@ -717,7 +813,11 @@ impl f128 { /// /// ``` /// #![feature(f128)] - /// # #[cfg(reliable_f128_math)] { + /// # #![cfg_attr(not(bootstrap), feature(cfg_target_has_reliable_f16_f128))] + /// # #![cfg_attr(not(bootstrap), expect(internal_features))] + /// # #[cfg(not(miri))] + /// # #[cfg(not(bootstrap))] + /// # #[cfg(target_has_reliable_f128_math)] { /// /// let x = std::f128::consts::FRAC_PI_2; /// @@ -745,7 +845,11 @@ impl f128 { /// /// ``` /// #![feature(f128)] - /// # #[cfg(reliable_f128_math)] { + /// # #![cfg_attr(not(bootstrap), feature(cfg_target_has_reliable_f16_f128))] + /// # #![cfg_attr(not(bootstrap), expect(internal_features))] + /// # #[cfg(not(miri))] + /// # #[cfg(not(bootstrap))] + /// # #[cfg(target_has_reliable_f128_math)] { /// /// let x = 2.0 * std::f128::consts::PI; /// @@ -776,7 +880,11 @@ impl f128 { /// /// ``` /// #![feature(f128)] - /// # #[cfg(reliable_f128_math)] { + /// # #![cfg_attr(not(bootstrap), feature(cfg_target_has_reliable_f16_f128))] + /// # #![cfg_attr(not(bootstrap), expect(internal_features))] + /// # #[cfg(not(miri))] + /// # #[cfg(not(bootstrap))] + /// # #[cfg(target_has_reliable_f128_math)] { /// /// let x = std::f128::consts::FRAC_PI_4; /// let abs_difference = (x.tan() - 1.0).abs(); @@ -789,7 +897,7 @@ impl f128 { #[unstable(feature = "f128", issue = "116909")] #[must_use = "method returns a new number and does not mutate the original value"] pub fn tan(self) -> f128 { - unsafe { cmath::tanf128(self) } + cmath::tanf128(self) } /// Computes the arcsine of a number. Return value is in radians in @@ -808,7 +916,11 @@ impl f128 { /// /// ``` /// #![feature(f128)] - /// # #[cfg(reliable_f128_math)] { + /// # #![cfg_attr(not(bootstrap), feature(cfg_target_has_reliable_f16_f128))] + /// # #![cfg_attr(not(bootstrap), expect(internal_features))] + /// # #[cfg(not(miri))] + /// # #[cfg(not(bootstrap))] + /// # #[cfg(target_has_reliable_f128_math)] { /// /// let f = std::f128::consts::FRAC_PI_2; /// @@ -824,7 +936,7 @@ impl f128 { #[unstable(feature = "f128", issue = "116909")] #[must_use = "method returns a new number and does not mutate the original value"] pub fn asin(self) -> f128 { - unsafe { cmath::asinf128(self) } + cmath::asinf128(self) } /// Computes the arccosine of a number. Return value is in radians in @@ -843,7 +955,11 @@ impl f128 { /// /// ``` /// #![feature(f128)] - /// # #[cfg(reliable_f128_math)] { + /// # #![cfg_attr(not(bootstrap), feature(cfg_target_has_reliable_f16_f128))] + /// # #![cfg_attr(not(bootstrap), expect(internal_features))] + /// # #[cfg(not(miri))] + /// # #[cfg(not(bootstrap))] + /// # #[cfg(target_has_reliable_f128_math)] { /// /// let f = std::f128::consts::FRAC_PI_4; /// @@ -859,7 +975,7 @@ impl f128 { #[unstable(feature = "f128", issue = "116909")] #[must_use = "method returns a new number and does not mutate the original value"] pub fn acos(self) -> f128 { - unsafe { cmath::acosf128(self) } + cmath::acosf128(self) } /// Computes the arctangent of a number. Return value is in radians in the @@ -877,7 +993,11 @@ impl f128 { /// /// ``` /// #![feature(f128)] - /// # #[cfg(reliable_f128_math)] { + /// # #![cfg_attr(not(bootstrap), feature(cfg_target_has_reliable_f16_f128))] + /// # #![cfg_attr(not(bootstrap), expect(internal_features))] + /// # #[cfg(not(miri))] + /// # #[cfg(not(bootstrap))] + /// # #[cfg(target_has_reliable_f128_math)] { /// /// let f = 1.0f128; /// @@ -893,7 +1013,7 @@ impl f128 { #[unstable(feature = "f128", issue = "116909")] #[must_use = "method returns a new number and does not mutate the original value"] pub fn atan(self) -> f128 { - unsafe { cmath::atanf128(self) } + cmath::atanf128(self) } /// Computes the four quadrant arctangent of `self` (`y`) and `other` (`x`) in radians. @@ -915,7 +1035,11 @@ impl f128 { /// /// ``` /// #![feature(f128)] - /// # #[cfg(reliable_f128_math)] { + /// # #![cfg_attr(not(bootstrap), feature(cfg_target_has_reliable_f16_f128))] + /// # #![cfg_attr(not(bootstrap), expect(internal_features))] + /// # #[cfg(not(miri))] + /// # #[cfg(not(bootstrap))] + /// # #[cfg(target_has_reliable_f128_math)] { /// /// // Positive angles measured counter-clockwise /// // from positive x axis @@ -939,7 +1063,7 @@ impl f128 { #[unstable(feature = "f128", issue = "116909")] #[must_use = "method returns a new number and does not mutate the original value"] pub fn atan2(self, other: f128) -> f128 { - unsafe { cmath::atan2f128(self, other) } + cmath::atan2f128(self, other) } /// Simultaneously computes the sine and cosine of the number, `x`. Returns @@ -957,7 +1081,11 @@ impl f128 { /// /// ``` /// #![feature(f128)] - /// # #[cfg(reliable_f128_math)] { + /// # #![cfg_attr(not(bootstrap), feature(cfg_target_has_reliable_f16_f128))] + /// # #![cfg_attr(not(bootstrap), expect(internal_features))] + /// # #[cfg(not(miri))] + /// # #[cfg(not(bootstrap))] + /// # #[cfg(target_has_reliable_f128_math)] { /// /// let x = std::f128::consts::FRAC_PI_4; /// let f = x.sin_cos(); @@ -992,7 +1120,11 @@ impl f128 { /// /// ``` /// #![feature(f128)] - /// # #[cfg(reliable_f128_math)] { + /// # #![cfg_attr(not(bootstrap), feature(cfg_target_has_reliable_f16_f128))] + /// # #![cfg_attr(not(bootstrap), expect(internal_features))] + /// # #[cfg(not(miri))] + /// # #[cfg(not(bootstrap))] + /// # #[cfg(target_has_reliable_f128_math)] { /// /// let x = 1e-8_f128; /// @@ -1008,7 +1140,7 @@ impl f128 { #[unstable(feature = "f128", issue = "116909")] #[must_use = "method returns a new number and does not mutate the original value"] pub fn exp_m1(self) -> f128 { - unsafe { cmath::expm1f128(self) } + cmath::expm1f128(self) } /// Returns `ln(1+n)` (natural logarithm) more accurately than if @@ -1028,7 +1160,11 @@ impl f128 { /// /// ``` /// #![feature(f128)] - /// # #[cfg(reliable_f128_math)] { + /// # #![cfg_attr(not(bootstrap), feature(cfg_target_has_reliable_f16_f128))] + /// # #![cfg_attr(not(bootstrap), expect(internal_features))] + /// # #[cfg(not(miri))] + /// # #[cfg(not(bootstrap))] + /// # #[cfg(target_has_reliable_f128_math)] { /// /// let x = 1e-8_f128; /// @@ -1043,7 +1179,11 @@ impl f128 { /// Out-of-range values: /// ``` /// #![feature(f128)] - /// # #[cfg(reliable_f128_math)] { + /// # #![cfg_attr(not(bootstrap), feature(cfg_target_has_reliable_f16_f128))] + /// # #![cfg_attr(not(bootstrap), expect(internal_features))] + /// # #[cfg(not(miri))] + /// # #[cfg(not(bootstrap))] + /// # #[cfg(target_has_reliable_f128_math)] { /// /// assert_eq!((-1.0_f128).ln_1p(), f128::NEG_INFINITY); /// assert!((-2.0_f128).ln_1p().is_nan()); @@ -1055,7 +1195,7 @@ impl f128 { #[rustc_allow_incoherent_impl] #[unstable(feature = "f128", issue = "116909")] pub fn ln_1p(self) -> f128 { - unsafe { cmath::log1pf128(self) } + cmath::log1pf128(self) } /// Hyperbolic sine function. @@ -1072,7 +1212,11 @@ impl f128 { /// /// ``` /// #![feature(f128)] - /// # #[cfg(reliable_f128_math)] { + /// # #![cfg_attr(not(bootstrap), feature(cfg_target_has_reliable_f16_f128))] + /// # #![cfg_attr(not(bootstrap), expect(internal_features))] + /// # #[cfg(not(miri))] + /// # #[cfg(not(bootstrap))] + /// # #[cfg(target_has_reliable_f128_math)] { /// /// let e = std::f128::consts::E; /// let x = 1.0f128; @@ -1090,7 +1234,7 @@ impl f128 { #[unstable(feature = "f128", issue = "116909")] #[must_use = "method returns a new number and does not mutate the original value"] pub fn sinh(self) -> f128 { - unsafe { cmath::sinhf128(self) } + cmath::sinhf128(self) } /// Hyperbolic cosine function. @@ -1107,7 +1251,11 @@ impl f128 { /// /// ``` /// #![feature(f128)] - /// # #[cfg(reliable_f128_math)] { + /// # #![cfg_attr(not(bootstrap), feature(cfg_target_has_reliable_f16_f128))] + /// # #![cfg_attr(not(bootstrap), expect(internal_features))] + /// # #[cfg(not(miri))] + /// # #[cfg(not(bootstrap))] + /// # #[cfg(target_has_reliable_f128_math)] { /// /// let e = std::f128::consts::E; /// let x = 1.0f128; @@ -1125,7 +1273,7 @@ impl f128 { #[unstable(feature = "f128", issue = "116909")] #[must_use = "method returns a new number and does not mutate the original value"] pub fn cosh(self) -> f128 { - unsafe { cmath::coshf128(self) } + cmath::coshf128(self) } /// Hyperbolic tangent function. @@ -1142,7 +1290,11 @@ impl f128 { /// /// ``` /// #![feature(f128)] - /// # #[cfg(reliable_f128_math)] { + /// # #![cfg_attr(not(bootstrap), feature(cfg_target_has_reliable_f16_f128))] + /// # #![cfg_attr(not(bootstrap), expect(internal_features))] + /// # #[cfg(not(miri))] + /// # #[cfg(not(bootstrap))] + /// # #[cfg(target_has_reliable_f128_math)] { /// /// let e = std::f128::consts::E; /// let x = 1.0f128; @@ -1160,7 +1312,7 @@ impl f128 { #[unstable(feature = "f128", issue = "116909")] #[must_use = "method returns a new number and does not mutate the original value"] pub fn tanh(self) -> f128 { - unsafe { cmath::tanhf128(self) } + cmath::tanhf128(self) } /// Inverse hyperbolic sine function. @@ -1174,7 +1326,11 @@ impl f128 { /// /// ``` /// #![feature(f128)] - /// # #[cfg(reliable_f128_math)] { + /// # #![cfg_attr(not(bootstrap), feature(cfg_target_has_reliable_f16_f128))] + /// # #![cfg_attr(not(bootstrap), expect(internal_features))] + /// # #[cfg(not(miri))] + /// # #[cfg(not(bootstrap))] + /// # #[cfg(target_has_reliable_f128_math)] { /// /// let x = 1.0f128; /// let f = x.sinh().asinh(); @@ -1206,7 +1362,11 @@ impl f128 { /// /// ``` /// #![feature(f128)] - /// # #[cfg(reliable_f128_math)] { + /// # #![cfg_attr(not(bootstrap), feature(cfg_target_has_reliable_f16_f128))] + /// # #![cfg_attr(not(bootstrap), expect(internal_features))] + /// # #[cfg(not(miri))] + /// # #[cfg(not(bootstrap))] + /// # #[cfg(target_has_reliable_f128_math)] { /// /// let x = 1.0f128; /// let f = x.cosh().acosh(); @@ -1240,7 +1400,11 @@ impl f128 { /// /// ``` /// #![feature(f128)] - /// # #[cfg(reliable_f128_math)] { + /// # #![cfg_attr(not(bootstrap), feature(cfg_target_has_reliable_f16_f128))] + /// # #![cfg_attr(not(bootstrap), expect(internal_features))] + /// # #[cfg(not(miri))] + /// # #[cfg(not(bootstrap))] + /// # #[cfg(target_has_reliable_f128_math)] { /// /// let e = std::f128::consts::E; /// let f = e.tanh().atanh(); @@ -1274,7 +1438,11 @@ impl f128 { /// ``` /// #![feature(f128)] /// #![feature(float_gamma)] - /// # #[cfg(reliable_f128_math)] { + /// # #![cfg_attr(not(bootstrap), feature(cfg_target_has_reliable_f16_f128))] + /// # #![cfg_attr(not(bootstrap), expect(internal_features))] + /// # #[cfg(not(miri))] + /// # #[cfg(not(bootstrap))] + /// # #[cfg(target_has_reliable_f128_math)] { /// /// let x = 5.0f128; /// @@ -1289,7 +1457,7 @@ impl f128 { // #[unstable(feature = "float_gamma", issue = "99842")] #[must_use = "method returns a new number and does not mutate the original value"] pub fn gamma(self) -> f128 { - unsafe { cmath::tgammaf128(self) } + cmath::tgammaf128(self) } /// Natural logarithm of the absolute value of the gamma function @@ -1309,7 +1477,11 @@ impl f128 { /// ``` /// #![feature(f128)] /// #![feature(float_gamma)] - /// # #[cfg(reliable_f128_math)] { + /// # #![cfg_attr(not(bootstrap), feature(cfg_target_has_reliable_f16_f128))] + /// # #![cfg_attr(not(bootstrap), expect(internal_features))] + /// # #[cfg(not(miri))] + /// # #[cfg(not(bootstrap))] + /// # #[cfg(target_has_reliable_f128_math)] { /// /// let x = 2.0f128; /// @@ -1325,7 +1497,7 @@ impl f128 { #[must_use = "method returns a new number and does not mutate the original value"] pub fn ln_gamma(self) -> (f128, i32) { let mut signgamp: i32 = 0; - let x = unsafe { cmath::lgammaf128_r(self, &mut signgamp) }; + let x = cmath::lgammaf128_r(self, &mut signgamp); (x, signgamp) } @@ -1344,7 +1516,11 @@ impl f128 { /// ``` /// #![feature(f128)] /// #![feature(float_erf)] - /// # #[cfg(reliable_f128_math)] { + /// # #![cfg_attr(not(bootstrap), feature(cfg_target_has_reliable_f16_f128))] + /// # #![cfg_attr(not(bootstrap), expect(internal_features))] + /// # #[cfg(not(miri))] + /// # #[cfg(not(bootstrap))] + /// # #[cfg(target_has_reliable_f128_math)] { /// /// The error function relates what percent of a normal distribution lies /// /// within `x` standard deviations (scaled by `1/sqrt(2)`). /// fn within_standard_deviations(x: f128) -> f128 { @@ -1365,7 +1541,7 @@ impl f128 { // #[unstable(feature = "float_erf", issue = "136321")] #[inline] pub fn erf(self) -> f128 { - unsafe { cmath::erff128(self) } + cmath::erff128(self) } /// Complementary error function. @@ -1383,7 +1559,11 @@ impl f128 { /// ``` /// #![feature(f128)] /// #![feature(float_erf)] - /// # #[cfg(reliable_f128_math)] { + /// # #![cfg_attr(not(bootstrap), feature(cfg_target_has_reliable_f16_f128))] + /// # #![cfg_attr(not(bootstrap), expect(internal_features))] + /// # #[cfg(not(miri))] + /// # #[cfg(not(bootstrap))] + /// # #[cfg(target_has_reliable_f128_math)] { /// let x: f128 = 0.123; /// /// let one = x.erf() + x.erfc(); @@ -1398,6 +1578,6 @@ impl f128 { // #[unstable(feature = "float_erf", issue = "136321")] #[inline] pub fn erfc(self) -> f128 { - unsafe { cmath::erfcf128(self) } + cmath::erfcf128(self) } } diff --git a/library/std/src/f16.rs b/library/std/src/f16.rs index 286993d736b..3f88ab2d400 100644 --- a/library/std/src/f16.rs +++ b/library/std/src/f16.rs @@ -22,7 +22,11 @@ impl f16 { /// /// ``` /// #![feature(f16)] - /// # #[cfg(reliable_f16_math)] { + /// # #![cfg_attr(not(bootstrap), feature(cfg_target_has_reliable_f16_f128))] + /// # #![cfg_attr(not(bootstrap), expect(internal_features))] + /// # #[cfg(not(miri))] + /// # #[cfg(not(bootstrap))] + /// # #[cfg(target_has_reliable_f16_math)] { /// /// let f = 3.7_f16; /// let g = 3.0_f16; @@ -49,7 +53,11 @@ impl f16 { /// /// ``` /// #![feature(f16)] - /// # #[cfg(reliable_f16_math)] { + /// # #![cfg_attr(not(bootstrap), feature(cfg_target_has_reliable_f16_f128))] + /// # #![cfg_attr(not(bootstrap), expect(internal_features))] + /// # #[cfg(not(miri))] + /// # #[cfg(not(bootstrap))] + /// # #[cfg(target_has_reliable_f16_math)] { /// /// let f = 3.01_f16; /// let g = 4.0_f16; @@ -76,7 +84,11 @@ impl f16 { /// /// ``` /// #![feature(f16)] - /// # #[cfg(reliable_f16_math)] { + /// # #![cfg_attr(not(bootstrap), feature(cfg_target_has_reliable_f16_f128))] + /// # #![cfg_attr(not(bootstrap), expect(internal_features))] + /// # #[cfg(not(miri))] + /// # #[cfg(not(bootstrap))] + /// # #[cfg(target_has_reliable_f16_math)] { /// /// let f = 3.3_f16; /// let g = -3.3_f16; @@ -108,7 +120,11 @@ impl f16 { /// /// ``` /// #![feature(f16)] - /// # #[cfg(reliable_f16_math)] { + /// # #![cfg_attr(not(bootstrap), feature(cfg_target_has_reliable_f16_f128))] + /// # #![cfg_attr(not(bootstrap), expect(internal_features))] + /// # #[cfg(not(miri))] + /// # #[cfg(not(bootstrap))] + /// # #[cfg(target_has_reliable_f16_math)] { /// /// let f = 3.3_f16; /// let g = -3.3_f16; @@ -138,7 +154,11 @@ impl f16 { /// /// ``` /// #![feature(f16)] - /// # #[cfg(reliable_f16_math)] { + /// # #![cfg_attr(not(bootstrap), feature(cfg_target_has_reliable_f16_f128))] + /// # #![cfg_attr(not(bootstrap), expect(internal_features))] + /// # #[cfg(not(miri))] + /// # #[cfg(not(bootstrap))] + /// # #[cfg(target_has_reliable_f16_math)] { /// /// let f = 3.7_f16; /// let g = 3.0_f16; @@ -166,7 +186,11 @@ impl f16 { /// /// ``` /// #![feature(f16)] - /// # #[cfg(reliable_f16_math)] { + /// # #![cfg_attr(not(bootstrap), feature(cfg_target_has_reliable_f16_f128))] + /// # #![cfg_attr(not(bootstrap), expect(internal_features))] + /// # #[cfg(not(miri))] + /// # #[cfg(not(bootstrap))] + /// # #[cfg(target_has_reliable_f16_math)] { /// /// let x = 3.6_f16; /// let y = -3.6_f16; @@ -203,7 +227,11 @@ impl f16 { /// /// ``` /// #![feature(f16)] - /// # #[cfg(reliable_f16_math)] { + /// # #![cfg_attr(not(bootstrap), feature(cfg_target_has_reliable_f16_f128))] + /// # #![cfg_attr(not(bootstrap), expect(internal_features))] + /// # #[cfg(not(miri))] + /// # #[cfg(not(bootstrap))] + /// # #[cfg(target_has_reliable_f16_math)] { /// /// let m = 10.0_f16; /// let x = 4.0_f16; @@ -247,7 +275,11 @@ impl f16 { /// /// ``` /// #![feature(f16)] - /// # #[cfg(reliable_f16_math)] { + /// # #![cfg_attr(not(bootstrap), feature(cfg_target_has_reliable_f16_f128))] + /// # #![cfg_attr(not(bootstrap), expect(internal_features))] + /// # #[cfg(not(miri))] + /// # #[cfg(not(bootstrap))] + /// # #[cfg(target_has_reliable_f16_math)] { /// /// let a: f16 = 7.0; /// let b = 4.0; @@ -289,7 +321,11 @@ impl f16 { /// /// ``` /// #![feature(f16)] - /// # #[cfg(reliable_f16_math)] { + /// # #![cfg_attr(not(bootstrap), feature(cfg_target_has_reliable_f16_f128))] + /// # #![cfg_attr(not(bootstrap), expect(internal_features))] + /// # #[cfg(not(miri))] + /// # #[cfg(not(bootstrap))] + /// # #[cfg(target_has_reliable_f16_math)] { /// /// let a: f16 = 7.0; /// let b = 4.0; @@ -326,7 +362,11 @@ impl f16 { /// /// ``` /// #![feature(f16)] - /// # #[cfg(reliable_f16_math)] { + /// # #![cfg_attr(not(bootstrap), feature(cfg_target_has_reliable_f16_f128))] + /// # #![cfg_attr(not(bootstrap), expect(internal_features))] + /// # #[cfg(not(miri))] + /// # #[cfg(not(bootstrap))] + /// # #[cfg(target_has_reliable_f16_math)] { /// /// let x = 2.0_f16; /// let abs_difference = (x.powi(2) - (x * x)).abs(); @@ -354,7 +394,11 @@ impl f16 { /// /// ``` /// #![feature(f16)] - /// # #[cfg(reliable_f16_math)] { + /// # #![cfg_attr(not(bootstrap), feature(cfg_target_has_reliable_f16_f128))] + /// # #![cfg_attr(not(bootstrap), expect(internal_features))] + /// # #[cfg(not(miri))] + /// # #[cfg(not(bootstrap))] + /// # #[cfg(target_has_reliable_f16_math)] { /// /// let x = 2.0_f16; /// let abs_difference = (x.powf(2.0) - (x * x)).abs(); @@ -386,7 +430,11 @@ impl f16 { /// /// ``` /// #![feature(f16)] - /// # #[cfg(reliable_f16_math)] { + /// # #![cfg_attr(not(bootstrap), feature(cfg_target_has_reliable_f16_f128))] + /// # #![cfg_attr(not(bootstrap), expect(internal_features))] + /// # #[cfg(not(miri))] + /// # #[cfg(not(bootstrap))] + /// # #[cfg(target_has_reliable_f16_math)] { /// /// let positive = 4.0_f16; /// let negative = -4.0_f16; @@ -417,7 +465,11 @@ impl f16 { /// /// ``` /// #![feature(f16)] - /// # #[cfg(reliable_f16_math)] { + /// # #![cfg_attr(not(bootstrap), feature(cfg_target_has_reliable_f16_f128))] + /// # #![cfg_attr(not(bootstrap), expect(internal_features))] + /// # #[cfg(not(miri))] + /// # #[cfg(not(bootstrap))] + /// # #[cfg(target_has_reliable_f16_math)] { /// /// let one = 1.0f16; /// // e^1 @@ -448,7 +500,11 @@ impl f16 { /// /// ``` /// #![feature(f16)] - /// # #[cfg(reliable_f16_math)] { + /// # #![cfg_attr(not(bootstrap), feature(cfg_target_has_reliable_f16_f128))] + /// # #![cfg_attr(not(bootstrap), expect(internal_features))] + /// # #[cfg(not(miri))] + /// # #[cfg(not(bootstrap))] + /// # #[cfg(target_has_reliable_f16_math)] { /// /// let f = 2.0f16; /// @@ -479,7 +535,11 @@ impl f16 { /// /// ``` /// #![feature(f16)] - /// # #[cfg(reliable_f16_math)] { + /// # #![cfg_attr(not(bootstrap), feature(cfg_target_has_reliable_f16_f128))] + /// # #![cfg_attr(not(bootstrap), expect(internal_features))] + /// # #[cfg(not(miri))] + /// # #[cfg(not(bootstrap))] + /// # #[cfg(target_has_reliable_f16_math)] { /// /// let one = 1.0f16; /// // e^1 @@ -495,7 +555,11 @@ impl f16 { /// Non-positive values: /// ``` /// #![feature(f16)] - /// # #[cfg(reliable_f16_math)] { + /// # #![cfg_attr(not(bootstrap), feature(cfg_target_has_reliable_f16_f128))] + /// # #![cfg_attr(not(bootstrap), expect(internal_features))] + /// # #[cfg(not(miri))] + /// # #[cfg(not(bootstrap))] + /// # #[cfg(target_has_reliable_f16_math)] { /// /// assert_eq!(0_f16.ln(), f16::NEG_INFINITY); /// assert!((-42_f16).ln().is_nan()); @@ -526,7 +590,11 @@ impl f16 { /// /// ``` /// #![feature(f16)] - /// # #[cfg(reliable_f16_math)] { + /// # #![cfg_attr(not(bootstrap), feature(cfg_target_has_reliable_f16_f128))] + /// # #![cfg_attr(not(bootstrap), expect(internal_features))] + /// # #[cfg(not(miri))] + /// # #[cfg(not(bootstrap))] + /// # #[cfg(target_has_reliable_f16_math)] { /// /// let five = 5.0f16; /// @@ -540,7 +608,11 @@ impl f16 { /// Non-positive values: /// ``` /// #![feature(f16)] - /// # #[cfg(reliable_f16_math)] { + /// # #![cfg_attr(not(bootstrap), feature(cfg_target_has_reliable_f16_f128))] + /// # #![cfg_attr(not(bootstrap), expect(internal_features))] + /// # #[cfg(not(miri))] + /// # #[cfg(not(bootstrap))] + /// # #[cfg(target_has_reliable_f16_math)] { /// /// assert_eq!(0_f16.log(10.0), f16::NEG_INFINITY); /// assert!((-42_f16).log(10.0).is_nan()); @@ -567,7 +639,11 @@ impl f16 { /// /// ``` /// #![feature(f16)] - /// # #[cfg(reliable_f16_math)] { + /// # #![cfg_attr(not(bootstrap), feature(cfg_target_has_reliable_f16_f128))] + /// # #![cfg_attr(not(bootstrap), expect(internal_features))] + /// # #[cfg(not(miri))] + /// # #[cfg(not(bootstrap))] + /// # #[cfg(target_has_reliable_f16_math)] { /// /// let two = 2.0f16; /// @@ -581,7 +657,11 @@ impl f16 { /// Non-positive values: /// ``` /// #![feature(f16)] - /// # #[cfg(reliable_f16_math)] { + /// # #![cfg_attr(not(bootstrap), feature(cfg_target_has_reliable_f16_f128))] + /// # #![cfg_attr(not(bootstrap), expect(internal_features))] + /// # #[cfg(not(miri))] + /// # #[cfg(not(bootstrap))] + /// # #[cfg(target_has_reliable_f16_math)] { /// /// assert_eq!(0_f16.log2(), f16::NEG_INFINITY); /// assert!((-42_f16).log2().is_nan()); @@ -608,7 +688,11 @@ impl f16 { /// /// ``` /// #![feature(f16)] - /// # #[cfg(reliable_f16_math)] { + /// # #![cfg_attr(not(bootstrap), feature(cfg_target_has_reliable_f16_f128))] + /// # #![cfg_attr(not(bootstrap), expect(internal_features))] + /// # #[cfg(not(miri))] + /// # #[cfg(not(bootstrap))] + /// # #[cfg(target_has_reliable_f16_math)] { /// /// let ten = 10.0f16; /// @@ -622,7 +706,11 @@ impl f16 { /// Non-positive values: /// ``` /// #![feature(f16)] - /// # #[cfg(reliable_f16_math)] { + /// # #![cfg_attr(not(bootstrap), feature(cfg_target_has_reliable_f16_f128))] + /// # #![cfg_attr(not(bootstrap), expect(internal_features))] + /// # #[cfg(not(miri))] + /// # #[cfg(not(bootstrap))] + /// # #[cfg(target_has_reliable_f16_math)] { /// /// assert_eq!(0_f16.log10(), f16::NEG_INFINITY); /// assert!((-42_f16).log10().is_nan()); @@ -650,7 +738,11 @@ impl f16 { /// /// ``` /// #![feature(f16)] - /// # #[cfg(reliable_f16_math)] { + /// # #![cfg_attr(not(bootstrap), feature(cfg_target_has_reliable_f16_f128))] + /// # #![cfg_attr(not(bootstrap), expect(internal_features))] + /// # #[cfg(not(miri))] + /// # #[cfg(not(bootstrap))] + /// # #[cfg(target_has_reliable_f16_math)] { /// /// let x = 8.0f16; /// @@ -665,7 +757,7 @@ impl f16 { #[unstable(feature = "f16", issue = "116909")] #[must_use = "method returns a new number and does not mutate the original value"] pub fn cbrt(self) -> f16 { - (unsafe { cmath::cbrtf(self as f32) }) as f16 + cmath::cbrtf(self as f32) as f16 } /// Compute the distance between the origin and a point (`x`, `y`) on the @@ -685,7 +777,11 @@ impl f16 { /// /// ``` /// #![feature(f16)] - /// # #[cfg(reliable_f16_math)] { + /// # #![cfg_attr(not(bootstrap), feature(cfg_target_has_reliable_f16_f128))] + /// # #![cfg_attr(not(bootstrap), expect(internal_features))] + /// # #[cfg(not(miri))] + /// # #[cfg(not(bootstrap))] + /// # #[cfg(target_has_reliable_f16_math)] { /// /// let x = 2.0f16; /// let y = 3.0f16; @@ -701,7 +797,7 @@ impl f16 { #[unstable(feature = "f16", issue = "116909")] #[must_use = "method returns a new number and does not mutate the original value"] pub fn hypot(self, other: f16) -> f16 { - (unsafe { cmath::hypotf(self as f32, other as f32) }) as f16 + cmath::hypotf(self as f32, other as f32) as f16 } /// Computes the sine of a number (in radians). @@ -715,7 +811,11 @@ impl f16 { /// /// ``` /// #![feature(f16)] - /// # #[cfg(reliable_f16_math)] { + /// # #![cfg_attr(not(bootstrap), feature(cfg_target_has_reliable_f16_f128))] + /// # #![cfg_attr(not(bootstrap), expect(internal_features))] + /// # #[cfg(not(miri))] + /// # #[cfg(not(bootstrap))] + /// # #[cfg(target_has_reliable_f16_math)] { /// /// let x = std::f16::consts::FRAC_PI_2; /// @@ -743,7 +843,11 @@ impl f16 { /// /// ``` /// #![feature(f16)] - /// # #[cfg(reliable_f16_math)] { + /// # #![cfg_attr(not(bootstrap), feature(cfg_target_has_reliable_f16_f128))] + /// # #![cfg_attr(not(bootstrap), expect(internal_features))] + /// # #[cfg(not(miri))] + /// # #[cfg(not(bootstrap))] + /// # #[cfg(target_has_reliable_f16_math)] { /// /// let x = 2.0 * std::f16::consts::PI; /// @@ -774,7 +878,11 @@ impl f16 { /// /// ``` /// #![feature(f16)] - /// # #[cfg(reliable_f16_math)] { + /// # #![cfg_attr(not(bootstrap), feature(cfg_target_has_reliable_f16_f128))] + /// # #![cfg_attr(not(bootstrap), expect(internal_features))] + /// # #[cfg(not(miri))] + /// # #[cfg(not(bootstrap))] + /// # #[cfg(target_has_reliable_f16_math)] { /// /// let x = std::f16::consts::FRAC_PI_4; /// let abs_difference = (x.tan() - 1.0).abs(); @@ -787,7 +895,7 @@ impl f16 { #[unstable(feature = "f16", issue = "116909")] #[must_use = "method returns a new number and does not mutate the original value"] pub fn tan(self) -> f16 { - (unsafe { cmath::tanf(self as f32) }) as f16 + cmath::tanf(self as f32) as f16 } /// Computes the arcsine of a number. Return value is in radians in @@ -806,7 +914,11 @@ impl f16 { /// /// ``` /// #![feature(f16)] - /// # #[cfg(reliable_f16_math)] { + /// # #![cfg_attr(not(bootstrap), feature(cfg_target_has_reliable_f16_f128))] + /// # #![cfg_attr(not(bootstrap), expect(internal_features))] + /// # #[cfg(not(miri))] + /// # #[cfg(not(bootstrap))] + /// # #[cfg(target_has_reliable_f16_math)] { /// /// let f = std::f16::consts::FRAC_PI_2; /// @@ -822,7 +934,7 @@ impl f16 { #[unstable(feature = "f16", issue = "116909")] #[must_use = "method returns a new number and does not mutate the original value"] pub fn asin(self) -> f16 { - (unsafe { cmath::asinf(self as f32) }) as f16 + cmath::asinf(self as f32) as f16 } /// Computes the arccosine of a number. Return value is in radians in @@ -841,7 +953,11 @@ impl f16 { /// /// ``` /// #![feature(f16)] - /// # #[cfg(reliable_f16_math)] { + /// # #![cfg_attr(not(bootstrap), feature(cfg_target_has_reliable_f16_f128))] + /// # #![cfg_attr(not(bootstrap), expect(internal_features))] + /// # #[cfg(not(miri))] + /// # #[cfg(not(bootstrap))] + /// # #[cfg(target_has_reliable_f16_math)] { /// /// let f = std::f16::consts::FRAC_PI_4; /// @@ -857,7 +973,7 @@ impl f16 { #[unstable(feature = "f16", issue = "116909")] #[must_use = "method returns a new number and does not mutate the original value"] pub fn acos(self) -> f16 { - (unsafe { cmath::acosf(self as f32) }) as f16 + cmath::acosf(self as f32) as f16 } /// Computes the arctangent of a number. Return value is in radians in the @@ -875,7 +991,11 @@ impl f16 { /// /// ``` /// #![feature(f16)] - /// # #[cfg(reliable_f16_math)] { + /// # #![cfg_attr(not(bootstrap), feature(cfg_target_has_reliable_f16_f128))] + /// # #![cfg_attr(not(bootstrap), expect(internal_features))] + /// # #[cfg(not(miri))] + /// # #[cfg(not(bootstrap))] + /// # #[cfg(target_has_reliable_f16_math)] { /// /// let f = 1.0f16; /// @@ -891,7 +1011,7 @@ impl f16 { #[unstable(feature = "f16", issue = "116909")] #[must_use = "method returns a new number and does not mutate the original value"] pub fn atan(self) -> f16 { - (unsafe { cmath::atanf(self as f32) }) as f16 + cmath::atanf(self as f32) as f16 } /// Computes the four quadrant arctangent of `self` (`y`) and `other` (`x`) in radians. @@ -913,7 +1033,11 @@ impl f16 { /// /// ``` /// #![feature(f16)] - /// # #[cfg(reliable_f16_math)] { + /// # #![cfg_attr(not(bootstrap), feature(cfg_target_has_reliable_f16_f128))] + /// # #![cfg_attr(not(bootstrap), expect(internal_features))] + /// # #[cfg(not(miri))] + /// # #[cfg(not(bootstrap))] + /// # #[cfg(target_has_reliable_f16_math)] { /// /// // Positive angles measured counter-clockwise /// // from positive x axis @@ -937,7 +1061,7 @@ impl f16 { #[unstable(feature = "f16", issue = "116909")] #[must_use = "method returns a new number and does not mutate the original value"] pub fn atan2(self, other: f16) -> f16 { - (unsafe { cmath::atan2f(self as f32, other as f32) }) as f16 + cmath::atan2f(self as f32, other as f32) as f16 } /// Simultaneously computes the sine and cosine of the number, `x`. Returns @@ -955,7 +1079,11 @@ impl f16 { /// /// ``` /// #![feature(f16)] - /// # #[cfg(reliable_f16_math)] { + /// # #![cfg_attr(not(bootstrap), feature(cfg_target_has_reliable_f16_f128))] + /// # #![cfg_attr(not(bootstrap), expect(internal_features))] + /// # #[cfg(not(miri))] + /// # #[cfg(not(bootstrap))] + /// # #[cfg(target_has_reliable_f16_math)] { /// /// let x = std::f16::consts::FRAC_PI_4; /// let f = x.sin_cos(); @@ -990,7 +1118,11 @@ impl f16 { /// /// ``` /// #![feature(f16)] - /// # #[cfg(reliable_f16_math)] { + /// # #![cfg_attr(not(bootstrap), feature(cfg_target_has_reliable_f16_f128))] + /// # #![cfg_attr(not(bootstrap), expect(internal_features))] + /// # #[cfg(not(miri))] + /// # #[cfg(not(bootstrap))] + /// # #[cfg(target_has_reliable_f16_math)] { /// /// let x = 1e-4_f16; /// @@ -1006,7 +1138,7 @@ impl f16 { #[unstable(feature = "f16", issue = "116909")] #[must_use = "method returns a new number and does not mutate the original value"] pub fn exp_m1(self) -> f16 { - (unsafe { cmath::expm1f(self as f32) }) as f16 + cmath::expm1f(self as f32) as f16 } /// Returns `ln(1+n)` (natural logarithm) more accurately than if @@ -1026,7 +1158,11 @@ impl f16 { /// /// ``` /// #![feature(f16)] - /// # #[cfg(reliable_f16_math)] { + /// # #![cfg_attr(not(bootstrap), feature(cfg_target_has_reliable_f16_f128))] + /// # #![cfg_attr(not(bootstrap), expect(internal_features))] + /// # #[cfg(not(miri))] + /// # #[cfg(not(bootstrap))] + /// # #[cfg(target_has_reliable_f16_math)] { /// /// let x = 1e-4_f16; /// @@ -1041,7 +1177,11 @@ impl f16 { /// Out-of-range values: /// ``` /// #![feature(f16)] - /// # #[cfg(reliable_f16_math)] { + /// # #![cfg_attr(not(bootstrap), feature(cfg_target_has_reliable_f16_f128))] + /// # #![cfg_attr(not(bootstrap), expect(internal_features))] + /// # #[cfg(not(miri))] + /// # #[cfg(not(bootstrap))] + /// # #[cfg(target_has_reliable_f16_math)] { /// /// assert_eq!((-1.0_f16).ln_1p(), f16::NEG_INFINITY); /// assert!((-2.0_f16).ln_1p().is_nan()); @@ -1053,7 +1193,7 @@ impl f16 { #[unstable(feature = "f16", issue = "116909")] #[must_use = "method returns a new number and does not mutate the original value"] pub fn ln_1p(self) -> f16 { - (unsafe { cmath::log1pf(self as f32) }) as f16 + cmath::log1pf(self as f32) as f16 } /// Hyperbolic sine function. @@ -1070,7 +1210,11 @@ impl f16 { /// /// ``` /// #![feature(f16)] - /// # #[cfg(reliable_f16_math)] { + /// # #![cfg_attr(not(bootstrap), feature(cfg_target_has_reliable_f16_f128))] + /// # #![cfg_attr(not(bootstrap), expect(internal_features))] + /// # #[cfg(not(miri))] + /// # #[cfg(not(bootstrap))] + /// # #[cfg(target_has_reliable_f16_math)] { /// /// let e = std::f16::consts::E; /// let x = 1.0f16; @@ -1088,7 +1232,7 @@ impl f16 { #[unstable(feature = "f16", issue = "116909")] #[must_use = "method returns a new number and does not mutate the original value"] pub fn sinh(self) -> f16 { - (unsafe { cmath::sinhf(self as f32) }) as f16 + cmath::sinhf(self as f32) as f16 } /// Hyperbolic cosine function. @@ -1105,7 +1249,11 @@ impl f16 { /// /// ``` /// #![feature(f16)] - /// # #[cfg(reliable_f16_math)] { + /// # #![cfg_attr(not(bootstrap), feature(cfg_target_has_reliable_f16_f128))] + /// # #![cfg_attr(not(bootstrap), expect(internal_features))] + /// # #[cfg(not(miri))] + /// # #[cfg(not(bootstrap))] + /// # #[cfg(target_has_reliable_f16_math)] { /// /// let e = std::f16::consts::E; /// let x = 1.0f16; @@ -1123,7 +1271,7 @@ impl f16 { #[unstable(feature = "f16", issue = "116909")] #[must_use = "method returns a new number and does not mutate the original value"] pub fn cosh(self) -> f16 { - (unsafe { cmath::coshf(self as f32) }) as f16 + cmath::coshf(self as f32) as f16 } /// Hyperbolic tangent function. @@ -1140,7 +1288,11 @@ impl f16 { /// /// ``` /// #![feature(f16)] - /// # #[cfg(reliable_f16_math)] { + /// # #![cfg_attr(not(bootstrap), feature(cfg_target_has_reliable_f16_f128))] + /// # #![cfg_attr(not(bootstrap), expect(internal_features))] + /// # #[cfg(not(miri))] + /// # #[cfg(not(bootstrap))] + /// # #[cfg(target_has_reliable_f16_math)] { /// /// let e = std::f16::consts::E; /// let x = 1.0f16; @@ -1158,7 +1310,7 @@ impl f16 { #[unstable(feature = "f16", issue = "116909")] #[must_use = "method returns a new number and does not mutate the original value"] pub fn tanh(self) -> f16 { - (unsafe { cmath::tanhf(self as f32) }) as f16 + cmath::tanhf(self as f32) as f16 } /// Inverse hyperbolic sine function. @@ -1172,7 +1324,11 @@ impl f16 { /// /// ``` /// #![feature(f16)] - /// # #[cfg(reliable_f16_math)] { + /// # #![cfg_attr(not(bootstrap), feature(cfg_target_has_reliable_f16_f128))] + /// # #![cfg_attr(not(bootstrap), expect(internal_features))] + /// # #[cfg(not(miri))] + /// # #[cfg(not(bootstrap))] + /// # #[cfg(target_has_reliable_f16_math)] { /// /// let x = 1.0f16; /// let f = x.sinh().asinh(); @@ -1204,7 +1360,11 @@ impl f16 { /// /// ``` /// #![feature(f16)] - /// # #[cfg(reliable_f16_math)] { + /// # #![cfg_attr(not(bootstrap), feature(cfg_target_has_reliable_f16_f128))] + /// # #![cfg_attr(not(bootstrap), expect(internal_features))] + /// # #[cfg(not(miri))] + /// # #[cfg(not(bootstrap))] + /// # #[cfg(target_has_reliable_f16_math)] { /// /// let x = 1.0f16; /// let f = x.cosh().acosh(); @@ -1238,7 +1398,11 @@ impl f16 { /// /// ``` /// #![feature(f16)] - /// # #[cfg(reliable_f16_math)] { + /// # #![cfg_attr(not(bootstrap), feature(cfg_target_has_reliable_f16_f128))] + /// # #![cfg_attr(not(bootstrap), expect(internal_features))] + /// # #[cfg(not(miri))] + /// # #[cfg(not(bootstrap))] + /// # #[cfg(target_has_reliable_f16_math)] { /// /// let e = std::f16::consts::E; /// let f = e.tanh().atanh(); @@ -1272,7 +1436,11 @@ impl f16 { /// ``` /// #![feature(f16)] /// #![feature(float_gamma)] - /// # #[cfg(reliable_f16_math)] { + /// # #![cfg_attr(not(bootstrap), feature(cfg_target_has_reliable_f16_f128))] + /// # #![cfg_attr(not(bootstrap), expect(internal_features))] + /// # #[cfg(not(miri))] + /// # #[cfg(not(bootstrap))] + /// # #[cfg(target_has_reliable_f16_math)] { /// /// let x = 5.0f16; /// @@ -1287,7 +1455,7 @@ impl f16 { // #[unstable(feature = "float_gamma", issue = "99842")] #[must_use = "method returns a new number and does not mutate the original value"] pub fn gamma(self) -> f16 { - (unsafe { cmath::tgammaf(self as f32) }) as f16 + cmath::tgammaf(self as f32) as f16 } /// Natural logarithm of the absolute value of the gamma function @@ -1307,7 +1475,11 @@ impl f16 { /// ``` /// #![feature(f16)] /// #![feature(float_gamma)] - /// # #[cfg(reliable_f16_math)] { + /// # #![cfg_attr(not(bootstrap), feature(cfg_target_has_reliable_f16_f128))] + /// # #![cfg_attr(not(bootstrap), expect(internal_features))] + /// # #[cfg(not(miri))] + /// # #[cfg(not(bootstrap))] + /// # #[cfg(target_has_reliable_f16_math)] { /// /// let x = 2.0f16; /// @@ -1323,7 +1495,7 @@ impl f16 { #[must_use = "method returns a new number and does not mutate the original value"] pub fn ln_gamma(self) -> (f16, i32) { let mut signgamp: i32 = 0; - let x = (unsafe { cmath::lgammaf_r(self as f32, &mut signgamp) }) as f16; + let x = cmath::lgammaf_r(self as f32, &mut signgamp) as f16; (x, signgamp) } @@ -1342,7 +1514,11 @@ impl f16 { /// ``` /// #![feature(f16)] /// #![feature(float_erf)] - /// # #[cfg(reliable_f16_math)] { + /// # #![cfg_attr(not(bootstrap), feature(cfg_target_has_reliable_f16_f128))] + /// # #![cfg_attr(not(bootstrap), expect(internal_features))] + /// # #[cfg(not(miri))] + /// # #[cfg(not(bootstrap))] + /// # #[cfg(target_has_reliable_f16_math)] { /// /// The error function relates what percent of a normal distribution lies /// /// within `x` standard deviations (scaled by `1/sqrt(2)`). /// fn within_standard_deviations(x: f16) -> f16 { @@ -1363,7 +1539,7 @@ impl f16 { // #[unstable(feature = "float_erf", issue = "136321")] #[inline] pub fn erf(self) -> f16 { - (unsafe { cmath::erff(self as f32) }) as f16 + cmath::erff(self as f32) as f16 } /// Complementary error function. @@ -1381,7 +1557,11 @@ impl f16 { /// ``` /// #![feature(f16)] /// #![feature(float_erf)] - /// # #[cfg(reliable_f16_math)] { + /// # #![cfg_attr(not(bootstrap), feature(cfg_target_has_reliable_f16_f128))] + /// # #![cfg_attr(not(bootstrap), expect(internal_features))] + /// # #[cfg(not(miri))] + /// # #[cfg(not(bootstrap))] + /// # #[cfg(target_has_reliable_f16_math)] { /// let x: f16 = 0.123; /// /// let one = x.erf() + x.erfc(); @@ -1396,6 +1576,6 @@ impl f16 { // #[unstable(feature = "float_erf", issue = "136321")] #[inline] pub fn erfc(self) -> f16 { - (unsafe { cmath::erfcf(self as f32) }) as f16 + cmath::erfcf(self as f32) as f16 } } diff --git a/library/std/src/f32.rs b/library/std/src/f32.rs index 980e7f7793a..baf7002f380 100644 --- a/library/std/src/f32.rs +++ b/library/std/src/f32.rs @@ -599,7 +599,7 @@ impl f32 { filing an issue describing your use-case too)." )] pub fn abs_sub(self, other: f32) -> f32 { - unsafe { cmath::fdimf(self, other) } + cmath::fdimf(self, other) } /// Returns the cube root of a number. @@ -626,7 +626,7 @@ impl f32 { #[stable(feature = "rust1", since = "1.0.0")] #[inline] pub fn cbrt(self) -> f32 { - unsafe { cmath::cbrtf(self) } + cmath::cbrtf(self) } /// Compute the distance between the origin and a point (`x`, `y`) on the @@ -657,7 +657,7 @@ impl f32 { #[stable(feature = "rust1", since = "1.0.0")] #[inline] pub fn hypot(self, other: f32) -> f32 { - unsafe { cmath::hypotf(self, other) } + cmath::hypotf(self, other) } /// Computes the sine of a number (in radians). @@ -730,7 +730,7 @@ impl f32 { #[stable(feature = "rust1", since = "1.0.0")] #[inline] pub fn tan(self) -> f32 { - unsafe { cmath::tanf(self) } + cmath::tanf(self) } /// Computes the arcsine of a number. Return value is in radians in @@ -760,7 +760,7 @@ impl f32 { #[stable(feature = "rust1", since = "1.0.0")] #[inline] pub fn asin(self) -> f32 { - unsafe { cmath::asinf(self) } + cmath::asinf(self) } /// Computes the arccosine of a number. Return value is in radians in @@ -790,7 +790,7 @@ impl f32 { #[stable(feature = "rust1", since = "1.0.0")] #[inline] pub fn acos(self) -> f32 { - unsafe { cmath::acosf(self) } + cmath::acosf(self) } /// Computes the arctangent of a number. Return value is in radians in the @@ -819,7 +819,7 @@ impl f32 { #[stable(feature = "rust1", since = "1.0.0")] #[inline] pub fn atan(self) -> f32 { - unsafe { cmath::atanf(self) } + cmath::atanf(self) } /// Computes the four quadrant arctangent of `self` (`y`) and `other` (`x`) in radians. @@ -860,7 +860,7 @@ impl f32 { #[stable(feature = "rust1", since = "1.0.0")] #[inline] pub fn atan2(self, other: f32) -> f32 { - unsafe { cmath::atan2f(self, other) } + cmath::atan2f(self, other) } /// Simultaneously computes the sine and cosine of the number, `x`. Returns @@ -919,7 +919,7 @@ impl f32 { #[stable(feature = "rust1", since = "1.0.0")] #[inline] pub fn exp_m1(self) -> f32 { - unsafe { cmath::expm1f(self) } + cmath::expm1f(self) } /// Returns `ln(1+n)` (natural logarithm) more accurately than if @@ -957,7 +957,7 @@ impl f32 { #[stable(feature = "rust1", since = "1.0.0")] #[inline] pub fn ln_1p(self) -> f32 { - unsafe { cmath::log1pf(self) } + cmath::log1pf(self) } /// Hyperbolic sine function. @@ -987,7 +987,7 @@ impl f32 { #[stable(feature = "rust1", since = "1.0.0")] #[inline] pub fn sinh(self) -> f32 { - unsafe { cmath::sinhf(self) } + cmath::sinhf(self) } /// Hyperbolic cosine function. @@ -1017,7 +1017,7 @@ impl f32 { #[stable(feature = "rust1", since = "1.0.0")] #[inline] pub fn cosh(self) -> f32 { - unsafe { cmath::coshf(self) } + cmath::coshf(self) } /// Hyperbolic tangent function. @@ -1047,7 +1047,7 @@ impl f32 { #[stable(feature = "rust1", since = "1.0.0")] #[inline] pub fn tanh(self) -> f32 { - unsafe { cmath::tanhf(self) } + cmath::tanhf(self) } /// Inverse hyperbolic sine function. @@ -1158,7 +1158,7 @@ impl f32 { #[unstable(feature = "float_gamma", issue = "99842")] #[inline] pub fn gamma(self) -> f32 { - unsafe { cmath::tgammaf(self) } + cmath::tgammaf(self) } /// Natural logarithm of the absolute value of the gamma function @@ -1188,7 +1188,7 @@ impl f32 { #[inline] pub fn ln_gamma(self) -> (f32, i32) { let mut signgamp: i32 = 0; - let x = unsafe { cmath::lgammaf_r(self, &mut signgamp) }; + let x = cmath::lgammaf_r(self, &mut signgamp); (x, signgamp) } @@ -1224,7 +1224,7 @@ impl f32 { #[unstable(feature = "float_erf", issue = "136321")] #[inline] pub fn erf(self) -> f32 { - unsafe { cmath::erff(self) } + cmath::erff(self) } /// Complementary error function. @@ -1253,6 +1253,6 @@ impl f32 { #[unstable(feature = "float_erf", issue = "136321")] #[inline] pub fn erfc(self) -> f32 { - unsafe { cmath::erfcf(self) } + cmath::erfcf(self) } } diff --git a/library/std/src/f64.rs b/library/std/src/f64.rs index 2aaab3ffc83..84fd9bfb7b6 100644 --- a/library/std/src/f64.rs +++ b/library/std/src/f64.rs @@ -599,7 +599,7 @@ impl f64 { filing an issue describing your use-case too)." )] pub fn abs_sub(self, other: f64) -> f64 { - unsafe { cmath::fdim(self, other) } + cmath::fdim(self, other) } /// Returns the cube root of a number. @@ -626,7 +626,7 @@ impl f64 { #[stable(feature = "rust1", since = "1.0.0")] #[inline] pub fn cbrt(self) -> f64 { - unsafe { cmath::cbrt(self) } + cmath::cbrt(self) } /// Compute the distance between the origin and a point (`x`, `y`) on the @@ -657,7 +657,7 @@ impl f64 { #[stable(feature = "rust1", since = "1.0.0")] #[inline] pub fn hypot(self, other: f64) -> f64 { - unsafe { cmath::hypot(self, other) } + cmath::hypot(self, other) } /// Computes the sine of a number (in radians). @@ -730,7 +730,7 @@ impl f64 { #[stable(feature = "rust1", since = "1.0.0")] #[inline] pub fn tan(self) -> f64 { - unsafe { cmath::tan(self) } + cmath::tan(self) } /// Computes the arcsine of a number. Return value is in radians in @@ -760,7 +760,7 @@ impl f64 { #[stable(feature = "rust1", since = "1.0.0")] #[inline] pub fn asin(self) -> f64 { - unsafe { cmath::asin(self) } + cmath::asin(self) } /// Computes the arccosine of a number. Return value is in radians in @@ -790,7 +790,7 @@ impl f64 { #[stable(feature = "rust1", since = "1.0.0")] #[inline] pub fn acos(self) -> f64 { - unsafe { cmath::acos(self) } + cmath::acos(self) } /// Computes the arctangent of a number. Return value is in radians in the @@ -819,7 +819,7 @@ impl f64 { #[stable(feature = "rust1", since = "1.0.0")] #[inline] pub fn atan(self) -> f64 { - unsafe { cmath::atan(self) } + cmath::atan(self) } /// Computes the four quadrant arctangent of `self` (`y`) and `other` (`x`) in radians. @@ -860,7 +860,7 @@ impl f64 { #[stable(feature = "rust1", since = "1.0.0")] #[inline] pub fn atan2(self, other: f64) -> f64 { - unsafe { cmath::atan2(self, other) } + cmath::atan2(self, other) } /// Simultaneously computes the sine and cosine of the number, `x`. Returns @@ -919,7 +919,7 @@ impl f64 { #[stable(feature = "rust1", since = "1.0.0")] #[inline] pub fn exp_m1(self) -> f64 { - unsafe { cmath::expm1(self) } + cmath::expm1(self) } /// Returns `ln(1+n)` (natural logarithm) more accurately than if @@ -957,7 +957,7 @@ impl f64 { #[stable(feature = "rust1", since = "1.0.0")] #[inline] pub fn ln_1p(self) -> f64 { - unsafe { cmath::log1p(self) } + cmath::log1p(self) } /// Hyperbolic sine function. @@ -987,7 +987,7 @@ impl f64 { #[stable(feature = "rust1", since = "1.0.0")] #[inline] pub fn sinh(self) -> f64 { - unsafe { cmath::sinh(self) } + cmath::sinh(self) } /// Hyperbolic cosine function. @@ -1017,7 +1017,7 @@ impl f64 { #[stable(feature = "rust1", since = "1.0.0")] #[inline] pub fn cosh(self) -> f64 { - unsafe { cmath::cosh(self) } + cmath::cosh(self) } /// Hyperbolic tangent function. @@ -1047,7 +1047,7 @@ impl f64 { #[stable(feature = "rust1", since = "1.0.0")] #[inline] pub fn tanh(self) -> f64 { - unsafe { cmath::tanh(self) } + cmath::tanh(self) } /// Inverse hyperbolic sine function. @@ -1158,7 +1158,7 @@ impl f64 { #[unstable(feature = "float_gamma", issue = "99842")] #[inline] pub fn gamma(self) -> f64 { - unsafe { cmath::tgamma(self) } + cmath::tgamma(self) } /// Natural logarithm of the absolute value of the gamma function @@ -1188,7 +1188,7 @@ impl f64 { #[inline] pub fn ln_gamma(self) -> (f64, i32) { let mut signgamp: i32 = 0; - let x = unsafe { cmath::lgamma_r(self, &mut signgamp) }; + let x = cmath::lgamma_r(self, &mut signgamp); (x, signgamp) } @@ -1224,7 +1224,7 @@ impl f64 { #[unstable(feature = "float_erf", issue = "136321")] #[inline] pub fn erf(self) -> f64 { - unsafe { cmath::erf(self) } + cmath::erf(self) } /// Complementary error function. @@ -1253,6 +1253,6 @@ impl f64 { #[unstable(feature = "float_erf", issue = "136321")] #[inline] pub fn erfc(self) -> f64 { - unsafe { cmath::erfc(self) } + cmath::erfc(self) } } diff --git a/library/std/src/ffi/mod.rs b/library/std/src/ffi/mod.rs index 860ec3a6be1..bd9446f5aba 100644 --- a/library/std/src/ffi/mod.rs +++ b/library/std/src/ffi/mod.rs @@ -161,7 +161,7 @@ #![stable(feature = "rust1", since = "1.0.0")] -#[unstable(feature = "c_str_module", issue = "112134")] +#[stable(feature = "c_str_module", since = "CURRENT_RUSTC_VERSION")] pub mod c_str; #[stable(feature = "core_c_void", since = "1.30.0")] @@ -201,5 +201,5 @@ pub use self::c_str::{CStr, CString}; #[doc(inline)] pub use self::os_str::{OsStr, OsString}; -#[stable(feature = "os_str_display", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "os_str_display", since = "1.87.0")] pub mod os_str; diff --git a/library/std/src/ffi/os_str.rs b/library/std/src/ffi/os_str.rs index aa25ff5293c..ce01175309a 100644 --- a/library/std/src/ffi/os_str.rs +++ b/library/std/src/ffi/os_str.rs @@ -1255,7 +1255,7 @@ impl OsStr { /// let s = OsStr::new("Hello, world!"); /// println!("{}", s.display()); /// ``` - #[stable(feature = "os_str_display", since = "CURRENT_RUSTC_VERSION")] + #[stable(feature = "os_str_display", since = "1.87.0")] #[must_use = "this does not display the `OsStr`; \ it returns an object that can be displayed"] #[inline] @@ -1612,19 +1612,19 @@ impl fmt::Debug for OsStr { /// /// [`Display`]: fmt::Display /// [`format!`]: crate::format -#[stable(feature = "os_str_display", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "os_str_display", since = "1.87.0")] pub struct Display<'a> { os_str: &'a OsStr, } -#[stable(feature = "os_str_display", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "os_str_display", since = "1.87.0")] impl fmt::Debug for Display<'_> { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { fmt::Debug::fmt(&self.os_str, f) } } -#[stable(feature = "os_str_display", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "os_str_display", since = "1.87.0")] impl fmt::Display for Display<'_> { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { fmt::Display::fmt(&self.os_str.inner, f) diff --git a/library/std/src/fs.rs b/library/std/src/fs.rs index 801baf3d990..462c06dcea2 100644 --- a/library/std/src/fs.rs +++ b/library/std/src/fs.rs @@ -2874,6 +2874,8 @@ pub fn remove_dir<P: AsRef<Path>>(path: P) -> io::Result<()> { /// /// Consider ignoring the error if validating the removal is not required for your use case. /// +/// This function may return [`io::ErrorKind::DirectoryNotEmpty`] if the directory is concurrently +/// written into, which typically indicates some contents were removed but not all. /// [`io::ErrorKind::NotFound`] is only returned if no removal occurs. /// /// [`fs::remove_file`]: remove_file @@ -2980,6 +2982,21 @@ pub fn read_dir<P: AsRef<Path>>(path: P) -> io::Result<ReadDir> { /// /// [changes]: io#platform-specific-behavior /// +/// ## Symlinks +/// On UNIX-like systems, this function will update the permission bits +/// of the file pointed to by the symlink. +/// +/// Note that this behavior can lead to privalage escalation vulnerabilites, +/// where the ability to create a symlink in one directory allows you to +/// cause the permissions of another file or directory to be modified. +/// +/// For this reason, using this function with symlinks should be avoided. +/// When possible, permissions should be set at creation time instead. +/// +/// # Rationale +/// POSIX does not specify an `lchown` function, +/// and symlinks can be followed regardless of what permission bits are set. +/// /// # Errors /// /// This function will return an error in the following situations, but is not diff --git a/library/std/src/io/error.rs b/library/std/src/io/error.rs index 8472f903050..cf3778bd290 100644 --- a/library/std/src/io/error.rs +++ b/library/std/src/io/error.rs @@ -48,6 +48,7 @@ use crate::{error, fmt, result, sys}; /// } /// ``` #[stable(feature = "rust1", since = "1.0.0")] +#[cfg_attr(not(bootstrap), doc(search_unbox))] pub type Result<T> = result::Result<T, Error>; /// The error type for I/O operations of the [`Read`], [`Write`], [`Seek`], and @@ -374,7 +375,7 @@ pub enum ErrorKind { /// A filename was invalid. /// /// This error can also occur if a length limit for a name was exceeded. - #[stable(feature = "io_error_invalid_filename", since = "CURRENT_RUSTC_VERSION")] + #[stable(feature = "io_error_invalid_filename", since = "1.87.0")] InvalidFilename, /// Program argument list too long. /// diff --git a/library/std/src/io/mod.rs b/library/std/src/io/mod.rs index 314cbb45d49..96fac4f6bde 100644 --- a/library/std/src/io/mod.rs +++ b/library/std/src/io/mod.rs @@ -310,7 +310,7 @@ pub use self::error::RawOsError; pub use self::error::SimpleMessage; #[unstable(feature = "io_const_error", issue = "133448")] pub use self::error::const_error; -#[stable(feature = "anonymous_pipe", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "anonymous_pipe", since = "1.87.0")] pub use self::pipe::{PipeReader, PipeWriter, pipe}; #[stable(feature = "is_terminal", since = "1.70.0")] pub use self::stdio::IsTerminal; @@ -2319,9 +2319,9 @@ pub trait BufRead: Read { /// Checks if there is any data left to be `read`. /// /// This function may fill the buffer to check for data, - /// so this functions returns `Result<bool>`, not `bool`. + /// so this function returns `Result<bool>`, not `bool`. /// - /// Default implementation calls `fill_buf` and checks that + /// The default implementation calls `fill_buf` and checks that the /// returned slice is empty (which means that there is no data left, /// since EOF is reached). /// @@ -2658,6 +2658,10 @@ impl<T, U> Chain<T, U> { /// Gets references to the underlying readers in this `Chain`. /// + /// Care should be taken to avoid modifying the internal I/O state of the + /// underlying readers as doing so may corrupt the internal state of this + /// `Chain`. + /// /// # Examples /// /// ```no_run @@ -2915,6 +2919,10 @@ impl<T> Take<T> { /// Gets a reference to the underlying reader. /// + /// Care should be taken to avoid modifying the internal I/O state of the + /// underlying reader as doing so may corrupt the internal limit of this + /// `Take`. + /// /// # Examples /// /// ```no_run diff --git a/library/std/src/io/pipe.rs b/library/std/src/io/pipe.rs index cfed9b05cc0..c6b7b49a351 100644 --- a/library/std/src/io/pipe.rs +++ b/library/std/src/io/pipe.rs @@ -67,19 +67,19 @@ use crate::sys_common::{FromInner, IntoInner}; /// ``` /// [changes]: io#platform-specific-behavior /// [man page]: https://man7.org/linux/man-pages/man7/pipe.7.html -#[stable(feature = "anonymous_pipe", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "anonymous_pipe", since = "1.87.0")] #[inline] pub fn pipe() -> io::Result<(PipeReader, PipeWriter)> { pipe_inner().map(|(reader, writer)| (PipeReader(reader), PipeWriter(writer))) } /// Read end of an anonymous pipe. -#[stable(feature = "anonymous_pipe", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "anonymous_pipe", since = "1.87.0")] #[derive(Debug)] pub struct PipeReader(pub(crate) AnonPipe); /// Write end of an anonymous pipe. -#[stable(feature = "anonymous_pipe", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "anonymous_pipe", since = "1.87.0")] #[derive(Debug)] pub struct PipeWriter(pub(crate) AnonPipe); @@ -160,7 +160,7 @@ impl PipeReader { /// # Ok(()) /// # } /// ``` - #[stable(feature = "anonymous_pipe", since = "CURRENT_RUSTC_VERSION")] + #[stable(feature = "anonymous_pipe", since = "1.87.0")] pub fn try_clone(&self) -> io::Result<Self> { self.0.try_clone().map(Self) } @@ -199,13 +199,13 @@ impl PipeWriter { /// # Ok(()) /// # } /// ``` - #[stable(feature = "anonymous_pipe", since = "CURRENT_RUSTC_VERSION")] + #[stable(feature = "anonymous_pipe", since = "1.87.0")] pub fn try_clone(&self) -> io::Result<Self> { self.0.try_clone().map(Self) } } -#[stable(feature = "anonymous_pipe", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "anonymous_pipe", since = "1.87.0")] impl io::Read for &PipeReader { fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> { self.0.read(buf) @@ -225,7 +225,7 @@ impl io::Read for &PipeReader { } } -#[stable(feature = "anonymous_pipe", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "anonymous_pipe", since = "1.87.0")] impl io::Read for PipeReader { fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> { self.0.read(buf) @@ -245,7 +245,7 @@ impl io::Read for PipeReader { } } -#[stable(feature = "anonymous_pipe", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "anonymous_pipe", since = "1.87.0")] impl io::Write for &PipeWriter { fn write(&mut self, buf: &[u8]) -> io::Result<usize> { self.0.write(buf) @@ -263,7 +263,7 @@ impl io::Write for &PipeWriter { } } -#[stable(feature = "anonymous_pipe", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "anonymous_pipe", since = "1.87.0")] impl io::Write for PipeWriter { fn write(&mut self, buf: &[u8]) -> io::Result<usize> { self.0.write(buf) diff --git a/library/std/src/io/stdio.rs b/library/std/src/io/stdio.rs index 8fc16331339..2d80fe49e80 100644 --- a/library/std/src/io/stdio.rs +++ b/library/std/src/io/stdio.rs @@ -11,7 +11,7 @@ use crate::io::{ self, BorrowedCursor, BufReader, IoSlice, IoSliceMut, LineWriter, Lines, SpecReadByte, }; use crate::panic::{RefUnwindSafe, UnwindSafe}; -use crate::sync::atomic::{AtomicBool, Ordering}; +use crate::sync::atomic::{Atomic, AtomicBool, Ordering}; use crate::sync::{Arc, Mutex, MutexGuard, OnceLock, ReentrantLock, ReentrantLockGuard}; use crate::sys::stdio; use crate::thread::AccessError; @@ -37,7 +37,7 @@ thread_local! { /// have a consistent order between set_output_capture and print_to *within /// the same thread*. Within the same thread, things always have a perfectly /// consistent order. So Ordering::Relaxed is fine. -static OUTPUT_CAPTURE_USED: AtomicBool = AtomicBool::new(false); +static OUTPUT_CAPTURE_USED: Atomic<bool> = AtomicBool::new(false); /// A handle to a raw instance of the standard input stream of this process. /// diff --git a/library/std/src/keyword_docs.rs b/library/std/src/keyword_docs.rs index b6a9ba01290..d715aca21a7 100644 --- a/library/std/src/keyword_docs.rs +++ b/library/std/src/keyword_docs.rs @@ -119,7 +119,7 @@ mod break_keyword {} #[doc(keyword = "const")] // -/// Compile-time constants, compile-time evaluable functions, and raw pointers. +/// Compile-time constants, compile-time blocks, compile-time evaluable functions, and raw pointers. /// /// ## Compile-time constants /// @@ -166,6 +166,12 @@ mod break_keyword {} /// /// For more detail on `const`, see the [Rust Book] or the [Reference]. /// +/// ## Compile-time blocks +/// +/// The `const` keyword can also be used to define a block of code that is evaluated at compile time. +/// This is useful for ensuring certain computations are completed before optimizations happen, as well as +/// before runtime. For more details, see the [Reference][const-blocks]. +/// /// ## Compile-time evaluable functions /// /// The other main use of the `const` keyword is in `const fn`. This marks a function as being @@ -184,6 +190,7 @@ mod break_keyword {} /// [pointer primitive]: pointer /// [Rust Book]: ../book/ch03-01-variables-and-mutability.html#constants /// [Reference]: ../reference/items/constant-items.html +/// [const-blocks]: ../reference/expressions/block-expr.html#const-blocks /// [const-eval]: ../reference/const_eval.html mod const_keyword {} @@ -381,11 +388,15 @@ mod enum_keyword {} /// lazy_static;`. The other use is in foreign function interfaces (FFI). /// /// `extern` is used in two different contexts within FFI. The first is in the form of external -/// blocks, for declaring function interfaces that Rust code can call foreign code by. +/// blocks, for declaring function interfaces that Rust code can call foreign code by. This use +/// of `extern` is unsafe, since we are asserting to the compiler that all function declarations +/// are correct. If they are not, using these items may lead to undefined behavior. /// /// ```rust ignore +/// // SAFETY: The function declarations given below are in +/// // line with the header files of `my_c_library`. /// #[link(name = "my_c_library")] -/// extern "C" { +/// unsafe extern "C" { /// fn my_c_function(x: i32) -> bool; /// } /// ``` diff --git a/library/std/src/lib.rs b/library/std/src/lib.rs index 5c381181218..ba57ad9bae3 100644 --- a/library/std/src/lib.rs +++ b/library/std/src/lib.rs @@ -312,7 +312,6 @@ #![feature(needs_panic_runtime)] #![feature(negative_impls)] #![feature(never_type)] -#![feature(no_sanitize)] #![feature(optimize_attribute)] #![feature(prelude_import)] #![feature(rustc_attrs)] @@ -330,7 +329,6 @@ #![feature(array_chunks)] #![feature(bstr)] #![feature(bstr_internals)] -#![feature(c_str_module)] #![feature(char_internals)] #![feature(clone_to_uninit)] #![feature(core_intrinsics)] @@ -345,6 +343,7 @@ #![feature(float_gamma)] #![feature(float_minimum_maximum)] #![feature(fmt_internals)] +#![feature(generic_atomic)] #![feature(hasher_prefixfree_extras)] #![feature(hashmap_internals)] #![feature(hint_must_use)] @@ -705,11 +704,18 @@ pub use core::cfg_match; reason = "`concat_bytes` is not stable enough for use and is subject to change" )] pub use core::concat_bytes; +#[stable(feature = "matches_macro", since = "1.42.0")] +#[allow(deprecated, deprecated_in_future)] +pub use core::matches; #[stable(feature = "core_primitive", since = "1.43.0")] pub use core::primitive; +#[stable(feature = "todo_macro", since = "1.40.0")] +#[allow(deprecated, deprecated_in_future)] +pub use core::todo; // Re-export built-in macros defined through core. #[stable(feature = "builtin_macro_prelude", since = "1.38.0")] #[allow(deprecated)] +#[cfg_attr(bootstrap, allow(deprecated_in_future))] pub use core::{ assert, assert_matches, cfg, column, compile_error, concat, concat_idents, const_format_args, env, file, format_args, format_args_nl, include, include_bytes, include_str, line, log_syntax, @@ -719,8 +725,8 @@ pub use core::{ #[stable(feature = "rust1", since = "1.0.0")] #[allow(deprecated, deprecated_in_future)] pub use core::{ - assert_eq, assert_ne, debug_assert, debug_assert_eq, debug_assert_ne, matches, todo, r#try, - unimplemented, unreachable, write, writeln, + assert_eq, assert_ne, debug_assert, debug_assert_eq, debug_assert_ne, r#try, unimplemented, + unreachable, write, writeln, }; // Include a number of private modules that exist solely to provide diff --git a/library/std/src/os/fd/owned.rs b/library/std/src/os/fd/owned.rs index be73e7dee9c..10e1e73a115 100644 --- a/library/std/src/os/fd/owned.rs +++ b/library/std/src/os/fd/owned.rs @@ -505,7 +505,7 @@ impl<'a> AsFd for io::StderrLock<'a> { } } -#[stable(feature = "anonymous_pipe", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "anonymous_pipe", since = "1.87.0")] #[cfg(not(target_os = "trusty"))] impl AsFd for io::PipeReader { fn as_fd(&self) -> BorrowedFd<'_> { @@ -513,7 +513,7 @@ impl AsFd for io::PipeReader { } } -#[stable(feature = "anonymous_pipe", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "anonymous_pipe", since = "1.87.0")] #[cfg(not(target_os = "trusty"))] impl From<io::PipeReader> for OwnedFd { fn from(pipe: io::PipeReader) -> Self { @@ -521,7 +521,7 @@ impl From<io::PipeReader> for OwnedFd { } } -#[stable(feature = "anonymous_pipe", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "anonymous_pipe", since = "1.87.0")] #[cfg(not(target_os = "trusty"))] impl AsFd for io::PipeWriter { fn as_fd(&self) -> BorrowedFd<'_> { @@ -529,7 +529,7 @@ impl AsFd for io::PipeWriter { } } -#[stable(feature = "anonymous_pipe", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "anonymous_pipe", since = "1.87.0")] #[cfg(not(target_os = "trusty"))] impl From<io::PipeWriter> for OwnedFd { fn from(pipe: io::PipeWriter) -> Self { @@ -537,7 +537,7 @@ impl From<io::PipeWriter> for OwnedFd { } } -#[stable(feature = "anonymous_pipe", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "anonymous_pipe", since = "1.87.0")] #[cfg(not(target_os = "trusty"))] impl From<OwnedFd> for io::PipeReader { fn from(owned_fd: OwnedFd) -> Self { @@ -545,7 +545,7 @@ impl From<OwnedFd> for io::PipeReader { } } -#[stable(feature = "anonymous_pipe", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "anonymous_pipe", since = "1.87.0")] #[cfg(not(target_os = "trusty"))] impl From<OwnedFd> for io::PipeWriter { fn from(owned_fd: OwnedFd) -> Self { diff --git a/library/std/src/os/fd/raw.rs b/library/std/src/os/fd/raw.rs index c800c1489ad..34a6cf1a8b8 100644 --- a/library/std/src/os/fd/raw.rs +++ b/library/std/src/os/fd/raw.rs @@ -285,7 +285,7 @@ impl<T: AsRawFd> AsRawFd for Box<T> { } } -#[stable(feature = "anonymous_pipe", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "anonymous_pipe", since = "1.87.0")] #[cfg(not(target_os = "trusty"))] impl AsRawFd for io::PipeReader { fn as_raw_fd(&self) -> RawFd { @@ -293,7 +293,7 @@ impl AsRawFd for io::PipeReader { } } -#[stable(feature = "anonymous_pipe", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "anonymous_pipe", since = "1.87.0")] #[cfg(not(target_os = "trusty"))] impl FromRawFd for io::PipeReader { unsafe fn from_raw_fd(raw_fd: RawFd) -> Self { @@ -301,7 +301,7 @@ impl FromRawFd for io::PipeReader { } } -#[stable(feature = "anonymous_pipe", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "anonymous_pipe", since = "1.87.0")] #[cfg(not(target_os = "trusty"))] impl IntoRawFd for io::PipeReader { fn into_raw_fd(self) -> RawFd { @@ -309,7 +309,7 @@ impl IntoRawFd for io::PipeReader { } } -#[stable(feature = "anonymous_pipe", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "anonymous_pipe", since = "1.87.0")] #[cfg(not(target_os = "trusty"))] impl AsRawFd for io::PipeWriter { fn as_raw_fd(&self) -> RawFd { @@ -317,7 +317,7 @@ impl AsRawFd for io::PipeWriter { } } -#[stable(feature = "anonymous_pipe", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "anonymous_pipe", since = "1.87.0")] #[cfg(not(target_os = "trusty"))] impl FromRawFd for io::PipeWriter { unsafe fn from_raw_fd(raw_fd: RawFd) -> Self { @@ -325,7 +325,7 @@ impl FromRawFd for io::PipeWriter { } } -#[stable(feature = "anonymous_pipe", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "anonymous_pipe", since = "1.87.0")] #[cfg(not(target_os = "trusty"))] impl IntoRawFd for io::PipeWriter { fn into_raw_fd(self) -> RawFd { diff --git a/library/std/src/os/uefi/env.rs b/library/std/src/os/uefi/env.rs index cf8ae697e38..ab5406e605c 100644 --- a/library/std/src/os/uefi/env.rs +++ b/library/std/src/os/uefi/env.rs @@ -4,13 +4,13 @@ use crate::ffi::c_void; use crate::ptr::NonNull; -use crate::sync::atomic::{AtomicBool, AtomicPtr, Ordering}; +use crate::sync::atomic::{Atomic, AtomicBool, AtomicPtr, Ordering}; -static SYSTEM_TABLE: AtomicPtr<c_void> = AtomicPtr::new(crate::ptr::null_mut()); -static IMAGE_HANDLE: AtomicPtr<c_void> = AtomicPtr::new(crate::ptr::null_mut()); +static SYSTEM_TABLE: Atomic<*mut c_void> = AtomicPtr::new(crate::ptr::null_mut()); +static IMAGE_HANDLE: Atomic<*mut c_void> = AtomicPtr::new(crate::ptr::null_mut()); // Flag to check if BootServices are still valid. // Start with assuming that they are not available -static BOOT_SERVICES_FLAG: AtomicBool = AtomicBool::new(false); +static BOOT_SERVICES_FLAG: Atomic<bool> = AtomicBool::new(false); /// Initializes the global System Table and Image Handle pointers. /// diff --git a/library/std/src/os/unix/fs.rs b/library/std/src/os/unix/fs.rs index 0427feb2955..4f9259f39c1 100644 --- a/library/std/src/os/unix/fs.rs +++ b/library/std/src/os/unix/fs.rs @@ -1100,3 +1100,39 @@ pub fn lchown<P: AsRef<Path>>(dir: P, uid: Option<u32>, gid: Option<u32>) -> io: pub fn chroot<P: AsRef<Path>>(dir: P) -> io::Result<()> { sys::fs::chroot(dir.as_ref()) } + +/// Create a FIFO special file at the specified path with the specified mode. +/// +/// # Examples +/// +/// ```no_run +/// # #![feature(unix_mkfifo)] +/// # #[cfg(not(unix))] +/// # fn main() {} +/// # #[cfg(unix)] +/// # fn main() -> std::io::Result<()> { +/// # use std::{ +/// # os::unix::fs::{mkfifo, PermissionsExt}, +/// # fs::{File, Permissions, remove_file}, +/// # io::{Write, Read}, +/// # }; +/// # let _ = remove_file("/tmp/fifo"); +/// mkfifo("/tmp/fifo", Permissions::from_mode(0o774))?; +/// +/// let mut wx = File::options().read(true).write(true).open("/tmp/fifo")?; +/// let mut rx = File::open("/tmp/fifo")?; +/// +/// wx.write_all(b"hello, world!")?; +/// drop(wx); +/// +/// let mut s = String::new(); +/// rx.read_to_string(&mut s)?; +/// +/// assert_eq!(s, "hello, world!"); +/// # Ok(()) +/// # } +/// ``` +#[unstable(feature = "unix_mkfifo", issue = "139324")] +pub fn mkfifo<P: AsRef<Path>>(path: P, permissions: Permissions) -> io::Result<()> { + sys::fs::mkfifo(path.as_ref(), permissions.mode()) +} diff --git a/library/std/src/os/unix/fs/tests.rs b/library/std/src/os/unix/fs/tests.rs index db9621c8c20..1840bb38c17 100644 --- a/library/std/src/os/unix/fs/tests.rs +++ b/library/std/src/os/unix/fs/tests.rs @@ -55,3 +55,23 @@ fn write_vectored_at() { let content = fs::read(&filename).unwrap(); assert_eq!(&content, expected); } + +#[test] +fn test_mkfifo() { + let tmp_dir = crate::test_helpers::tmpdir(); + + let fifo = tmp_dir.path().join("fifo"); + + mkfifo(&fifo, Permissions::from_mode(0o774)).unwrap(); + + let mut wx = fs::File::options().read(true).write(true).open(&fifo).unwrap(); + let mut rx = fs::File::open(fifo).unwrap(); + + wx.write_all(b"hello, world!").unwrap(); + drop(wx); + + let mut s = String::new(); + rx.read_to_string(&mut s).unwrap(); + + assert_eq!(s, "hello, world!"); +} diff --git a/library/std/src/os/windows/io/handle.rs b/library/std/src/os/windows/io/handle.rs index 7f21929b85f..4fc04b79315 100644 --- a/library/std/src/os/windows/io/handle.rs +++ b/library/std/src/os/windows/io/handle.rs @@ -661,42 +661,42 @@ impl<T> From<crate::thread::JoinHandle<T>> for OwnedHandle { } } -#[stable(feature = "anonymous_pipe", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "anonymous_pipe", since = "1.87.0")] impl AsHandle for io::PipeReader { fn as_handle(&self) -> BorrowedHandle<'_> { self.0.as_handle() } } -#[stable(feature = "anonymous_pipe", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "anonymous_pipe", since = "1.87.0")] impl From<io::PipeReader> for OwnedHandle { fn from(pipe: io::PipeReader) -> Self { pipe.into_inner().into_inner() } } -#[stable(feature = "anonymous_pipe", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "anonymous_pipe", since = "1.87.0")] impl AsHandle for io::PipeWriter { fn as_handle(&self) -> BorrowedHandle<'_> { self.0.as_handle() } } -#[stable(feature = "anonymous_pipe", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "anonymous_pipe", since = "1.87.0")] impl From<io::PipeWriter> for OwnedHandle { fn from(pipe: io::PipeWriter) -> Self { pipe.into_inner().into_inner() } } -#[stable(feature = "anonymous_pipe", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "anonymous_pipe", since = "1.87.0")] impl From<OwnedHandle> for io::PipeReader { fn from(owned_handle: OwnedHandle) -> Self { Self::from_inner(FromInner::from_inner(owned_handle)) } } -#[stable(feature = "anonymous_pipe", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "anonymous_pipe", since = "1.87.0")] impl From<OwnedHandle> for io::PipeWriter { fn from(owned_handle: OwnedHandle) -> Self { Self::from_inner(FromInner::from_inner(owned_handle)) diff --git a/library/std/src/os/windows/io/raw.rs b/library/std/src/os/windows/io/raw.rs index bc3e55c8629..a3ec7440338 100644 --- a/library/std/src/os/windows/io/raw.rs +++ b/library/std/src/os/windows/io/raw.rs @@ -311,42 +311,42 @@ impl IntoRawSocket for net::UdpSocket { } } -#[stable(feature = "anonymous_pipe", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "anonymous_pipe", since = "1.87.0")] impl AsRawHandle for io::PipeReader { fn as_raw_handle(&self) -> RawHandle { self.0.as_raw_handle() } } -#[stable(feature = "anonymous_pipe", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "anonymous_pipe", since = "1.87.0")] impl FromRawHandle for io::PipeReader { unsafe fn from_raw_handle(raw_handle: RawHandle) -> Self { unsafe { Self::from_inner(FromRawHandle::from_raw_handle(raw_handle)) } } } -#[stable(feature = "anonymous_pipe", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "anonymous_pipe", since = "1.87.0")] impl IntoRawHandle for io::PipeReader { fn into_raw_handle(self) -> RawHandle { self.0.into_raw_handle() } } -#[stable(feature = "anonymous_pipe", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "anonymous_pipe", since = "1.87.0")] impl AsRawHandle for io::PipeWriter { fn as_raw_handle(&self) -> RawHandle { self.0.as_raw_handle() } } -#[stable(feature = "anonymous_pipe", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "anonymous_pipe", since = "1.87.0")] impl FromRawHandle for io::PipeWriter { unsafe fn from_raw_handle(raw_handle: RawHandle) -> Self { unsafe { Self::from_inner(FromRawHandle::from_raw_handle(raw_handle)) } } } -#[stable(feature = "anonymous_pipe", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "anonymous_pipe", since = "1.87.0")] impl IntoRawHandle for io::PipeWriter { fn into_raw_handle(self) -> RawHandle { self.0.into_raw_handle() diff --git a/library/std/src/os/xous/services.rs b/library/std/src/os/xous/services.rs index 93916750c05..0681485ea06 100644 --- a/library/std/src/os/xous/services.rs +++ b/library/std/src/os/xous/services.rs @@ -1,4 +1,4 @@ -use core::sync::atomic::{AtomicU32, Ordering}; +use core::sync::atomic::{Atomic, AtomicU32, Ordering}; use crate::os::xous::ffi::Connection; @@ -106,7 +106,7 @@ pub fn try_connect(name: &str) -> Option<Connection> { ns::try_connect_with_name(name) } -static NAME_SERVER_CONNECTION: AtomicU32 = AtomicU32::new(0); +static NAME_SERVER_CONNECTION: Atomic<u32> = AtomicU32::new(0); /// Returns a `Connection` to the name server. If the name server has not been started, /// then this call will block until the name server has been started. The `Connection` diff --git a/library/std/src/os/xous/services/dns.rs b/library/std/src/os/xous/services/dns.rs index 02881648393..7641d1f15e4 100644 --- a/library/std/src/os/xous/services/dns.rs +++ b/library/std/src/os/xous/services/dns.rs @@ -1,4 +1,4 @@ -use core::sync::atomic::{AtomicU32, Ordering}; +use core::sync::atomic::{Atomic, AtomicU32, Ordering}; use crate::os::xous::ffi::Connection; use crate::os::xous::services::connect; @@ -17,7 +17,7 @@ impl Into<usize> for DnsLendMut { /// Returns a `Connection` to the DNS lookup server. This server is used for /// querying domain name values. pub(crate) fn dns_server() -> Connection { - static DNS_CONNECTION: AtomicU32 = AtomicU32::new(0); + static DNS_CONNECTION: Atomic<u32> = AtomicU32::new(0); let cid = DNS_CONNECTION.load(Ordering::Relaxed); if cid != 0 { return cid.into(); diff --git a/library/std/src/os/xous/services/log.rs b/library/std/src/os/xous/services/log.rs index 095d4f4a3e7..e7717c8515d 100644 --- a/library/std/src/os/xous/services/log.rs +++ b/library/std/src/os/xous/services/log.rs @@ -1,4 +1,4 @@ -use core::sync::atomic::{AtomicU32, Ordering}; +use core::sync::atomic::{Atomic, AtomicU32, Ordering}; use crate::os::xous::ffi::Connection; @@ -64,7 +64,7 @@ impl Into<usize> for LogLend { /// running. It is safe to call this multiple times, because the address is /// shared among all threads in a process. pub(crate) fn log_server() -> Connection { - static LOG_SERVER_CONNECTION: AtomicU32 = AtomicU32::new(0); + static LOG_SERVER_CONNECTION: Atomic<u32> = AtomicU32::new(0); let cid = LOG_SERVER_CONNECTION.load(Ordering::Relaxed); if cid != 0 { diff --git a/library/std/src/os/xous/services/net.rs b/library/std/src/os/xous/services/net.rs index 83acc7961b3..c20bf1a7ad5 100644 --- a/library/std/src/os/xous/services/net.rs +++ b/library/std/src/os/xous/services/net.rs @@ -1,4 +1,4 @@ -use core::sync::atomic::{AtomicU32, Ordering}; +use core::sync::atomic::{Atomic, AtomicU32, Ordering}; use crate::os::xous::ffi::Connection; use crate::os::xous::services::connect; @@ -84,7 +84,7 @@ impl<'a> Into<[usize; 5]> for NetBlockingScalar { /// Returns a `Connection` to the Network server. This server provides all /// OS-level networking functions. pub(crate) fn net_server() -> Connection { - static NET_CONNECTION: AtomicU32 = AtomicU32::new(0); + static NET_CONNECTION: Atomic<u32> = AtomicU32::new(0); let cid = NET_CONNECTION.load(Ordering::Relaxed); if cid != 0 { return cid.into(); diff --git a/library/std/src/os/xous/services/systime.rs b/library/std/src/os/xous/services/systime.rs index de87694b4cd..e54cffdc4c0 100644 --- a/library/std/src/os/xous/services/systime.rs +++ b/library/std/src/os/xous/services/systime.rs @@ -1,4 +1,4 @@ -use core::sync::atomic::{AtomicU32, Ordering}; +use core::sync::atomic::{Atomic, AtomicU32, Ordering}; use crate::os::xous::ffi::{Connection, connect}; @@ -17,7 +17,7 @@ impl Into<[usize; 5]> for SystimeScalar { /// Returns a `Connection` to the systime server. This server is used for reporting the /// realtime clock. pub(crate) fn systime_server() -> Connection { - static SYSTIME_SERVER_CONNECTION: AtomicU32 = AtomicU32::new(0); + static SYSTIME_SERVER_CONNECTION: Atomic<u32> = AtomicU32::new(0); let cid = SYSTIME_SERVER_CONNECTION.load(Ordering::Relaxed); if cid != 0 { return cid.into(); diff --git a/library/std/src/os/xous/services/ticktimer.rs b/library/std/src/os/xous/services/ticktimer.rs index 66ade6da65c..bf51ecde8e5 100644 --- a/library/std/src/os/xous/services/ticktimer.rs +++ b/library/std/src/os/xous/services/ticktimer.rs @@ -1,4 +1,4 @@ -use core::sync::atomic::{AtomicU32, Ordering}; +use core::sync::atomic::{Atomic, AtomicU32, Ordering}; use crate::os::xous::ffi::Connection; @@ -31,7 +31,7 @@ impl Into<[usize; 5]> for TicktimerScalar { /// Returns a `Connection` to the ticktimer server. This server is used for synchronization /// primitives such as sleep, Mutex, and Condvar. pub(crate) fn ticktimer_server() -> Connection { - static TICKTIMER_SERVER_CONNECTION: AtomicU32 = AtomicU32::new(0); + static TICKTIMER_SERVER_CONNECTION: Atomic<u32> = AtomicU32::new(0); let cid = TICKTIMER_SERVER_CONNECTION.load(Ordering::Relaxed); if cid != 0 { return cid.into(); diff --git a/library/std/src/panic.rs b/library/std/src/panic.rs index 22776ae2bc4..f3b26ac64df 100644 --- a/library/std/src/panic.rs +++ b/library/std/src/panic.rs @@ -3,7 +3,7 @@ #![stable(feature = "std_panic", since = "1.9.0")] use crate::any::Any; -use crate::sync::atomic::{AtomicU8, Ordering}; +use crate::sync::atomic::{Atomic, AtomicU8, Ordering}; use crate::sync::{Condvar, Mutex, RwLock}; use crate::thread::Result; use crate::{collections, fmt, panicking}; @@ -469,7 +469,7 @@ impl BacktraceStyle { // that backtrace. // // Internally stores equivalent of an Option<BacktraceStyle>. -static SHOULD_CAPTURE: AtomicU8 = AtomicU8::new(0); +static SHOULD_CAPTURE: Atomic<u8> = AtomicU8::new(0); /// Configures whether the default panic hook will capture and display a /// backtrace. diff --git a/library/std/src/panicking.rs b/library/std/src/panicking.rs index b35549c92ad..4bfedf78366 100644 --- a/library/std/src/panicking.rs +++ b/library/std/src/panicking.rs @@ -21,7 +21,7 @@ use crate::any::Any; use crate::io::try_set_output_capture; use crate::mem::{self, ManuallyDrop}; use crate::panic::{BacktraceStyle, PanicHookInfo}; -use crate::sync::atomic::{AtomicBool, Ordering}; +use crate::sync::atomic::{Atomic, AtomicBool, Ordering}; use crate::sync::{PoisonError, RwLock}; use crate::sys::backtrace; use crate::sys::stdio::panic_output; @@ -55,14 +55,14 @@ pub static EMPTY_PANIC: fn(&'static str) -> ! = // hook up these functions, but it is not this day! #[allow(improper_ctypes)] unsafe extern "C" { - #[cfg_attr(not(bootstrap), rustc_std_internal_symbol)] + #[rustc_std_internal_symbol] fn __rust_panic_cleanup(payload: *mut u8) -> *mut (dyn Any + Send + 'static); } unsafe extern "Rust" { /// `PanicPayload` lazily performs allocation only when needed (this avoids /// allocations when using the "abort" panic runtime). - #[cfg_attr(not(bootstrap), rustc_std_internal_symbol)] + #[rustc_std_internal_symbol] fn __rust_start_panic(payload: &mut dyn PanicPayload) -> u32; } @@ -289,7 +289,7 @@ fn default_hook(info: &PanicHookInfo<'_>) { }; }); - static FIRST_PANIC: AtomicBool = AtomicBool::new(true); + static FIRST_PANIC: Atomic<bool> = AtomicBool::new(true); match backtrace { // SAFETY: we took out a lock just a second ago. @@ -374,7 +374,7 @@ pub mod panic_count { #[unstable(feature = "update_panic_count", issue = "none")] pub mod panic_count { use crate::cell::Cell; - use crate::sync::atomic::{AtomicUsize, Ordering}; + use crate::sync::atomic::{Atomic, AtomicUsize, Ordering}; const ALWAYS_ABORT_FLAG: usize = 1 << (usize::BITS - 1); @@ -416,7 +416,7 @@ pub mod panic_count { // // Stealing a bit is fine because it just amounts to assuming that each // panicking thread consumes at least 2 bytes of address space. - static GLOBAL_PANIC_COUNT: AtomicUsize = AtomicUsize::new(0); + static GLOBAL_PANIC_COUNT: Atomic<usize> = AtomicUsize::new(0); // Increases the global and local panic count, and returns whether an // immediate abort is required. diff --git a/library/std/src/path.rs b/library/std/src/path.rs index 980213be7ea..7cd20c48d89 100644 --- a/library/std/src/path.rs +++ b/library/std/src/path.rs @@ -353,6 +353,15 @@ fn split_file_at_dot(file: &OsStr) -> (&OsStr, Option<&OsStr>) { } } +/// Checks whether the string is valid as a file extension, or panics otherwise. +fn validate_extension(extension: &OsStr) { + for &b in extension.as_encoded_bytes() { + if is_sep_byte(b) { + panic!("extension cannot contain path separators: {extension:?}"); + } + } +} + //////////////////////////////////////////////////////////////////////////////// // The core iterators //////////////////////////////////////////////////////////////////////////////// @@ -1507,13 +1516,7 @@ impl PathBuf { } fn _set_extension(&mut self, extension: &OsStr) -> bool { - for &b in extension.as_encoded_bytes() { - if b < 128 { - if is_separator(b as char) { - panic!("extension cannot contain path separators: {:?}", extension); - } - } - } + validate_extension(extension); let file_stem = match self.file_stem() { None => return false, @@ -1541,6 +1544,11 @@ impl PathBuf { /// Returns `false` and does nothing if [`self.file_name`] is [`None`], /// returns `true` and updates the extension otherwise. /// + /// # Panics + /// + /// Panics if the passed extension contains a path separator (see + /// [`is_separator`]). + /// /// # Caveats /// /// The appended `extension` may contain dots and will be used in its entirety, @@ -1582,6 +1590,8 @@ impl PathBuf { } fn _add_extension(&mut self, extension: &OsStr) -> bool { + validate_extension(extension); + let file_name = match self.file_name() { None => return false, Some(f) => f.as_encoded_bytes(), @@ -3265,7 +3275,7 @@ impl Hash for Path { if !verbatim { component_start += match tail { [b'.'] => 1, - [b'.', sep @ _, ..] if is_sep_byte(*sep) => 1, + [b'.', sep, ..] if is_sep_byte(*sep) => 1, _ => 0, }; } diff --git a/library/std/src/prelude/v1.rs b/library/std/src/prelude/v1.rs index 4217f658640..68c9ac1e414 100644 --- a/library/std/src/prelude/v1.rs +++ b/library/std/src/prelude/v1.rs @@ -46,6 +46,7 @@ pub use crate::result::Result::{self, Err, Ok}; // Re-exported built-in macros #[stable(feature = "builtin_macro_prelude", since = "1.38.0")] #[allow(deprecated)] +#[cfg_attr(bootstrap, allow(deprecated_in_future))] #[doc(no_inline)] pub use core::prelude::v1::{ assert, cfg, column, compile_error, concat, concat_idents, env, file, format_args, @@ -109,7 +110,6 @@ pub use core::prelude::v1::deref; issue = "63063", reason = "`type_alias_impl_trait` has open design concerns" )] -#[cfg(not(bootstrap))] pub use core::prelude::v1::define_opaque; // The file so far is equivalent to core/src/prelude/v1.rs. It is duplicated diff --git a/library/std/src/process.rs b/library/std/src/process.rs index 3b765a9537b..76ce7bce81b 100644 --- a/library/std/src/process.rs +++ b/library/std/src/process.rs @@ -1286,6 +1286,40 @@ pub struct Output { pub stderr: Vec<u8>, } +impl Output { + /// Returns an error if a nonzero exit status was received. + /// + /// If the [`Command`] exited successfully, + /// `self` is returned. + /// + /// This is equivalent to calling [`exit_ok`](ExitStatus::exit_ok) + /// on [`Output.status`](Output::status). + /// + /// Note that this will throw away the [`Output::stderr`] field in the error case. + /// If the child process outputs useful informantion to stderr, you can: + /// * Use `cmd.stderr(Stdio::inherit())` to forward the + /// stderr child process to the parent's stderr, + /// usually printing it to console where the user can see it. + /// This is usually correct for command-line applications. + /// * Capture `stderr` using a custom error type. + /// This is usually correct for libraries. + /// + /// # Examples + /// + /// ``` + /// #![feature(exit_status_error)] + /// # #[cfg(unix)] { + /// use std::process::Command; + /// assert!(Command::new("false").output().unwrap().exit_ok().is_err()); + /// # } + /// ``` + #[unstable(feature = "exit_status_error", issue = "84908")] + pub fn exit_ok(self) -> Result<Self, ExitStatusError> { + self.status.exit_ok()?; + Ok(self) + } +} + // If either stderr or stdout are valid utf8 strings it prints the valid // strings, otherwise it prints the byte sequence instead #[stable(feature = "process_output_debug", since = "1.7.0")] @@ -1659,14 +1693,14 @@ impl From<io::Stderr> for Stdio { } } -#[stable(feature = "anonymous_pipe", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "anonymous_pipe", since = "1.87.0")] impl From<io::PipeWriter> for Stdio { fn from(pipe: io::PipeWriter) -> Self { Stdio::from_inner(pipe.into_inner().into()) } } -#[stable(feature = "anonymous_pipe", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "anonymous_pipe", since = "1.87.0")] impl From<io::PipeReader> for Stdio { fn from(pipe: io::PipeReader) -> Self { Stdio::from_inner(pipe.into_inner().into()) diff --git a/library/std/src/rt.rs b/library/std/src/rt.rs index 3a22a16cb16..9737b2f5bfe 100644 --- a/library/std/src/rt.rs +++ b/library/std/src/rt.rs @@ -46,7 +46,7 @@ macro_rules! rtprintpanic { macro_rules! rtabort { ($($t:tt)*) => { { - rtprintpanic!("fatal runtime error: {}\n", format_args!($($t)*)); + rtprintpanic!("fatal runtime error: {}, aborting\n", format_args!($($t)*)); crate::sys::abort_internal(); } } diff --git a/library/std/src/sync/mpmc/array.rs b/library/std/src/sync/mpmc/array.rs index a467237fef1..880d8b5f57c 100644 --- a/library/std/src/sync/mpmc/array.rs +++ b/library/std/src/sync/mpmc/array.rs @@ -16,13 +16,13 @@ use super::waker::SyncWaker; use crate::cell::UnsafeCell; use crate::mem::MaybeUninit; use crate::ptr; -use crate::sync::atomic::{self, AtomicUsize, Ordering}; +use crate::sync::atomic::{self, Atomic, AtomicUsize, Ordering}; use crate::time::Instant; /// A slot in a channel. struct Slot<T> { /// The current stamp. - stamp: AtomicUsize, + stamp: Atomic<usize>, /// The message in this slot. Either read out in `read` or dropped through /// `discard_all_messages`. @@ -55,7 +55,7 @@ pub(crate) struct Channel<T> { /// represent the lap. The mark bit in the head is always zero. /// /// Messages are popped from the head of the channel. - head: CachePadded<AtomicUsize>, + head: CachePadded<Atomic<usize>>, /// The tail of the channel. /// @@ -64,7 +64,7 @@ pub(crate) struct Channel<T> { /// represent the lap. The mark bit indicates that the channel is disconnected. /// /// Messages are pushed into the tail of the channel. - tail: CachePadded<AtomicUsize>, + tail: CachePadded<Atomic<usize>>, /// The buffer holding slots. buffer: Box<[Slot<T>]>, diff --git a/library/std/src/sync/mpmc/context.rs b/library/std/src/sync/mpmc/context.rs index 51aa7e82e78..6b2f4cb6ffd 100644 --- a/library/std/src/sync/mpmc/context.rs +++ b/library/std/src/sync/mpmc/context.rs @@ -5,7 +5,7 @@ use super::waker::current_thread_id; use crate::cell::Cell; use crate::ptr; use crate::sync::Arc; -use crate::sync::atomic::{AtomicPtr, AtomicUsize, Ordering}; +use crate::sync::atomic::{Atomic, AtomicPtr, AtomicUsize, Ordering}; use crate::thread::{self, Thread}; use crate::time::Instant; @@ -19,10 +19,10 @@ pub struct Context { #[derive(Debug)] struct Inner { /// Selected operation. - select: AtomicUsize, + select: Atomic<usize>, /// A slot into which another thread may store a pointer to its `Packet`. - packet: AtomicPtr<()>, + packet: Atomic<*mut ()>, /// Thread handle. thread: Thread, diff --git a/library/std/src/sync/mpmc/counter.rs b/library/std/src/sync/mpmc/counter.rs index d1bfe612f53..efa6af11483 100644 --- a/library/std/src/sync/mpmc/counter.rs +++ b/library/std/src/sync/mpmc/counter.rs @@ -1,16 +1,16 @@ -use crate::sync::atomic::{AtomicBool, AtomicUsize, Ordering}; +use crate::sync::atomic::{Atomic, AtomicBool, AtomicUsize, Ordering}; use crate::{ops, process}; /// Reference counter internals. struct Counter<C> { /// The number of senders associated with the channel. - senders: AtomicUsize, + senders: Atomic<usize>, /// The number of receivers associated with the channel. - receivers: AtomicUsize, + receivers: Atomic<usize>, /// Set to `true` if the last sender or the last receiver reference deallocates the channel. - destroy: AtomicBool, + destroy: Atomic<bool>, /// The internal channel. chan: C, diff --git a/library/std/src/sync/mpmc/list.rs b/library/std/src/sync/mpmc/list.rs index d88914f5291..3fcfb85cf2a 100644 --- a/library/std/src/sync/mpmc/list.rs +++ b/library/std/src/sync/mpmc/list.rs @@ -9,7 +9,7 @@ use crate::cell::UnsafeCell; use crate::marker::PhantomData; use crate::mem::MaybeUninit; use crate::ptr; -use crate::sync::atomic::{self, AtomicPtr, AtomicUsize, Ordering}; +use crate::sync::atomic::{self, Atomic, AtomicPtr, AtomicUsize, Ordering}; use crate::time::Instant; // Bits indicating the state of a slot: @@ -37,7 +37,7 @@ struct Slot<T> { msg: UnsafeCell<MaybeUninit<T>>, /// The state of the slot. - state: AtomicUsize, + state: Atomic<usize>, } impl<T> Slot<T> { @@ -55,7 +55,7 @@ impl<T> Slot<T> { /// Each block in the list can hold up to `BLOCK_CAP` messages. struct Block<T> { /// The next block in the linked list. - next: AtomicPtr<Block<T>>, + next: Atomic<*mut Block<T>>, /// Slots for messages. slots: [Slot<T>; BLOCK_CAP], @@ -65,11 +65,11 @@ impl<T> Block<T> { /// Creates an empty block. fn new() -> Box<Block<T>> { // SAFETY: This is safe because: - // [1] `Block::next` (AtomicPtr) may be safely zero initialized. + // [1] `Block::next` (Atomic<*mut _>) may be safely zero initialized. // [2] `Block::slots` (Array) may be safely zero initialized because of [3, 4]. // [3] `Slot::msg` (UnsafeCell) may be safely zero initialized because it // holds a MaybeUninit. - // [4] `Slot::state` (AtomicUsize) may be safely zero initialized. + // [4] `Slot::state` (Atomic<usize>) may be safely zero initialized. unsafe { Box::new_zeroed().assume_init() } } @@ -110,10 +110,10 @@ impl<T> Block<T> { #[derive(Debug)] struct Position<T> { /// The index in the channel. - index: AtomicUsize, + index: Atomic<usize>, /// The block in the linked list. - block: AtomicPtr<Block<T>>, + block: Atomic<*mut Block<T>>, } /// The token type for the list flavor. @@ -213,6 +213,11 @@ impl<T> Channel<T> { .compare_exchange(block, new, Ordering::Release, Ordering::Relaxed) .is_ok() { + // This yield point leaves the channel in a half-initialized state where the + // tail.block pointer is set but the head.block is not. This is used to + // facilitate the test in src/tools/miri/tests/pass/issues/issue-139553.rs + #[cfg(miri)] + crate::thread::yield_now(); self.head.block.store(new, Ordering::Release); block = new; } else { @@ -564,9 +569,15 @@ impl<T> Channel<T> { // In that case, just wait until it gets initialized. while block.is_null() { backoff.spin_heavy(); - block = self.head.block.load(Ordering::Acquire); + block = self.head.block.swap(ptr::null_mut(), Ordering::AcqRel); } } + // After this point `head.block` is not modified again and it will be deallocated if it's + // non-null. The `Drop` code of the channel, which runs after this function, also attempts + // to deallocate `head.block` if it's non-null. Therefore this function must maintain the + // invariant that if a deallocation of head.block is attemped then it must also be set to + // NULL. Failing to do so will lead to the Drop code attempting a double free. For this + // reason both reads above do an atomic swap instead of a simple atomic load. unsafe { // Drop all messages between head and tail and deallocate the heap-allocated blocks. diff --git a/library/std/src/sync/mpmc/waker.rs b/library/std/src/sync/mpmc/waker.rs index f5e764e69bd..4216fb7ac59 100644 --- a/library/std/src/sync/mpmc/waker.rs +++ b/library/std/src/sync/mpmc/waker.rs @@ -4,7 +4,7 @@ use super::context::Context; use super::select::{Operation, Selected}; use crate::ptr; use crate::sync::Mutex; -use crate::sync::atomic::{AtomicBool, Ordering}; +use crate::sync::atomic::{Atomic, AtomicBool, Ordering}; /// Represents a thread blocked on a specific channel operation. pub(crate) struct Entry { @@ -137,7 +137,7 @@ pub(crate) struct SyncWaker { inner: Mutex<Waker>, /// `true` if the waker is empty. - is_empty: AtomicBool, + is_empty: Atomic<bool>, } impl SyncWaker { diff --git a/library/std/src/sync/mpmc/zero.rs b/library/std/src/sync/mpmc/zero.rs index 577997c07a6..f1ecf80fcb9 100644 --- a/library/std/src/sync/mpmc/zero.rs +++ b/library/std/src/sync/mpmc/zero.rs @@ -10,7 +10,7 @@ use super::waker::Waker; use crate::cell::UnsafeCell; use crate::marker::PhantomData; use crate::sync::Mutex; -use crate::sync::atomic::{AtomicBool, Ordering}; +use crate::sync::atomic::{Atomic, AtomicBool, Ordering}; use crate::time::Instant; use crate::{fmt, ptr}; @@ -35,7 +35,7 @@ struct Packet<T> { on_stack: bool, /// Equals `true` once the packet is ready for reading or writing. - ready: AtomicBool, + ready: Atomic<bool>, /// The message. msg: UnsafeCell<Option<T>>, diff --git a/library/std/src/sync/poison.rs b/library/std/src/sync/poison.rs index 1b8809734b8..cc1d0b30152 100644 --- a/library/std/src/sync/poison.rs +++ b/library/std/src/sync/poison.rs @@ -76,7 +76,7 @@ pub use self::rwlock::{RwLock, RwLockReadGuard, RwLockWriteGuard}; use crate::error::Error; use crate::fmt; #[cfg(panic = "unwind")] -use crate::sync::atomic::{AtomicBool, Ordering}; +use crate::sync::atomic::{Atomic, AtomicBool, Ordering}; #[cfg(panic = "unwind")] use crate::thread; @@ -88,7 +88,7 @@ mod rwlock; pub(crate) struct Flag { #[cfg(panic = "unwind")] - failed: AtomicBool, + failed: Atomic<bool>, } // Note that the Ordering uses to access the `failed` field of `Flag` below is diff --git a/library/std/src/sync/poison/mutex.rs b/library/std/src/sync/poison/mutex.rs index 9362c764173..adb74bb6f3d 100644 --- a/library/std/src/sync/poison/mutex.rs +++ b/library/std/src/sync/poison/mutex.rs @@ -582,7 +582,9 @@ impl<T: ?Sized> Mutex<T> { /// Returns a mutable reference to the underlying data. /// /// Since this call borrows the `Mutex` mutably, no actual locking needs to - /// take place -- the mutable borrow statically guarantees no locks exist. + /// take place -- the mutable borrow statically guarantees no new locks can be acquired + /// while this reference exists. Note that this method does not clear any previous abandoned locks + /// (e.g., via [`forget()`] on a [`MutexGuard`]). /// /// # Errors /// @@ -599,6 +601,8 @@ impl<T: ?Sized> Mutex<T> { /// *mutex.get_mut().unwrap() = 10; /// assert_eq!(*mutex.lock().unwrap(), 10); /// ``` + /// + /// [`forget()`]: mem::forget #[stable(feature = "mutex_get_mut", since = "1.6.0")] pub fn get_mut(&mut self) -> LockResult<&mut T> { let data = self.data.get_mut(); diff --git a/library/std/src/sync/poison/rwlock.rs b/library/std/src/sync/poison/rwlock.rs index f9d9321f5f2..a2abd4f692e 100644 --- a/library/std/src/sync/poison/rwlock.rs +++ b/library/std/src/sync/poison/rwlock.rs @@ -608,7 +608,9 @@ impl<T: ?Sized> RwLock<T> { /// Returns a mutable reference to the underlying data. /// /// Since this call borrows the `RwLock` mutably, no actual locking needs to - /// take place -- the mutable borrow statically guarantees no locks exist. + /// take place -- the mutable borrow statically guarantees no new locks can be acquired + /// while this reference exists. Note that this method does not clear any previously abandoned locks + /// (e.g., via [`forget()`] on a [`RwLockReadGuard`] or [`RwLockWriteGuard`]). /// /// # Errors /// diff --git a/library/std/src/sync/reentrant_lock.rs b/library/std/src/sync/reentrant_lock.rs index e009eb410ef..24539d4e830 100644 --- a/library/std/src/sync/reentrant_lock.rs +++ b/library/std/src/sync/reentrant_lock.rs @@ -89,9 +89,9 @@ pub struct ReentrantLock<T: ?Sized> { cfg_if!( if #[cfg(target_has_atomic = "64")] { - use crate::sync::atomic::{AtomicU64, Ordering::Relaxed}; + use crate::sync::atomic::{Atomic, AtomicU64, Ordering::Relaxed}; - struct Tid(AtomicU64); + struct Tid(Atomic<u64>); impl Tid { const fn new() -> Self { @@ -120,6 +120,7 @@ cfg_if!( } use crate::sync::atomic::{ + Atomic, AtomicUsize, Ordering, }; @@ -137,7 +138,7 @@ cfg_if!( // the current thread, or by a thread that has terminated before // the current thread was created. In either case, no further // synchronization is needed (as per <https://github.com/rust-lang/miri/issues/3450>) - tls_addr: AtomicUsize, + tls_addr: Atomic<usize>, tid: UnsafeCell<u64>, } diff --git a/library/std/src/sys/alloc/sgx.rs b/library/std/src/sys/alloc/sgx.rs index f5c27688fbc..afdef7a5cb6 100644 --- a/library/std/src/sys/alloc/sgx.rs +++ b/library/std/src/sys/alloc/sgx.rs @@ -1,6 +1,6 @@ use crate::alloc::{GlobalAlloc, Layout, System}; use crate::ptr; -use crate::sync::atomic::{AtomicBool, Ordering}; +use crate::sync::atomic::{Atomic, AtomicBool, Ordering}; use crate::sys::pal::abi::mem as sgx_mem; use crate::sys::pal::waitqueue::SpinMutex; @@ -10,8 +10,10 @@ use crate::sys::pal::waitqueue::SpinMutex; // The current allocator here is the `dlmalloc` crate which we've got included // in the rust-lang/rust repository as a submodule. The crate is a port of // dlmalloc.c from C to Rust. +// +// Specifying linkage/symbol name is solely to ensure a single instance between this crate and its unit tests #[cfg_attr(test, linkage = "available_externally")] -#[unsafe(export_name = "_ZN16__rust_internals3std3sys3sgx5alloc8DLMALLOCE")] +#[unsafe(export_name = "_ZN16__rust_internals3std3sys5alloc3sgx8DLMALLOCE")] static DLMALLOC: SpinMutex<dlmalloc::Dlmalloc<Sgx>> = SpinMutex::new(dlmalloc::Dlmalloc::new_with_allocator(Sgx {})); @@ -20,7 +22,7 @@ struct Sgx; unsafe impl dlmalloc::Allocator for Sgx { /// Allocs system resources fn alloc(&self, _size: usize) -> (*mut u8, usize, u32) { - static INIT: AtomicBool = AtomicBool::new(false); + static INIT: Atomic<bool> = AtomicBool::new(false); // No ordering requirement since this function is protected by the global lock. if !INIT.swap(true, Ordering::Relaxed) { diff --git a/library/std/src/sys/alloc/wasm.rs b/library/std/src/sys/alloc/wasm.rs index 53fbc9529e5..c8fab992a88 100644 --- a/library/std/src/sys/alloc/wasm.rs +++ b/library/std/src/sys/alloc/wasm.rs @@ -60,10 +60,10 @@ unsafe impl GlobalAlloc for System { #[cfg(target_feature = "atomics")] mod lock { - use crate::sync::atomic::AtomicI32; use crate::sync::atomic::Ordering::{Acquire, Release}; + use crate::sync::atomic::{Atomic, AtomicI32}; - static LOCKED: AtomicI32 = AtomicI32::new(0); + static LOCKED: Atomic<i32> = AtomicI32::new(0); pub struct DropLock; diff --git a/library/std/src/sys/alloc/xous.rs b/library/std/src/sys/alloc/xous.rs index ccaa972c22d..c7f973b8027 100644 --- a/library/std/src/sys/alloc/xous.rs +++ b/library/std/src/sys/alloc/xous.rs @@ -49,10 +49,10 @@ unsafe impl GlobalAlloc for System { } mod lock { - use crate::sync::atomic::AtomicI32; use crate::sync::atomic::Ordering::{Acquire, Release}; + use crate::sync::atomic::{Atomic, AtomicI32}; - static LOCKED: AtomicI32 = AtomicI32::new(0); + static LOCKED: Atomic<i32> = AtomicI32::new(0); pub struct DropLock; diff --git a/library/std/src/sys/args/common.rs b/library/std/src/sys/args/common.rs new file mode 100644 index 00000000000..43ac5e95923 --- /dev/null +++ b/library/std/src/sys/args/common.rs @@ -0,0 +1,43 @@ +use crate::ffi::OsString; +use crate::{fmt, vec}; + +pub struct Args { + iter: vec::IntoIter<OsString>, +} + +impl !Send for Args {} +impl !Sync for Args {} + +impl Args { + pub(super) fn new(args: Vec<OsString>) -> Self { + Args { iter: args.into_iter() } + } +} + +impl fmt::Debug for Args { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + self.iter.as_slice().fmt(f) + } +} + +impl Iterator for Args { + type Item = OsString; + fn next(&mut self) -> Option<OsString> { + self.iter.next() + } + fn size_hint(&self) -> (usize, Option<usize>) { + self.iter.size_hint() + } +} + +impl ExactSizeIterator for Args { + fn len(&self) -> usize { + self.iter.len() + } +} + +impl DoubleEndedIterator for Args { + fn next_back(&mut self) -> Option<OsString> { + self.iter.next_back() + } +} diff --git a/library/std/src/sys/args/mod.rs b/library/std/src/sys/args/mod.rs new file mode 100644 index 00000000000..0011f55dc14 --- /dev/null +++ b/library/std/src/sys/args/mod.rs @@ -0,0 +1,44 @@ +//! Platform-dependent command line arguments abstraction. + +#![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"))), + target_os = "hermit", + ))] { + mod unix; + pub use unix::*; + } else if #[cfg(target_family = "windows")] { + mod windows; + pub use windows::*; + } else if #[cfg(all(target_vendor = "fortanix", target_env = "sgx"))] { + mod sgx; + pub use sgx::*; + } else if #[cfg(target_os = "uefi")] { + mod uefi; + pub use uefi::*; + } else if #[cfg(target_os = "wasi")] { + mod wasi; + pub use wasi::*; + } else if #[cfg(target_os = "xous")] { + mod xous; + pub use xous::*; + } else if #[cfg(target_os = "zkvm")] { + mod zkvm; + pub use zkvm::*; + } else { + mod unsupported; + pub use unsupported::*; + } +} diff --git a/library/std/src/sys/pal/sgx/args.rs b/library/std/src/sys/args/sgx.rs index e62bf383954..2a4bc76aefb 100644 --- a/library/std/src/sys/pal/sgx/args.rs +++ b/library/std/src/sys/args/sgx.rs @@ -1,14 +1,17 @@ -use super::abi::usercalls::alloc; -use super::abi::usercalls::raw::ByteBuffer; +#![allow(fuzzy_provenance_casts)] // FIXME: this module systematically confuses pointers and integers + use crate::ffi::OsString; -use crate::sync::atomic::{AtomicUsize, Ordering}; +use crate::sync::atomic::{Atomic, AtomicUsize, Ordering}; use crate::sys::os_str::Buf; +use crate::sys::pal::abi::usercalls::alloc; +use crate::sys::pal::abi::usercalls::raw::ByteBuffer; use crate::sys_common::FromInner; use crate::{fmt, slice}; +// Specifying linkage/symbol name is solely to ensure a single instance between this crate and its unit tests #[cfg_attr(test, linkage = "available_externally")] #[unsafe(export_name = "_ZN16__rust_internals3std3sys3sgx4args4ARGSE")] -static ARGS: AtomicUsize = AtomicUsize::new(0); +static ARGS: Atomic<usize> = AtomicUsize::new(0); type ArgsStore = Vec<OsString>; #[cfg_attr(test, allow(dead_code))] diff --git a/library/std/src/sys/pal/uefi/args.rs b/library/std/src/sys/args/uefi.rs index 0c29caf2db6..02dada382ef 100644 --- a/library/std/src/sys/pal/uefi/args.rs +++ b/library/std/src/sys/args/uefi.rs @@ -1,14 +1,10 @@ use r_efi::protocols::loaded_image; -use super::helpers; +pub use super::common::Args; use crate::env::current_exe; use crate::ffi::OsString; use crate::iter::Iterator; -use crate::{fmt, vec}; - -pub struct Args { - parsed_args_list: vec::IntoIter<OsString>, -} +use crate::sys::pal::helpers; pub fn args() -> Args { let lazy_current_exe = || Vec::from([current_exe().map(Into::into).unwrap_or_default()]); @@ -22,51 +18,17 @@ pub fn args() -> Args { let lp_size = unsafe { (*protocol.as_ptr()).load_options_size } as usize; // Break if we are sure that it cannot be UTF-16 if lp_size < size_of::<u16>() || lp_size % size_of::<u16>() != 0 { - return Args { parsed_args_list: lazy_current_exe().into_iter() }; + return Args::new(lazy_current_exe()); } let lp_size = lp_size / size_of::<u16>(); let lp_cmd_line = unsafe { (*protocol.as_ptr()).load_options as *const u16 }; if !lp_cmd_line.is_aligned() { - return Args { parsed_args_list: lazy_current_exe().into_iter() }; + return Args::new(lazy_current_exe()); } let lp_cmd_line = unsafe { crate::slice::from_raw_parts(lp_cmd_line, lp_size) }; - Args { - parsed_args_list: parse_lp_cmd_line(lp_cmd_line) - .unwrap_or_else(lazy_current_exe) - .into_iter(), - } -} - -impl fmt::Debug for Args { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - self.parsed_args_list.as_slice().fmt(f) - } -} - -impl Iterator for Args { - type Item = OsString; - - fn next(&mut self) -> Option<OsString> { - self.parsed_args_list.next() - } - - fn size_hint(&self) -> (usize, Option<usize>) { - self.parsed_args_list.size_hint() - } -} - -impl ExactSizeIterator for Args { - fn len(&self) -> usize { - self.parsed_args_list.len() - } -} - -impl DoubleEndedIterator for Args { - fn next_back(&mut self) -> Option<OsString> { - self.parsed_args_list.next_back() - } + Args::new(parse_lp_cmd_line(lp_cmd_line).unwrap_or_else(lazy_current_exe)) } /// Implements the UEFI command-line argument parsing algorithm. diff --git a/library/std/src/sys/pal/unix/args.rs b/library/std/src/sys/args/unix.rs index 0bb7b64007a..0dfbd5f03eb 100644 --- a/library/std/src/sys/pal/unix/args.rs +++ b/library/std/src/sys/args/unix.rs @@ -5,13 +5,16 @@ #![allow(dead_code)] // runtime init functions not used during testing -use crate::ffi::{CStr, OsString}; +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; -use crate::{fmt, vec}; /// One-time global initialization. pub unsafe fn init(argc: isize, argv: *const *const u8) { - imp::init(argc, argv) + unsafe { imp::init(argc, argv) } } /// Returns the command line arguments @@ -55,42 +58,7 @@ pub fn args() -> Args { vec.push(OsStringExt::from_vec(cstr.to_bytes().to_vec())); } - Args { iter: vec.into_iter() } -} - -pub struct Args { - iter: vec::IntoIter<OsString>, -} - -impl !Send for Args {} -impl !Sync for Args {} - -impl fmt::Debug for Args { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - self.iter.as_slice().fmt(f) - } -} - -impl Iterator for Args { - type Item = OsString; - fn next(&mut self) -> Option<OsString> { - self.iter.next() - } - fn size_hint(&self) -> (usize, Option<usize>) { - self.iter.size_hint() - } -} - -impl ExactSizeIterator for Args { - fn len(&self) -> usize { - self.iter.len() - } -} - -impl DoubleEndedIterator for Args { - fn next_back(&mut self) -> Option<OsString> { - self.iter.next_back() - } + Args::new(vec) } #[cfg(any( @@ -105,6 +73,7 @@ impl DoubleEndedIterator for Args { target_os = "illumos", target_os = "emscripten", target_os = "haiku", + target_os = "hermit", target_os = "l4re", target_os = "fuchsia", target_os = "redox", @@ -119,7 +88,7 @@ impl DoubleEndedIterator for Args { mod imp { use crate::ffi::c_char; use crate::ptr; - use crate::sync::atomic::{AtomicIsize, AtomicPtr, Ordering}; + use crate::sync::atomic::{Atomic, AtomicIsize, AtomicPtr, Ordering}; // The system-provided argc and argv, which we store in static memory // here so that we can defer the work of parsing them until its actually @@ -127,12 +96,12 @@ mod imp { // // Note that we never mutate argv/argc, the argv array, or the argv // strings, which allows the code in this file to be very simple. - static ARGC: AtomicIsize = AtomicIsize::new(0); - static ARGV: AtomicPtr<*const u8> = AtomicPtr::new(ptr::null_mut()); + static ARGC: Atomic<isize> = AtomicIsize::new(0); + static ARGV: Atomic<*mut *const u8> = AtomicPtr::new(ptr::null_mut()); unsafe fn really_init(argc: isize, argv: *const *const u8) { // These don't need to be ordered with each other or other stores, - // because they only hold the unmodified system-provide argv/argc. + // because they only hold the unmodified system-provided argv/argc. ARGC.store(argc, Ordering::Relaxed); ARGV.store(argv as *mut _, Ordering::Relaxed); } @@ -141,7 +110,7 @@ mod imp { pub unsafe fn init(argc: isize, argv: *const *const u8) { // on GNU/Linux if we are main then we will init argv and argc twice, it "duplicates work" // BUT edge-cases are real: only using .init_array can break most emulators, dlopen, etc. - really_init(argc, argv); + unsafe { really_init(argc, argv) }; } /// glibc passes argc, argv, and envp to functions in .init_array, as a non-standard extension. @@ -159,9 +128,7 @@ mod imp { argv: *const *const u8, _envp: *const *const u8, ) { - unsafe { - really_init(argc as isize, argv); - } + unsafe { really_init(argc as isize, argv) }; } init_wrapper }; @@ -228,16 +195,3 @@ mod imp { (argc as isize, argv.cast()) } } - -#[cfg(any(target_os = "espidf", target_os = "vita"))] -mod imp { - use crate::ffi::c_char; - use crate::ptr; - - #[inline(always)] - pub unsafe fn init(_argc: isize, _argv: *const *const u8) {} - - pub fn argc_argv() -> (isize, *const *const c_char) { - (0, ptr::null()) - } -} diff --git a/library/std/src/sys/pal/unsupported/args.rs b/library/std/src/sys/args/unsupported.rs index a2d75a61976..a2d75a61976 100644 --- a/library/std/src/sys/pal/unsupported/args.rs +++ b/library/std/src/sys/args/unsupported.rs diff --git a/library/std/src/sys/args/wasi.rs b/library/std/src/sys/args/wasi.rs new file mode 100644 index 00000000000..72063a87dc9 --- /dev/null +++ b/library/std/src/sys/args/wasi.rs @@ -0,0 +1,26 @@ +#![forbid(unsafe_op_in_unsafe_fn)] + +pub use super::common::Args; +use crate::ffi::{CStr, OsStr, OsString}; +use crate::os::wasi::ffi::OsStrExt; + +/// Returns the command line arguments +pub fn args() -> Args { + Args::new(maybe_args().unwrap_or(Vec::new())) +} + +fn maybe_args() -> Option<Vec<OsString>> { + unsafe { + let (argc, buf_size) = wasi::args_sizes_get().ok()?; + let mut argv = Vec::with_capacity(argc); + let mut buf = Vec::with_capacity(buf_size); + wasi::args_get(argv.as_mut_ptr(), buf.as_mut_ptr()).ok()?; + argv.set_len(argc); + let mut ret = Vec::with_capacity(argc); + for ptr in argv { + let s = CStr::from_ptr(ptr.cast()); + ret.push(OsStr::from_bytes(s.to_bytes()).to_owned()); + } + Some(ret) + } +} diff --git a/library/std/src/sys/pal/windows/args.rs b/library/std/src/sys/args/windows.rs index d973743639a..81c44fabdcc 100644 --- a/library/std/src/sys/pal/windows/args.rs +++ b/library/std/src/sys/args/windows.rs @@ -6,17 +6,18 @@ #[cfg(test)] mod tests; -use super::ensure_no_nuls; -use super::os::current_exe; +pub use super::common::Args; use crate::ffi::{OsStr, OsString}; use crate::num::NonZero; use crate::os::windows::prelude::*; use crate::path::{Path, PathBuf}; +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::{c, to_u16s}; use crate::sys_common::AsInner; use crate::sys_common::wstr::WStrUnits; -use crate::{fmt, io, iter, vec}; +use crate::{io, iter, ptr}; pub fn args() -> Args { // SAFETY: `GetCommandLineW` returns a pointer to a null terminated UTF-16 @@ -27,7 +28,7 @@ pub fn args() -> Args { current_exe().map(PathBuf::into_os_string).unwrap_or_else(|_| OsString::new()) }); - Args { parsed_args_list: parsed_args_list.into_iter() } + Args::new(parsed_args_list) } } @@ -153,38 +154,6 @@ fn parse_lp_cmd_line<'a, F: Fn() -> OsString>( ret_val } -pub struct Args { - parsed_args_list: vec::IntoIter<OsString>, -} - -impl fmt::Debug for Args { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - self.parsed_args_list.as_slice().fmt(f) - } -} - -impl Iterator for Args { - type Item = OsString; - fn next(&mut self) -> Option<OsString> { - self.parsed_args_list.next() - } - fn size_hint(&self) -> (usize, Option<usize>) { - self.parsed_args_list.size_hint() - } -} - -impl DoubleEndedIterator for Args { - fn next_back(&mut self) -> Option<OsString> { - self.parsed_args_list.next_back() - } -} - -impl ExactSizeIterator for Args { - fn len(&self) -> usize { - self.parsed_args_list.len() - } -} - #[derive(Debug)] pub(crate) enum Arg { /// Add quotes (if needed) @@ -384,9 +353,6 @@ pub(crate) fn to_user_path(path: &Path) -> io::Result<Vec<u16>> { from_wide_to_user_path(to_u16s(path)?) } pub(crate) fn from_wide_to_user_path(mut path: Vec<u16>) -> io::Result<Vec<u16>> { - use super::fill_utf16_buf; - use crate::ptr; - // UTF-16 encoded code points, used in parsing and building UTF-16 paths. // All of these are in the ASCII range so they can be cast directly to `u16`. const SEP: u16 = b'\\' as _; diff --git a/library/std/src/sys/pal/windows/args/tests.rs b/library/std/src/sys/args/windows/tests.rs index 484a90ab056..484a90ab056 100644 --- a/library/std/src/sys/pal/windows/args/tests.rs +++ b/library/std/src/sys/args/windows/tests.rs diff --git a/library/std/src/sys/args/xous.rs b/library/std/src/sys/args/xous.rs new file mode 100644 index 00000000000..2010bad14d1 --- /dev/null +++ b/library/std/src/sys/args/xous.rs @@ -0,0 +1,20 @@ +pub use super::common::Args; +use crate::sys::pal::os::get_application_parameters; +use crate::sys::pal::os::params::ArgumentList; + +pub fn args() -> Args { + let Some(params) = get_application_parameters() else { + return Args::new(vec![]); + }; + + for param in params { + if let Ok(args) = ArgumentList::try_from(¶m) { + let mut parsed_args = vec![]; + for arg in args { + parsed_args.push(arg.into()); + } + return Args::new(parsed_args); + } + } + Args::new(vec![]) +} diff --git a/library/std/src/sys/pal/zkvm/args.rs b/library/std/src/sys/args/zkvm.rs index 47857f6c448..194ba7159d4 100644 --- a/library/std/src/sys/pal/zkvm/args.rs +++ b/library/std/src/sys/args/zkvm.rs @@ -1,7 +1,7 @@ -use super::{WORD_SIZE, abi}; use crate::ffi::OsString; use crate::fmt; use crate::sys::os_str; +use crate::sys::pal::{WORD_SIZE, abi}; use crate::sys_common::FromInner; pub struct Args { diff --git a/library/std/src/sys/cmath.rs b/library/std/src/sys/cmath.rs index c9969b4e376..668fd928534 100644 --- a/library/std/src/sys/cmath.rs +++ b/library/std/src/sys/cmath.rs @@ -3,70 +3,70 @@ // These symbols are all defined by `libm`, // or by `compiler-builtins` on unsupported platforms. unsafe extern "C" { - pub fn acos(n: f64) -> f64; - pub fn asin(n: f64) -> f64; - pub fn atan(n: f64) -> f64; - pub fn atan2(a: f64, b: f64) -> f64; - pub fn cbrt(n: f64) -> f64; - pub fn cbrtf(n: f32) -> f32; - pub fn cosh(n: f64) -> f64; - pub fn expm1(n: f64) -> f64; - pub fn expm1f(n: f32) -> f32; - pub fn fdim(a: f64, b: f64) -> f64; - pub fn fdimf(a: f32, b: f32) -> f32; + pub safe fn acos(n: f64) -> f64; + pub safe fn asin(n: f64) -> f64; + pub safe fn atan(n: f64) -> f64; + pub safe fn atan2(a: f64, b: f64) -> f64; + pub safe fn cbrt(n: f64) -> f64; + pub safe fn cbrtf(n: f32) -> f32; + pub safe fn cosh(n: f64) -> f64; + pub safe fn expm1(n: f64) -> f64; + pub safe fn expm1f(n: f32) -> f32; + pub safe fn fdim(a: f64, b: f64) -> f64; + pub safe fn fdimf(a: f32, b: f32) -> f32; #[cfg_attr(target_env = "msvc", link_name = "_hypot")] - pub fn hypot(x: f64, y: f64) -> f64; + pub safe fn hypot(x: f64, y: f64) -> f64; #[cfg_attr(target_env = "msvc", link_name = "_hypotf")] - pub fn hypotf(x: f32, y: f32) -> f32; - pub fn log1p(n: f64) -> f64; - pub fn log1pf(n: f32) -> f32; - pub fn sinh(n: f64) -> f64; - pub fn tan(n: f64) -> f64; - pub fn tanh(n: f64) -> f64; - pub fn tgamma(n: f64) -> f64; - pub fn tgammaf(n: f32) -> f32; - pub fn lgamma_r(n: f64, s: &mut i32) -> f64; + pub safe fn hypotf(x: f32, y: f32) -> f32; + pub safe fn log1p(n: f64) -> f64; + pub safe fn log1pf(n: f32) -> f32; + pub safe fn sinh(n: f64) -> f64; + pub safe fn tan(n: f64) -> f64; + pub safe fn tanh(n: f64) -> f64; + pub safe fn tgamma(n: f64) -> f64; + pub safe fn tgammaf(n: f32) -> f32; + pub safe fn lgamma_r(n: f64, s: &mut i32) -> f64; #[cfg(not(target_os = "aix"))] - pub fn lgammaf_r(n: f32, s: &mut i32) -> f32; - pub fn erf(n: f64) -> f64; - pub fn erff(n: f32) -> f32; - pub fn erfc(n: f64) -> f64; - pub fn erfcf(n: f32) -> f32; + pub safe fn lgammaf_r(n: f32, s: &mut i32) -> f32; + pub safe fn erf(n: f64) -> f64; + pub safe fn erff(n: f32) -> f32; + pub safe fn erfc(n: f64) -> f64; + pub safe fn erfcf(n: f32) -> f32; - pub fn acosf128(n: f128) -> f128; - pub fn asinf128(n: f128) -> f128; - pub fn atanf128(n: f128) -> f128; - pub fn atan2f128(a: f128, b: f128) -> f128; - pub fn cbrtf128(n: f128) -> f128; - pub fn coshf128(n: f128) -> f128; - pub fn expm1f128(n: f128) -> f128; - pub fn hypotf128(x: f128, y: f128) -> f128; - pub fn log1pf128(n: f128) -> f128; - pub fn sinhf128(n: f128) -> f128; - pub fn tanf128(n: f128) -> f128; - pub fn tanhf128(n: f128) -> f128; - pub fn tgammaf128(n: f128) -> f128; - pub fn lgammaf128_r(n: f128, s: &mut i32) -> f128; - pub fn erff128(n: f128) -> f128; - pub fn erfcf128(n: f128) -> f128; + pub safe fn acosf128(n: f128) -> f128; + pub safe fn asinf128(n: f128) -> f128; + pub safe fn atanf128(n: f128) -> f128; + pub safe fn atan2f128(a: f128, b: f128) -> f128; + pub safe fn cbrtf128(n: f128) -> f128; + pub safe fn coshf128(n: f128) -> f128; + pub safe fn expm1f128(n: f128) -> f128; + pub safe fn hypotf128(x: f128, y: f128) -> f128; + pub safe fn log1pf128(n: f128) -> f128; + pub safe fn sinhf128(n: f128) -> f128; + pub safe fn tanf128(n: f128) -> f128; + pub safe fn tanhf128(n: f128) -> f128; + pub safe fn tgammaf128(n: f128) -> f128; + pub safe fn lgammaf128_r(n: f128, s: &mut i32) -> f128; + pub safe fn erff128(n: f128) -> f128; + pub safe fn erfcf128(n: f128) -> f128; cfg_if::cfg_if! { if #[cfg(not(all(target_os = "windows", target_env = "msvc", target_arch = "x86")))] { - pub fn acosf(n: f32) -> f32; - pub fn asinf(n: f32) -> f32; - pub fn atan2f(a: f32, b: f32) -> f32; - pub fn atanf(n: f32) -> f32; - pub fn coshf(n: f32) -> f32; - pub fn sinhf(n: f32) -> f32; - pub fn tanf(n: f32) -> f32; - pub fn tanhf(n: f32) -> f32; + pub safe fn acosf(n: f32) -> f32; + pub safe fn asinf(n: f32) -> f32; + pub safe fn atan2f(a: f32, b: f32) -> f32; + pub safe fn atanf(n: f32) -> f32; + pub safe fn coshf(n: f32) -> f32; + pub safe fn sinhf(n: f32) -> f32; + pub safe fn tanf(n: f32) -> f32; + pub safe fn tanhf(n: f32) -> f32; }} } // On AIX, we don't have lgammaf_r only the f64 version, so we can // use the f64 version lgamma_r #[cfg(target_os = "aix")] -pub unsafe fn lgammaf_r(n: f32, s: &mut i32) -> f32 { +pub fn lgammaf_r(n: f32, s: &mut i32) -> f32 { lgamma_r(n.into(), s) as f32 } @@ -76,42 +76,42 @@ pub unsafe fn lgammaf_r(n: f32, s: &mut i32) -> f32 { cfg_if::cfg_if! { if #[cfg(all(target_os = "windows", target_env = "msvc", target_arch = "x86"))] { #[inline] - pub unsafe fn acosf(n: f32) -> f32 { + pub fn acosf(n: f32) -> f32 { f64::acos(n as f64) as f32 } #[inline] - pub unsafe fn asinf(n: f32) -> f32 { + pub fn asinf(n: f32) -> f32 { f64::asin(n as f64) as f32 } #[inline] - pub unsafe fn atan2f(n: f32, b: f32) -> f32 { + pub fn atan2f(n: f32, b: f32) -> f32 { f64::atan2(n as f64, b as f64) as f32 } #[inline] - pub unsafe fn atanf(n: f32) -> f32 { + pub fn atanf(n: f32) -> f32 { f64::atan(n as f64) as f32 } #[inline] - pub unsafe fn coshf(n: f32) -> f32 { + pub fn coshf(n: f32) -> f32 { f64::cosh(n as f64) as f32 } #[inline] - pub unsafe fn sinhf(n: f32) -> f32 { + pub fn sinhf(n: f32) -> f32 { f64::sinh(n as f64) as f32 } #[inline] - pub unsafe fn tanf(n: f32) -> f32 { + pub fn tanf(n: f32) -> f32 { f64::tan(n as f64) as f32 } #[inline] - pub unsafe fn tanhf(n: f32) -> f32 { + pub fn tanhf(n: f32) -> f32 { f64::tanh(n as f64) as f32 } }} diff --git a/library/std/src/sys/env/common.rs b/library/std/src/sys/env/common.rs new file mode 100644 index 00000000000..f161ff073f3 --- /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 <OsStr as Debug>::fmt matches <str as Debug>::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<usize>) { + self.iter.size_hint() + } +} diff --git a/library/std/src/sys/env/hermit.rs b/library/std/src/sys/env/hermit.rs new file mode 100644 index 00000000000..445ecdeb6a3 --- /dev/null +++ b/library/std/src/sys/env/hermit.rs @@ -0,0 +1,72 @@ +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; + +static ENV: Mutex<Option<HashMap<OsString, OsString>>> = Mutex::new(None); + +pub fn init(env: *const *const c_char) { + let mut guard = ENV.lock().unwrap(); + let map = guard.insert(HashMap::new()); + + if env.is_null() { + return; + } + + unsafe { + let mut environ = env; + while !(*environ).is_null() { + if let Some((key, value)) = parse(CStr::from_ptr(*environ).to_bytes()) { + map.insert(key, value); + } + environ = environ.add(1); + } + } + + fn parse(input: &[u8]) -> Option<(OsString, OsString)> { + // Strategy (copied from glibc): Variable name and value are separated + // by an ASCII equals sign '='. Since a variable name must not be + // empty, allow variable names starting with an equals sign. Skip all + // malformed lines. + if input.is_empty() { + return None; + } + let pos = memchr::memchr(b'=', &input[1..]).map(|p| p + 1); + pos.map(|p| { + ( + OsStringExt::from_vec(input[..p].to_vec()), + OsStringExt::from_vec(input[p + 1..].to_vec()), + ) + }) + } +} + +/// 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(); + + Env::new(result) +} + +pub fn getenv(k: &OsStr) -> Option<OsString> { + ENV.lock().unwrap().as_ref().unwrap().get(k).cloned() +} + +pub unsafe fn setenv(k: &OsStr, v: &OsStr) -> io::Result<()> { + let (k, v) = (k.to_owned(), v.to_owned()); + ENV.lock().unwrap().as_mut().unwrap().insert(k, v); + Ok(()) +} + +pub unsafe fn unsetenv(k: &OsStr) -> io::Result<()> { + ENV.lock().unwrap().as_mut().unwrap().remove(k); + Ok(()) +} diff --git a/library/std/src/sys/env/mod.rs b/library/std/src/sys/env/mod.rs new file mode 100644 index 00000000000..d81ff875c83 --- /dev/null +++ b/library/std/src/sys/env/mod.rs @@ -0,0 +1,48 @@ +//! Platform-dependent environment variables abstraction. + +#![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; + pub use unix::*; + } else if #[cfg(target_family = "windows")] { + mod windows; + pub use windows::*; + } else if #[cfg(target_os = "hermit")] { + mod hermit; + pub use hermit::*; + } else if #[cfg(all(target_vendor = "fortanix", target_env = "sgx"))] { + mod sgx; + pub use sgx::*; + } else if #[cfg(target_os = "solid_asp3")] { + mod solid; + pub use solid::*; + } else if #[cfg(target_os = "uefi")] { + mod uefi; + pub use uefi::*; + } else if #[cfg(target_os = "wasi")] { + mod wasi; + pub use wasi::*; + } else if #[cfg(target_os = "xous")] { + mod xous; + pub use xous::*; + } else if #[cfg(target_os = "zkvm")] { + mod zkvm; + pub use zkvm::*; + } else { + mod unsupported; + pub use unsupported::*; + } +} diff --git a/library/std/src/sys/env/sgx.rs b/library/std/src/sys/env/sgx.rs new file mode 100644 index 00000000000..09090ec7cf0 --- /dev/null +++ b/library/std/src/sys/env/sgx.rs @@ -0,0 +1,55 @@ +#![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::{Atomic, AtomicUsize, Ordering}; +use crate::sync::{Mutex, Once}; + +// Specifying linkage/symbol name is solely to ensure a single instance between this crate and its unit tests +#[cfg_attr(test, linkage = "available_externally")] +#[unsafe(export_name = "_ZN16__rust_internals3std3sys3pal3sgx2os3ENVE")] +static ENV: Atomic<usize> = AtomicUsize::new(0); +// Specifying linkage/symbol name is solely to ensure a single instance between this crate and its unit tests +#[cfg_attr(test, linkage = "available_externally")] +#[unsafe(export_name = "_ZN16__rust_internals3std3sys3pal3sgx2os8ENV_INITE")] +static ENV_INIT: Once = Once::new(); +type EnvStore = Mutex<HashMap<OsString, OsString>>; + +fn get_env_store() -> Option<&'static EnvStore> { + unsafe { (ENV.load(Ordering::Relaxed) as *const EnvStore).as_ref() } +} + +fn create_env_store() -> &'static EnvStore { + ENV_INIT.call_once(|| { + ENV.store(Box::into_raw(Box::new(EnvStore::default())) as _, Ordering::Relaxed) + }); + unsafe { &*(ENV.load(Ordering::Relaxed) as *const EnvStore) } +} + +pub fn env() -> Env { + let clone_to_vec = |map: &HashMap<OsString, OsString>| -> Vec<_> { + map.iter().map(|(k, v)| (k.clone(), v.clone())).collect() + }; + + 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<OsString> { + get_env_store().and_then(|s| s.lock().unwrap().get(k).cloned()) +} + +pub unsafe fn setenv(k: &OsStr, v: &OsStr) -> io::Result<()> { + let (k, v) = (k.to_owned(), v.to_owned()); + create_env_store().lock().unwrap().insert(k, v); + Ok(()) +} + +pub unsafe fn unsetenv(k: &OsStr) -> io::Result<()> { + if let Some(env) = get_env_store() { + env.lock().unwrap().remove(k); + } + Ok(()) +} diff --git a/library/std/src/sys/env/solid.rs b/library/std/src/sys/env/solid.rs new file mode 100644 index 00000000000..ea77fc3c119 --- /dev/null +++ b/library/std/src/sys/env/solid.rs @@ -0,0 +1,96 @@ +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; + +static ENV_LOCK: RwLock<()> = RwLock::new(()); + +pub fn env_read_lock() -> impl Drop { + ENV_LOCK.read().unwrap_or_else(PoisonError::into_inner) +} + +/// Returns a vector of (variable, value) byte-vector pairs for all the +/// environment variables of the current process. +pub fn env() -> Env { + unsafe extern "C" { + static mut environ: *const *const c_char; + } + + unsafe { + let _guard = env_read_lock(); + let mut result = Vec::new(); + if !environ.is_null() { + while !(*environ).is_null() { + if let Some(key_value) = parse(CStr::from_ptr(*environ).to_bytes()) { + result.push(key_value); + } + environ = environ.add(1); + } + } + return Env::new(result); + } + + fn parse(input: &[u8]) -> Option<(OsString, OsString)> { + // Strategy (copied from glibc): Variable name and value are separated + // by an ASCII equals sign '='. Since a variable name must not be + // empty, allow variable names starting with an equals sign. Skip all + // malformed lines. + if input.is_empty() { + return None; + } + let pos = memchr::memchr(b'=', &input[1..]).map(|p| p + 1); + pos.map(|p| { + ( + OsStringExt::from_vec(input[..p].to_vec()), + OsStringExt::from_vec(input[p + 1..].to_vec()), + ) + }) + } +} + +pub fn getenv(k: &OsStr) -> Option<OsString> { + // environment variables with a nul byte can't be set, so their value is + // always None as well + run_with_cstr(k.as_bytes(), &|k| { + let _guard = env_read_lock(); + let v = unsafe { libc::getenv(k.as_ptr()) } as *const libc::c_char; + + if v.is_null() { + Ok(None) + } else { + // SAFETY: `v` cannot be mutated while executing this line since we've a read lock + let bytes = unsafe { CStr::from_ptr(v) }.to_bytes().to_vec(); + + Ok(Some(OsStringExt::from_vec(bytes))) + } + }) + .ok() + .flatten() +} + +pub unsafe fn setenv(k: &OsStr, v: &OsStr) -> io::Result<()> { + run_with_cstr(k.as_bytes(), &|k| { + run_with_cstr(v.as_bytes(), &|v| { + let _guard = ENV_LOCK.write(); + cvt_env(unsafe { libc::setenv(k.as_ptr(), v.as_ptr(), 1) }).map(drop) + }) + }) +} + +pub unsafe fn unsetenv(n: &OsStr) -> io::Result<()> { + run_with_cstr(n.as_bytes(), &|nbuf| { + let _guard = ENV_LOCK.write(); + cvt_env(unsafe { libc::unsetenv(nbuf.as_ptr()) }).map(drop) + }) +} + +/// In kmclib, `setenv` and `unsetenv` don't always set `errno`, so this +/// function just returns a generic error. +fn cvt_env(t: c_int) -> io::Result<c_int> { + if t == -1 { Err(io::const_error!(io::ErrorKind::Uncategorized, "failure")) } else { Ok(t) } +} diff --git a/library/std/src/sys/env/uefi.rs b/library/std/src/sys/env/uefi.rs new file mode 100644 index 00000000000..1561df41cac --- /dev/null +++ b/library/std/src/sys/env/uefi.rs @@ -0,0 +1,102 @@ +pub use super::common::Env; +use crate::ffi::{OsStr, OsString}; +use crate::io; + +pub fn env() -> Env { + let env = uefi_env::get_all().expect("not supported on this platform"); + Env::new(env) +} + +pub fn getenv(key: &OsStr) -> Option<OsString> { + uefi_env::get(key) +} + +pub unsafe fn setenv(key: &OsStr, val: &OsStr) -> io::Result<()> { + uefi_env::set(key, val) +} + +pub unsafe fn unsetenv(key: &OsStr) -> io::Result<()> { + uefi_env::unset(key) +} + +mod uefi_env { + use crate::ffi::{OsStr, OsString}; + use crate::io; + use crate::os::uefi::ffi::OsStringExt; + use crate::ptr::NonNull; + use crate::sys::{helpers, unsupported_err}; + + pub(crate) fn get(key: &OsStr) -> Option<OsString> { + let shell = helpers::open_shell()?; + let mut key_ptr = helpers::os_string_to_raw(key)?; + unsafe { get_raw(shell, key_ptr.as_mut_ptr()) } + } + + pub(crate) fn set(key: &OsStr, val: &OsStr) -> io::Result<()> { + let mut key_ptr = helpers::os_string_to_raw(key) + .ok_or(io::const_error!(io::ErrorKind::InvalidInput, "invalid key"))?; + let mut val_ptr = helpers::os_string_to_raw(val) + .ok_or(io::const_error!(io::ErrorKind::InvalidInput, "invalid value"))?; + unsafe { set_raw(key_ptr.as_mut_ptr(), val_ptr.as_mut_ptr()) } + } + + pub(crate) fn unset(key: &OsStr) -> io::Result<()> { + let mut key_ptr = helpers::os_string_to_raw(key) + .ok_or(io::const_error!(io::ErrorKind::InvalidInput, "invalid key"))?; + unsafe { set_raw(key_ptr.as_mut_ptr(), crate::ptr::null_mut()) } + } + + pub(crate) fn get_all() -> io::Result<Vec<(OsString, OsString)>> { + let shell = helpers::open_shell().ok_or(unsupported_err())?; + + let mut vars = Vec::new(); + let val = unsafe { ((*shell.as_ptr()).get_env)(crate::ptr::null_mut()) }; + + if val.is_null() { + return Ok(vars); + } + + let mut start = 0; + + // UEFI Shell returns all keys separated by NULL. + // End of string is denoted by two NULLs + for i in 0.. { + if unsafe { *val.add(i) } == 0 { + // Two NULL signal end of string + if i == start { + break; + } + + let key = OsString::from_wide(unsafe { + crate::slice::from_raw_parts(val.add(start), i - start) + }); + // SAFETY: val.add(start) is always NULL terminated + let val = unsafe { get_raw(shell, val.add(start)) } + .ok_or(io::const_error!(io::ErrorKind::InvalidInput, "invalid value"))?; + + vars.push((key, val)); + start = i + 1; + } + } + + Ok(vars) + } + + unsafe fn get_raw( + shell: NonNull<r_efi::efi::protocols::shell::Protocol>, + key_ptr: *mut r_efi::efi::Char16, + ) -> Option<OsString> { + let val = unsafe { ((*shell.as_ptr()).get_env)(key_ptr) }; + helpers::os_string_from_raw(val) + } + + unsafe fn set_raw( + key_ptr: *mut r_efi::efi::Char16, + val_ptr: *mut r_efi::efi::Char16, + ) -> io::Result<()> { + let shell = helpers::open_shell().ok_or(unsupported_err())?; + let r = + unsafe { ((*shell.as_ptr()).set_env)(key_ptr, val_ptr, r_efi::efi::Boolean::FALSE) }; + if r.is_error() { Err(io::Error::from_raw_os_error(r.as_usize())) } else { Ok(()) } + } +} diff --git a/library/std/src/sys/env/unix.rs b/library/std/src/sys/env/unix.rs new file mode 100644 index 00000000000..78c7af65f9e --- /dev/null +++ b/library/std/src/sys/env/unix.rs @@ -0,0 +1,126 @@ +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 `_NSGetEnviron` on Apple platforms. +// +// `_NSGetEnviron` is the documented alternative (see `man environ`), and has +// been available since the first versions of both macOS and iOS. +// +// Nowadays, specifically since macOS 10.8, `environ` has been exposed through +// `libdyld.dylib`, which is linked via. `libSystem.dylib`: +// <https://github.com/apple-oss-distributions/dyld/blob/dyld-1160.6/libdyld/libdyldGlue.cpp#L913> +// +// So in the end, it likely doesn't really matter which option we use, but the +// performance cost of using `_NSGetEnviron` is extremely miniscule, and it +// might be ever so slightly more supported, so let's just use that. +// +// NOTE: The header where this is defined (`crt_externs.h`) was added to the +// iOS 13.0 SDK, which has been the source of a great deal of confusion in the +// past about the availability of this API. +// +// NOTE(madsmtm): Neither this nor using `environ` has been verified to not +// cause App Store rejections; if this is found to be the case, an alternative +// implementation of this is possible using `[NSProcessInfo environment]` +// - which internally uses `_NSGetEnviron` and a system-wide lock on the +// environment variables to protect against `setenv`, so using that might be +// desirable anyhow? Though it also means that we have to link to Foundation. +#[cfg(target_vendor = "apple")] +pub unsafe fn environ() -> *mut *const *const c_char { + unsafe { libc::_NSGetEnviron() as *mut *const *const c_char } +} + +// Use the `environ` static which is part of POSIX. +#[cfg(not(target_vendor = "apple"))] +pub unsafe fn environ() -> *mut *const *const c_char { + unsafe extern "C" { + static mut environ: *const *const c_char; + } + &raw mut environ +} + +static ENV_LOCK: RwLock<()> = RwLock::new(()); + +pub fn env_read_lock() -> impl Drop { + ENV_LOCK.read().unwrap_or_else(PoisonError::into_inner) +} + +/// Returns a vector of (variable, value) byte-vector pairs for all the +/// environment variables of the current process. +pub fn env() -> Env { + unsafe { + let _guard = env_read_lock(); + let mut environ = *environ(); + let mut result = Vec::new(); + if !environ.is_null() { + while !(*environ).is_null() { + if let Some(key_value) = parse(CStr::from_ptr(*environ).to_bytes()) { + result.push(key_value); + } + environ = environ.add(1); + } + } + return Env::new(result); + } + + fn parse(input: &[u8]) -> Option<(OsString, OsString)> { + // Strategy (copied from glibc): Variable name and value are separated + // by an ASCII equals sign '='. Since a variable name must not be + // empty, allow variable names starting with an equals sign. Skip all + // malformed lines. + if input.is_empty() { + return None; + } + let pos = memchr::memchr(b'=', &input[1..]).map(|p| p + 1); + pos.map(|p| { + ( + OsStringExt::from_vec(input[..p].to_vec()), + OsStringExt::from_vec(input[p + 1..].to_vec()), + ) + }) + } +} + +pub fn getenv(k: &OsStr) -> Option<OsString> { + // environment variables with a nul byte can't be set, so their value is + // always None as well + run_with_cstr(k.as_bytes(), &|k| { + let _guard = env_read_lock(); + let v = unsafe { libc::getenv(k.as_ptr()) } as *const libc::c_char; + + if v.is_null() { + Ok(None) + } else { + // SAFETY: `v` cannot be mutated while executing this line since we've a read lock + let bytes = unsafe { CStr::from_ptr(v) }.to_bytes().to_vec(); + + Ok(Some(OsStringExt::from_vec(bytes))) + } + }) + .ok() + .flatten() +} + +pub unsafe fn setenv(k: &OsStr, v: &OsStr) -> io::Result<()> { + run_with_cstr(k.as_bytes(), &|k| { + run_with_cstr(v.as_bytes(), &|v| { + let _guard = ENV_LOCK.write(); + cvt(unsafe { libc::setenv(k.as_ptr(), v.as_ptr(), 1) }).map(drop) + }) + }) +} + +pub unsafe fn unsetenv(n: &OsStr) -> io::Result<()> { + run_with_cstr(n.as_bytes(), &|nbuf| { + let _guard = ENV_LOCK.write(); + cvt(unsafe { libc::unsetenv(nbuf.as_ptr()) }).map(drop) + }) +} diff --git a/library/std/src/sys/env/unsupported.rs b/library/std/src/sys/env/unsupported.rs new file mode 100644 index 00000000000..98905e64827 --- /dev/null +++ b/library/std/src/sys/env/unsupported.rs @@ -0,0 +1,40 @@ +use crate::ffi::{OsStr, OsString}; +use crate::{fmt, io}; + +pub struct Env(!); + +impl Env { + // FIXME(https://github.com/rust-lang/rust/issues/114583): Remove this when <OsStr as Debug>::fmt matches <str as Debug>::fmt. + pub fn str_debug(&self) -> impl fmt::Debug + '_ { + self.0 + } +} + +impl fmt::Debug for Env { + fn fmt(&self, _: &mut fmt::Formatter<'_>) -> fmt::Result { + self.0 + } +} + +impl Iterator for Env { + type Item = (OsString, OsString); + fn next(&mut self) -> Option<(OsString, OsString)> { + self.0 + } +} + +pub fn env() -> Env { + panic!("not supported on this platform") +} + +pub fn getenv(_: &OsStr) -> Option<OsString> { + None +} + +pub unsafe fn setenv(_: &OsStr, _: &OsStr) -> io::Result<()> { + Err(io::const_error!(io::ErrorKind::Unsupported, "cannot set env vars on this platform")) +} + +pub unsafe fn unsetenv(_: &OsStr) -> io::Result<()> { + Err(io::const_error!(io::ErrorKind::Unsupported, "cannot unset env vars on this platform")) +} diff --git a/library/std/src/sys/env/wasi.rs b/library/std/src/sys/env/wasi.rs new file mode 100644 index 00000000000..3719f9db51e --- /dev/null +++ b/library/std/src/sys/env/wasi.rs @@ -0,0 +1,102 @@ +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}; + +cfg_if::cfg_if! { + if #[cfg(target_feature = "atomics")] { + // Access to the environment must be protected by a lock in multi-threaded scenarios. + use crate::sync::{PoisonError, RwLock}; + static ENV_LOCK: RwLock<()> = RwLock::new(()); + pub fn env_read_lock() -> impl Drop { + ENV_LOCK.read().unwrap_or_else(PoisonError::into_inner) + } + pub fn env_write_lock() -> impl Drop { + ENV_LOCK.write().unwrap_or_else(PoisonError::into_inner) + } + } else { + // No need for a lock if we are single-threaded. + pub fn env_read_lock() -> impl Drop { + Box::new(()) + } + pub fn env_write_lock() -> impl Drop { + Box::new(()) + } + } +} + +pub fn env() -> Env { + unsafe { + let _guard = env_read_lock(); + + // Use `__wasilibc_get_environ` instead of `environ` here so that we + // don't require wasi-libc to eagerly initialize the environment + // variables. + let mut environ = libc::__wasilibc_get_environ(); + + let mut result = Vec::new(); + if !environ.is_null() { + while !(*environ).is_null() { + if let Some(key_value) = parse(CStr::from_ptr(*environ).to_bytes()) { + result.push(key_value); + } + environ = environ.add(1); + } + } + return Env::new(result); + } + + // See src/libstd/sys/pal/unix/os.rs, same as that + fn parse(input: &[u8]) -> Option<(OsString, OsString)> { + if input.is_empty() { + return None; + } + let pos = memchr::memchr(b'=', &input[1..]).map(|p| p + 1); + pos.map(|p| { + ( + OsStringExt::from_vec(input[..p].to_vec()), + OsStringExt::from_vec(input[p + 1..].to_vec()), + ) + }) + } +} + +pub fn getenv(k: &OsStr) -> Option<OsString> { + // environment variables with a nul byte can't be set, so their value is + // always None as well + run_with_cstr(k.as_bytes(), &|k| { + let _guard = env_read_lock(); + let v = unsafe { libc::getenv(k.as_ptr()) } as *const libc::c_char; + + if v.is_null() { + Ok(None) + } else { + // SAFETY: `v` cannot be mutated while executing this line since we've a read lock + let bytes = unsafe { CStr::from_ptr(v) }.to_bytes().to_vec(); + + Ok(Some(OsStringExt::from_vec(bytes))) + } + }) + .ok() + .flatten() +} + +pub unsafe fn setenv(k: &OsStr, v: &OsStr) -> io::Result<()> { + run_with_cstr(k.as_bytes(), &|k| { + run_with_cstr(v.as_bytes(), &|v| unsafe { + let _guard = env_write_lock(); + cvt(libc::setenv(k.as_ptr(), v.as_ptr(), 1)).map(drop) + }) + }) +} + +pub unsafe fn unsetenv(n: &OsStr) -> io::Result<()> { + run_with_cstr(n.as_bytes(), &|nbuf| unsafe { + let _guard = env_write_lock(); + cvt(libc::unsetenv(nbuf.as_ptr())).map(drop) + }) +} diff --git a/library/std/src/sys/env/windows.rs b/library/std/src/sys/env/windows.rs new file mode 100644 index 00000000000..3c4d4a84cfd --- /dev/null +++ b/library/std/src/sys/env/windows.rs @@ -0,0 +1,133 @@ +use crate::ffi::{OsStr, OsString}; +use crate::os::windows::prelude::*; +use crate::sys::pal::{c, cvt, fill_utf16_buf, to_u16s}; +use crate::{fmt, io, ptr, slice}; + +pub struct Env { + base: *mut c::WCHAR, + iter: EnvIterator, +} + +// FIXME(https://github.com/rust-lang/rust/issues/114583): Remove this when <OsStr as Debug>::fmt matches <str as Debug>::fmt. +pub struct EnvStrDebug<'a> { + iter: &'a EnvIterator, +} + +impl fmt::Debug for EnvStrDebug<'_> { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + let Self { iter } = self; + let iter: EnvIterator = (*iter).clone(); + let mut list = f.debug_list(); + for (a, b) in iter { + list.entry(&(a.to_str().unwrap(), b.to_str().unwrap())); + } + list.finish() + } +} + +impl Env { + pub fn str_debug(&self) -> impl fmt::Debug + '_ { + let Self { base: _, iter } = self; + EnvStrDebug { iter } + } +} + +impl fmt::Debug for Env { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + let Self { base: _, iter } = self; + f.debug_list().entries(iter.clone()).finish() + } +} + +impl Iterator for Env { + type Item = (OsString, OsString); + + fn next(&mut self) -> Option<(OsString, OsString)> { + let Self { base: _, iter } = self; + iter.next() + } +} + +#[derive(Clone)] +struct EnvIterator(*mut c::WCHAR); + +impl Iterator for EnvIterator { + type Item = (OsString, OsString); + + fn next(&mut self) -> Option<(OsString, OsString)> { + let Self(cur) = self; + loop { + unsafe { + if **cur == 0 { + return None; + } + let p = *cur as *const u16; + let mut len = 0; + while *p.add(len) != 0 { + len += 1; + } + let s = slice::from_raw_parts(p, len); + *cur = cur.add(len + 1); + + // Windows allows environment variables to start with an equals + // symbol (in any other position, this is the separator between + // variable name and value). Since`s` has at least length 1 at + // this point (because the empty string terminates the array of + // environment variables), we can safely slice. + let pos = match s[1..].iter().position(|&u| u == b'=' as u16).map(|p| p + 1) { + Some(p) => p, + None => continue, + }; + return Some(( + OsStringExt::from_wide(&s[..pos]), + OsStringExt::from_wide(&s[pos + 1..]), + )); + } + } + } +} + +impl Drop for Env { + fn drop(&mut self) { + unsafe { + c::FreeEnvironmentStringsW(self.base); + } + } +} + +pub fn env() -> Env { + unsafe { + let ch = c::GetEnvironmentStringsW(); + if ch.is_null() { + panic!("failure getting env string from OS: {}", io::Error::last_os_error()); + } + Env { base: ch, iter: EnvIterator(ch) } + } +} + +pub fn getenv(k: &OsStr) -> Option<OsString> { + let k = to_u16s(k).ok()?; + fill_utf16_buf( + |buf, sz| unsafe { c::GetEnvironmentVariableW(k.as_ptr(), buf, sz) }, + OsStringExt::from_wide, + ) + .ok() +} + +pub unsafe fn setenv(k: &OsStr, v: &OsStr) -> io::Result<()> { + // SAFETY: We ensure that k and v are null-terminated wide strings. + unsafe { + let k = to_u16s(k)?; + let v = to_u16s(v)?; + + cvt(c::SetEnvironmentVariableW(k.as_ptr(), v.as_ptr())).map(drop) + } +} + +pub unsafe fn unsetenv(n: &OsStr) -> io::Result<()> { + // SAFETY: We ensure that v is a null-terminated wide strings. + unsafe { + let v = to_u16s(n)?; + cvt(c::SetEnvironmentVariableW(v.as_ptr(), ptr::null())).map(drop) + } +} diff --git a/library/std/src/sys/env/xous.rs b/library/std/src/sys/env/xous.rs new file mode 100644 index 00000000000..8f65f30d35f --- /dev/null +++ b/library/std/src/sys/env/xous.rs @@ -0,0 +1,54 @@ +pub use super::common::Env; +use crate::collections::HashMap; +use crate::ffi::{OsStr, OsString}; +use crate::io; +use crate::sync::atomic::{Atomic, AtomicUsize, Ordering}; +use crate::sync::{Mutex, Once}; +use crate::sys::pal::os::{get_application_parameters, params}; + +static ENV: Atomic<usize> = AtomicUsize::new(0); +static ENV_INIT: Once = Once::new(); +type EnvStore = Mutex<HashMap<OsString, OsString>>; + +fn get_env_store() -> &'static EnvStore { + ENV_INIT.call_once(|| { + let env_store = EnvStore::default(); + if let Some(params) = get_application_parameters() { + for param in params { + if let Ok(envs) = params::EnvironmentBlock::try_from(¶m) { + let mut env_store = env_store.lock().unwrap(); + for env in envs { + env_store.insert(env.key.into(), env.value.into()); + } + break; + } + } + } + ENV.store(Box::into_raw(Box::new(env_store)) as _, Ordering::Relaxed) + }); + unsafe { &*core::ptr::with_exposed_provenance::<EnvStore>(ENV.load(Ordering::Relaxed)) } +} + +pub fn env() -> Env { + let clone_to_vec = |map: &HashMap<OsString, OsString>| -> Vec<_> { + map.iter().map(|(k, v)| (k.clone(), v.clone())).collect() + }; + + let env = clone_to_vec(&*get_env_store().lock().unwrap()); + Env::new(env) +} + +pub fn getenv(k: &OsStr) -> Option<OsString> { + get_env_store().lock().unwrap().get(k).cloned() +} + +pub unsafe fn setenv(k: &OsStr, v: &OsStr) -> io::Result<()> { + let (k, v) = (k.to_owned(), v.to_owned()); + get_env_store().lock().unwrap().insert(k, v); + Ok(()) +} + +pub unsafe fn unsetenv(k: &OsStr) -> io::Result<()> { + get_env_store().lock().unwrap().remove(k); + Ok(()) +} diff --git a/library/std/src/sys/env/zkvm.rs b/library/std/src/sys/env/zkvm.rs new file mode 100644 index 00000000000..2eb7005ba12 --- /dev/null +++ b/library/std/src/sys/env/zkvm.rs @@ -0,0 +1,32 @@ +#[expect(dead_code)] +#[path = "unsupported.rs"] +mod unsupported_env; +pub use unsupported_env::{Env, env, setenv, unsetenv}; + +use crate::ffi::{OsStr, OsString}; +use crate::sys::os_str; +use crate::sys::pal::{WORD_SIZE, abi}; +use crate::sys_common::FromInner; + +pub fn getenv(varname: &OsStr) -> Option<OsString> { + let varname = varname.as_encoded_bytes(); + let nbytes = + unsafe { abi::sys_getenv(crate::ptr::null_mut(), 0, varname.as_ptr(), varname.len()) }; + if nbytes == usize::MAX { + return None; + } + + let nwords = (nbytes + WORD_SIZE - 1) / WORD_SIZE; + let words = unsafe { abi::sys_alloc_words(nwords) }; + + let nbytes2 = unsafe { abi::sys_getenv(words, nwords, varname.as_ptr(), varname.len()) }; + debug_assert_eq!(nbytes, nbytes2); + + // Convert to OsString. + // + // FIXME: We can probably get rid of the extra copy here if we + // reimplement "os_str" instead of just using the generic unix + // "os_str". + let u8s: &[u8] = unsafe { crate::slice::from_raw_parts(words.cast() as *const u8, nbytes) }; + Some(OsString::from_inner(os_str::Buf { inner: u8s.to_vec() })) +} diff --git a/library/std/src/sys/pal/unix/env.rs b/library/std/src/sys/env_consts.rs index c6609298f4b..9683fd47cf9 100644 --- a/library/std/src/sys/pal/unix/env.rs +++ b/library/std/src/sys/env_consts.rs @@ -1,73 +1,79 @@ -#[cfg(target_os = "linux")] -pub mod os { - pub const FAMILY: &str = "unix"; - pub const OS: &str = "linux"; - pub const DLL_PREFIX: &str = "lib"; - pub const DLL_SUFFIX: &str = ".so"; - pub const DLL_EXTENSION: &str = "so"; - pub const EXE_SUFFIX: &str = ""; - pub const EXE_EXTENSION: &str = ""; +//! Constants associated with each target. + +// Replaces the #[else] gate with #[cfg(not(any(…)))] of all the other gates. +// This ensures that they must be mutually exclusive and do not have precedence +// like cfg_if!. +macro cfg_unordered( + $(#[cfg($cfg:meta)] $os:item)* + #[else] $fallback:item +) { + $(#[cfg($cfg)] $os)* + #[cfg(not(any($($cfg),*)))] $fallback } -#[cfg(target_os = "macos")] +// Keep entries sorted alphabetically and mutually exclusive. + +cfg_unordered! { + +#[cfg(target_os = "aix")] pub mod os { pub const FAMILY: &str = "unix"; - pub const OS: &str = "macos"; + pub const OS: &str = "aix"; pub const DLL_PREFIX: &str = "lib"; - pub const DLL_SUFFIX: &str = ".dylib"; - pub const DLL_EXTENSION: &str = "dylib"; + pub const DLL_SUFFIX: &str = ".a"; + pub const DLL_EXTENSION: &str = "a"; pub const EXE_SUFFIX: &str = ""; pub const EXE_EXTENSION: &str = ""; } -#[cfg(target_os = "ios")] +#[cfg(target_os = "android")] pub mod os { pub const FAMILY: &str = "unix"; - pub const OS: &str = "ios"; + pub const OS: &str = "android"; pub const DLL_PREFIX: &str = "lib"; - pub const DLL_SUFFIX: &str = ".dylib"; - pub const DLL_EXTENSION: &str = "dylib"; + pub const DLL_SUFFIX: &str = ".so"; + pub const DLL_EXTENSION: &str = "so"; pub const EXE_SUFFIX: &str = ""; pub const EXE_EXTENSION: &str = ""; } -#[cfg(target_os = "tvos")] +#[cfg(target_os = "cygwin")] pub mod os { pub const FAMILY: &str = "unix"; - pub const OS: &str = "tvos"; - pub const DLL_PREFIX: &str = "lib"; - pub const DLL_SUFFIX: &str = ".dylib"; - pub const DLL_EXTENSION: &str = "dylib"; - pub const EXE_SUFFIX: &str = ""; - pub const EXE_EXTENSION: &str = ""; + pub const OS: &str = "cygwin"; + pub const DLL_PREFIX: &str = ""; + pub const DLL_SUFFIX: &str = ".dll"; + pub const DLL_EXTENSION: &str = "dll"; + pub const EXE_SUFFIX: &str = ".exe"; + pub const EXE_EXTENSION: &str = "exe"; } -#[cfg(target_os = "watchos")] +#[cfg(target_os = "dragonfly")] pub mod os { pub const FAMILY: &str = "unix"; - pub const OS: &str = "watchos"; + pub const OS: &str = "dragonfly"; pub const DLL_PREFIX: &str = "lib"; - pub const DLL_SUFFIX: &str = ".dylib"; - pub const DLL_EXTENSION: &str = "dylib"; + pub const DLL_SUFFIX: &str = ".so"; + pub const DLL_EXTENSION: &str = "so"; pub const EXE_SUFFIX: &str = ""; pub const EXE_EXTENSION: &str = ""; } -#[cfg(target_os = "visionos")] +#[cfg(target_os = "emscripten")] pub mod os { pub const FAMILY: &str = "unix"; - pub const OS: &str = "visionos"; + pub const OS: &str = "emscripten"; pub const DLL_PREFIX: &str = "lib"; - pub const DLL_SUFFIX: &str = ".dylib"; - pub const DLL_EXTENSION: &str = "dylib"; - pub const EXE_SUFFIX: &str = ""; - pub const EXE_EXTENSION: &str = ""; + pub const DLL_SUFFIX: &str = ".so"; + pub const DLL_EXTENSION: &str = "so"; + pub const EXE_SUFFIX: &str = ".js"; + pub const EXE_EXTENSION: &str = "js"; } -#[cfg(target_os = "freebsd")] +#[cfg(target_os = "espidf")] pub mod os { pub const FAMILY: &str = "unix"; - pub const OS: &str = "freebsd"; + pub const OS: &str = "espidf"; pub const DLL_PREFIX: &str = "lib"; pub const DLL_SUFFIX: &str = ".so"; pub const DLL_EXTENSION: &str = "so"; @@ -75,10 +81,10 @@ pub mod os { pub const EXE_EXTENSION: &str = ""; } -#[cfg(target_os = "dragonfly")] +#[cfg(target_os = "freebsd")] pub mod os { pub const FAMILY: &str = "unix"; - pub const OS: &str = "dragonfly"; + pub const OS: &str = "freebsd"; pub const DLL_PREFIX: &str = "lib"; pub const DLL_SUFFIX: &str = ".so"; pub const DLL_EXTENSION: &str = "so"; @@ -86,10 +92,10 @@ pub mod os { pub const EXE_EXTENSION: &str = ""; } -#[cfg(target_os = "netbsd")] +#[cfg(target_os = "fuchsia")] pub mod os { pub const FAMILY: &str = "unix"; - pub const OS: &str = "netbsd"; + pub const OS: &str = "fuchsia"; pub const DLL_PREFIX: &str = "lib"; pub const DLL_SUFFIX: &str = ".so"; pub const DLL_EXTENSION: &str = "so"; @@ -97,10 +103,10 @@ pub mod os { pub const EXE_EXTENSION: &str = ""; } -#[cfg(target_os = "openbsd")] +#[cfg(target_os = "haiku")] pub mod os { pub const FAMILY: &str = "unix"; - pub const OS: &str = "openbsd"; + pub const OS: &str = "haiku"; pub const DLL_PREFIX: &str = "lib"; pub const DLL_SUFFIX: &str = ".so"; pub const DLL_EXTENSION: &str = "so"; @@ -108,32 +114,32 @@ pub mod os { pub const EXE_EXTENSION: &str = ""; } -#[cfg(target_os = "cygwin")] +#[cfg(target_os = "hermit")] pub mod os { - pub const FAMILY: &str = "unix"; - pub const OS: &str = "cygwin"; + pub const FAMILY: &str = ""; + pub const OS: &str = "hermit"; pub const DLL_PREFIX: &str = ""; - pub const DLL_SUFFIX: &str = ".dll"; - pub const DLL_EXTENSION: &str = "dll"; - pub const EXE_SUFFIX: &str = ".exe"; - pub const EXE_EXTENSION: &str = "exe"; + pub const DLL_SUFFIX: &str = ""; + pub const DLL_EXTENSION: &str = ""; + pub const EXE_SUFFIX: &str = ""; + pub const EXE_EXTENSION: &str = ""; } -#[cfg(target_os = "android")] +#[cfg(target_os = "horizon")] pub mod os { pub const FAMILY: &str = "unix"; - pub const OS: &str = "android"; + pub const OS: &str = "horizon"; pub const DLL_PREFIX: &str = "lib"; pub const DLL_SUFFIX: &str = ".so"; pub const DLL_EXTENSION: &str = "so"; - pub const EXE_SUFFIX: &str = ""; - pub const EXE_EXTENSION: &str = ""; + pub const EXE_SUFFIX: &str = ".elf"; + pub const EXE_EXTENSION: &str = "elf"; } -#[cfg(target_os = "solaris")] +#[cfg(target_os = "hurd")] pub mod os { pub const FAMILY: &str = "unix"; - pub const OS: &str = "solaris"; + pub const OS: &str = "hurd"; pub const DLL_PREFIX: &str = "lib"; pub const DLL_SUFFIX: &str = ".so"; pub const DLL_EXTENSION: &str = "so"; @@ -152,32 +158,32 @@ pub mod os { pub const EXE_EXTENSION: &str = ""; } -#[cfg(target_os = "haiku")] +#[cfg(target_os = "ios")] pub mod os { pub const FAMILY: &str = "unix"; - pub const OS: &str = "haiku"; + pub const OS: &str = "ios"; pub const DLL_PREFIX: &str = "lib"; - pub const DLL_SUFFIX: &str = ".so"; - pub const DLL_EXTENSION: &str = "so"; + pub const DLL_SUFFIX: &str = ".dylib"; + pub const DLL_EXTENSION: &str = "dylib"; pub const EXE_SUFFIX: &str = ""; pub const EXE_EXTENSION: &str = ""; } -#[cfg(target_os = "horizon")] +#[cfg(target_os = "l4re")] pub mod os { pub const FAMILY: &str = "unix"; - pub const OS: &str = "horizon"; + pub const OS: &str = "l4re"; pub const DLL_PREFIX: &str = "lib"; pub const DLL_SUFFIX: &str = ".so"; pub const DLL_EXTENSION: &str = "so"; - pub const EXE_SUFFIX: &str = ".elf"; - pub const EXE_EXTENSION: &str = "elf"; + pub const EXE_SUFFIX: &str = ""; + pub const EXE_EXTENSION: &str = ""; } -#[cfg(target_os = "hurd")] +#[cfg(target_os = "linux")] pub mod os { pub const FAMILY: &str = "unix"; - pub const OS: &str = "hurd"; + pub const OS: &str = "linux"; pub const DLL_PREFIX: &str = "lib"; pub const DLL_SUFFIX: &str = ".so"; pub const DLL_EXTENSION: &str = "so"; @@ -185,32 +191,32 @@ pub mod os { pub const EXE_EXTENSION: &str = ""; } -#[cfg(target_os = "vita")] +#[cfg(target_os = "macos")] pub mod os { pub const FAMILY: &str = "unix"; - pub const OS: &str = "vita"; + pub const OS: &str = "macos"; pub const DLL_PREFIX: &str = "lib"; - pub const DLL_SUFFIX: &str = ".so"; - pub const DLL_EXTENSION: &str = "so"; - pub const EXE_SUFFIX: &str = ".elf"; - pub const EXE_EXTENSION: &str = "elf"; + pub const DLL_SUFFIX: &str = ".dylib"; + pub const DLL_EXTENSION: &str = "dylib"; + pub const EXE_SUFFIX: &str = ""; + pub const EXE_EXTENSION: &str = ""; } -#[cfg(all(target_os = "emscripten", target_arch = "wasm32"))] +#[cfg(target_os = "netbsd")] pub mod os { pub const FAMILY: &str = "unix"; - pub const OS: &str = "emscripten"; + pub const OS: &str = "netbsd"; pub const DLL_PREFIX: &str = "lib"; pub const DLL_SUFFIX: &str = ".so"; pub const DLL_EXTENSION: &str = "so"; - pub const EXE_SUFFIX: &str = ".js"; - pub const EXE_EXTENSION: &str = "js"; + pub const EXE_SUFFIX: &str = ""; + pub const EXE_EXTENSION: &str = ""; } -#[cfg(target_os = "fuchsia")] +#[cfg(target_os = "nto")] pub mod os { pub const FAMILY: &str = "unix"; - pub const OS: &str = "fuchsia"; + pub const OS: &str = "nto"; pub const DLL_PREFIX: &str = "lib"; pub const DLL_SUFFIX: &str = ".so"; pub const DLL_EXTENSION: &str = "so"; @@ -218,10 +224,10 @@ pub mod os { pub const EXE_EXTENSION: &str = ""; } -#[cfg(target_os = "l4re")] +#[cfg(target_os = "nuttx")] pub mod os { pub const FAMILY: &str = "unix"; - pub const OS: &str = "l4re"; + pub const OS: &str = "nuttx"; pub const DLL_PREFIX: &str = "lib"; pub const DLL_SUFFIX: &str = ".so"; pub const DLL_EXTENSION: &str = "so"; @@ -229,10 +235,10 @@ pub mod os { pub const EXE_EXTENSION: &str = ""; } -#[cfg(target_os = "nto")] +#[cfg(target_os = "openbsd")] pub mod os { pub const FAMILY: &str = "unix"; - pub const OS: &str = "nto"; + pub const OS: &str = "openbsd"; pub const DLL_PREFIX: &str = "lib"; pub const DLL_SUFFIX: &str = ".so"; pub const DLL_EXTENSION: &str = "so"; @@ -262,10 +268,21 @@ pub mod os { pub const EXE_EXTENSION: &str = ""; } -#[cfg(target_os = "vxworks")] +#[cfg(all(target_vendor = "fortanix", target_env = "sgx"))] +pub mod os { + pub const FAMILY: &str = ""; + pub const OS: &str = ""; + pub const DLL_PREFIX: &str = ""; + pub const DLL_SUFFIX: &str = ".sgxs"; + pub const DLL_EXTENSION: &str = "sgxs"; + pub const EXE_SUFFIX: &str = ".sgxs"; + pub const EXE_EXTENSION: &str = "sgxs"; +} + +#[cfg(target_os = "solaris")] pub mod os { pub const FAMILY: &str = "unix"; - pub const OS: &str = "vxworks"; + pub const OS: &str = "solaris"; pub const DLL_PREFIX: &str = "lib"; pub const DLL_SUFFIX: &str = ".so"; pub const DLL_EXTENSION: &str = "so"; @@ -273,35 +290,126 @@ pub mod os { pub const EXE_EXTENSION: &str = ""; } -#[cfg(target_os = "espidf")] +#[cfg(target_os = "solid_asp3")] pub mod os { - pub const FAMILY: &str = "unix"; - pub const OS: &str = "espidf"; - pub const DLL_PREFIX: &str = "lib"; + pub const FAMILY: &str = "itron"; + pub const OS: &str = "solid"; + pub const DLL_PREFIX: &str = ""; pub const DLL_SUFFIX: &str = ".so"; pub const DLL_EXTENSION: &str = "so"; pub const EXE_SUFFIX: &str = ""; pub const EXE_EXTENSION: &str = ""; } -#[cfg(target_os = "aix")] +#[cfg(target_os = "tvos")] pub mod os { pub const FAMILY: &str = "unix"; - pub const OS: &str = "aix"; + pub const OS: &str = "tvos"; pub const DLL_PREFIX: &str = "lib"; - pub const DLL_SUFFIX: &str = ".a"; - pub const DLL_EXTENSION: &str = "a"; + pub const DLL_SUFFIX: &str = ".dylib"; + pub const DLL_EXTENSION: &str = "dylib"; pub const EXE_SUFFIX: &str = ""; pub const EXE_EXTENSION: &str = ""; } -#[cfg(target_os = "nuttx")] +#[cfg(target_os = "uefi")] +pub mod os { + pub const FAMILY: &str = ""; + pub const OS: &str = "uefi"; + pub const DLL_PREFIX: &str = ""; + pub const DLL_SUFFIX: &str = ""; + pub const DLL_EXTENSION: &str = ""; + pub const EXE_SUFFIX: &str = ".efi"; + pub const EXE_EXTENSION: &str = "efi"; +} + +#[cfg(target_os = "visionos")] pub mod os { pub const FAMILY: &str = "unix"; - pub const OS: &str = "nuttx"; + pub const OS: &str = "visionos"; + pub const DLL_PREFIX: &str = "lib"; + pub const DLL_SUFFIX: &str = ".dylib"; + pub const DLL_EXTENSION: &str = "dylib"; + pub const EXE_SUFFIX: &str = ""; + pub const EXE_EXTENSION: &str = ""; +} + +#[cfg(target_os = "vita")] +pub mod os { + pub const FAMILY: &str = "unix"; + pub const OS: &str = "vita"; + pub const DLL_PREFIX: &str = "lib"; + pub const DLL_SUFFIX: &str = ".so"; + pub const DLL_EXTENSION: &str = "so"; + pub const EXE_SUFFIX: &str = ".elf"; + pub const EXE_EXTENSION: &str = "elf"; +} + +#[cfg(target_os = "vxworks")] +pub mod os { + pub const FAMILY: &str = "unix"; + pub const OS: &str = "vxworks"; pub const DLL_PREFIX: &str = "lib"; pub const DLL_SUFFIX: &str = ".so"; pub const DLL_EXTENSION: &str = "so"; pub const EXE_SUFFIX: &str = ""; pub const EXE_EXTENSION: &str = ""; } + +#[cfg(all(target_family = "wasm", not(any(target_os = "emscripten", target_os = "linux"))))] +pub mod os { + pub const FAMILY: &str = ""; + pub const OS: &str = ""; + pub const DLL_PREFIX: &str = ""; + pub const DLL_SUFFIX: &str = ".wasm"; + pub const DLL_EXTENSION: &str = "wasm"; + pub const EXE_SUFFIX: &str = ".wasm"; + pub const EXE_EXTENSION: &str = "wasm"; +} + +#[cfg(target_os = "watchos")] +pub mod os { + pub const FAMILY: &str = "unix"; + pub const OS: &str = "watchos"; + pub const DLL_PREFIX: &str = "lib"; + pub const DLL_SUFFIX: &str = ".dylib"; + pub const DLL_EXTENSION: &str = "dylib"; + pub const EXE_SUFFIX: &str = ""; + pub const EXE_EXTENSION: &str = ""; +} + +#[cfg(target_os = "windows")] +pub mod os { + pub const FAMILY: &str = "windows"; + pub const OS: &str = "windows"; + pub const DLL_PREFIX: &str = ""; + pub const DLL_SUFFIX: &str = ".dll"; + pub const DLL_EXTENSION: &str = "dll"; + pub const EXE_SUFFIX: &str = ".exe"; + pub const EXE_EXTENSION: &str = "exe"; +} + +#[cfg(target_os = "zkvm")] +pub mod os { + pub const FAMILY: &str = ""; + pub const OS: &str = ""; + pub const DLL_PREFIX: &str = ""; + pub const DLL_SUFFIX: &str = ".elf"; + pub const DLL_EXTENSION: &str = "elf"; + pub const EXE_SUFFIX: &str = ".elf"; + pub const EXE_EXTENSION: &str = "elf"; +} + +// The fallback when none of the other gates match. +#[else] +pub mod os { + pub const FAMILY: &str = ""; + pub const OS: &str = ""; + pub const DLL_PREFIX: &str = ""; + pub const DLL_SUFFIX: &str = ""; + pub const DLL_EXTENSION: &str = ""; + pub const EXE_SUFFIX: &str = ""; + pub const EXE_EXTENSION: &str = ""; +} + +} diff --git a/library/std/src/sys/exit_guard.rs b/library/std/src/sys/exit_guard.rs index 5a090f50666..bd70d178244 100644 --- a/library/std/src/sys/exit_guard.rs +++ b/library/std/src/sys/exit_guard.rs @@ -1,14 +1,5 @@ cfg_if::cfg_if! { if #[cfg(target_os = "linux")] { - /// pthread_t is a pointer on some platforms, - /// so we wrap it in this to impl Send + Sync. - #[derive(Clone, Copy)] - #[repr(transparent)] - struct PThread(libc::pthread_t); - // Safety: pthread_t is safe to send between threads - unsafe impl Send for PThread {} - // Safety: pthread_t is safe to share between threads - unsafe impl Sync for PThread {} /// Mitigation for <https://github.com/rust-lang/rust/issues/126600> /// /// On glibc, `libc::exit` has been observed to not always be thread-safe. @@ -30,28 +21,34 @@ cfg_if::cfg_if! { /// (waiting for the process to exit). #[cfg_attr(any(test, doctest), allow(dead_code))] pub(crate) fn unique_thread_exit() { - let this_thread_id = unsafe { libc::pthread_self() }; - use crate::sync::{Mutex, PoisonError}; - static EXITING_THREAD_ID: Mutex<Option<PThread>> = Mutex::new(None); - let mut exiting_thread_id = - EXITING_THREAD_ID.lock().unwrap_or_else(PoisonError::into_inner); - match *exiting_thread_id { - None => { + use crate::ffi::c_int; + use crate::ptr; + use crate::sync::atomic::AtomicPtr; + use crate::sync::atomic::Ordering::{Acquire, Relaxed}; + + static EXITING_THREAD_ID: AtomicPtr<c_int> = AtomicPtr::new(ptr::null_mut()); + + // We use the address of `errno` as a cheap and safe way to identify + // threads. As the C standard mandates that `errno` must have thread + // storage duration, we can rely on its address not changing over the + // lifetime of the thread. Additionally, accesses to `errno` are + // async-signal-safe, so this function is available in all imaginable + // circumstances. + let this_thread_id = crate::sys::os::errno_location(); + match EXITING_THREAD_ID.compare_exchange(ptr::null_mut(), this_thread_id, Acquire, Relaxed) { + Ok(_) => { // This is the first thread to call `unique_thread_exit`, - // and this is the first time it is called. - // Set EXITING_THREAD_ID to this thread's ID and return. - *exiting_thread_id = Some(PThread(this_thread_id)); - }, - Some(exiting_thread_id) if exiting_thread_id.0 == this_thread_id => { + // and this is the first time it is called. Continue exiting. + } + Err(exiting_thread_id) if exiting_thread_id == this_thread_id => { // This is the first thread to call `unique_thread_exit`, // but this is the second time it is called. // Abort the process. core::panicking::panic_nounwind("std::process::exit called re-entrantly") } - Some(_) => { + Err(_) => { // This is not the first thread to call `unique_thread_exit`. // Pause until the process exits. - drop(exiting_thread_id); loop { // Safety: libc::pause is safe to call. unsafe { libc::pause(); } diff --git a/library/std/src/sys/fd/unix.rs b/library/std/src/sys/fd/unix.rs index 2042ea2c73d..cdca73cdca1 100644 --- a/library/std/src/sys/fd/unix.rs +++ b/library/std/src/sys/fd/unix.rs @@ -71,9 +71,11 @@ const fn max_iov() -> usize { target_os = "android", target_os = "dragonfly", target_os = "emscripten", + target_os = "espidf", target_os = "freebsd", target_os = "linux", target_os = "netbsd", + target_os = "nuttx", target_os = "nto", target_os = "openbsd", target_os = "horizon", @@ -257,9 +259,6 @@ impl FileDesc { } #[cfg(all(target_os = "android", target_pointer_width = "32"))] - // FIXME(#115199): Rust currently omits weak function definitions - // and its metadata from LLVM IR. - #[no_sanitize(cfi)] pub fn read_vectored_at(&self, bufs: &mut [IoSliceMut<'_>], offset: u64) -> io::Result<usize> { weak!( fn preadv64( diff --git a/library/std/src/sys/fs/mod.rs b/library/std/src/sys/fs/mod.rs index 3b176d0d16c..d55e28074fe 100644 --- a/library/std/src/sys/fs/mod.rs +++ b/library/std/src/sys/fs/mod.rs @@ -9,7 +9,7 @@ cfg_if::cfg_if! { if #[cfg(target_family = "unix")] { mod unix; use unix as imp; - pub use unix::{chown, fchown, lchown}; + pub use unix::{chown, fchown, lchown, mkfifo}; #[cfg(not(target_os = "fuchsia"))] pub use unix::chroot; pub(crate) use unix::debug_assert_fd_is_open; @@ -20,6 +20,7 @@ cfg_if::cfg_if! { mod windows; use windows as imp; pub use windows::{symlink_inner, junction_point}; + use crate::sys::path::with_native_path; } else if #[cfg(target_os = "hermit")] { mod hermit; use hermit as imp; @@ -39,7 +40,7 @@ cfg_if::cfg_if! { } // FIXME: Replace this with platform-specific path conversion functions. -#[cfg(not(target_family = "unix"))] +#[cfg(not(any(target_family = "unix", target_os = "windows")))] #[inline] pub fn with_native_path<T>(path: &Path, f: &dyn Fn(&Path) -> io::Result<T>) -> io::Result<T> { f(path) @@ -51,7 +52,7 @@ pub use imp::{ }; pub fn read_dir(path: &Path) -> io::Result<ReadDir> { - // FIXME: use with_native_path + // FIXME: use with_native_path on all platforms imp::readdir(path) } @@ -68,8 +69,11 @@ pub fn remove_dir(path: &Path) -> io::Result<()> { } pub fn remove_dir_all(path: &Path) -> io::Result<()> { - // FIXME: use with_native_path - imp::remove_dir_all(path) + // FIXME: use with_native_path on all platforms + #[cfg(not(windows))] + return imp::remove_dir_all(path); + #[cfg(windows)] + with_native_path(path, &imp::remove_dir_all) } pub fn read_link(path: &Path) -> io::Result<PathBuf> { @@ -77,6 +81,10 @@ pub fn read_link(path: &Path) -> io::Result<PathBuf> { } pub fn symlink(original: &Path, link: &Path) -> io::Result<()> { + // FIXME: use with_native_path on all platforms + #[cfg(windows)] + return imp::symlink(original, link); + #[cfg(not(windows))] with_native_path(original, &|original| { with_native_path(link, &|link| imp::symlink(original, link)) }) @@ -105,11 +113,17 @@ pub fn canonicalize(path: &Path) -> io::Result<PathBuf> { } pub fn copy(from: &Path, to: &Path) -> io::Result<u64> { - // FIXME: use with_native_path - imp::copy(from, to) + // FIXME: use with_native_path on all platforms + #[cfg(not(windows))] + return imp::copy(from, to); + #[cfg(windows)] + with_native_path(from, &|from| with_native_path(to, &|to| imp::copy(from, to))) } pub fn exists(path: &Path) -> io::Result<bool> { - // FIXME: use with_native_path - imp::exists(path) + // FIXME: use with_native_path on all platforms + #[cfg(not(windows))] + return imp::exists(path); + #[cfg(windows)] + with_native_path(path, &imp::exists) } diff --git a/library/std/src/sys/fs/unix.rs b/library/std/src/sys/fs/unix.rs index 87865be0387..5af59a2a914 100644 --- a/library/std/src/sys/fs/unix.rs +++ b/library/std/src/sys/fs/unix.rs @@ -12,10 +12,11 @@ use libc::c_char; all(target_os = "linux", not(target_env = "musl")), target_os = "android", target_os = "fuchsia", - target_os = "hurd" + target_os = "hurd", + target_os = "illumos", ))] use libc::dirfd; -#[cfg(target_os = "fuchsia")] +#[cfg(any(target_os = "fuchsia", target_os = "illumos"))] use libc::fstatat as fstatat64; #[cfg(any(all(target_os = "linux", not(target_env = "musl")), target_os = "hurd"))] use libc::fstatat64; @@ -146,14 +147,14 @@ cfg_has_statx! {{ flags: i32, mask: u32, ) -> Option<io::Result<FileAttr>> { - use crate::sync::atomic::{AtomicU8, Ordering}; + use crate::sync::atomic::{Atomic, AtomicU8, Ordering}; // Linux kernel prior to 4.11 or glibc prior to glibc 2.28 don't support `statx`. // We check for it on first failure and remember availability to avoid having to // do it again. #[repr(u8)] enum STATX_STATE{ Unknown = 0, Present, Unavailable } - static STATX_SAVED_STATE: AtomicU8 = AtomicU8::new(STATX_STATE::Unknown as u8); + static STATX_SAVED_STATE: Atomic<u8> = AtomicU8::new(STATX_STATE::Unknown as u8); syscall!( fn statx( @@ -892,7 +893,8 @@ impl DirEntry { all(target_os = "linux", not(target_env = "musl")), target_os = "android", target_os = "fuchsia", - target_os = "hurd" + target_os = "hurd", + target_os = "illumos", ), not(miri) // no dirfd on Miri ))] @@ -922,6 +924,7 @@ impl DirEntry { target_os = "android", target_os = "fuchsia", target_os = "hurd", + target_os = "illumos", )), miri ))] @@ -1463,20 +1466,6 @@ impl File { Ok(()) } - // FIXME(#115199): Rust currently omits weak function definitions - // and its metadata from LLVM IR. - #[cfg_attr( - any( - target_os = "android", - all( - target_os = "linux", - target_env = "gnu", - target_pointer_width = "32", - not(target_arch = "riscv32") - ) - ), - no_sanitize(cfi) - )] pub fn set_times(&self, times: FileTimes) -> io::Result<()> { #[cfg(not(any( target_os = "redox", @@ -2148,6 +2137,12 @@ pub fn chroot(dir: &Path) -> io::Result<()> { Err(io::const_error!(io::ErrorKind::Unsupported, "chroot not supported by vxworks")) } +pub fn mkfifo(path: &Path, mode: u32) -> io::Result<()> { + run_path_with_cstr(path, &|path| { + cvt(unsafe { libc::mkfifo(path.as_ptr(), mode.try_into().unwrap()) }).map(|_| ()) + }) +} + pub use remove_dir_impl::remove_dir_all; // Fallback for REDOX, ESP-ID, Horizon, Vita, Vxworks and Miri diff --git a/library/std/src/sys/fs/windows.rs b/library/std/src/sys/fs/windows.rs index 15727c99683..9215f937567 100644 --- a/library/std/src/sys/fs/windows.rs +++ b/library/std/src/sys/fs/windows.rs @@ -12,7 +12,7 @@ use crate::sync::Arc; use crate::sys::handle::Handle; use crate::sys::pal::api::{self, WinError, set_file_information_by_handle}; use crate::sys::pal::{IoResult, fill_utf16_buf, to_u16s, truncate_utf16_at_nul}; -use crate::sys::path::maybe_verbatim; +use crate::sys::path::{WCStr, maybe_verbatim}; use crate::sys::time::SystemTime; use crate::sys::{Align8, c, cvt}; use crate::sys_common::{AsInner, FromInner, IntoInner}; @@ -298,10 +298,12 @@ impl OpenOptions { impl File { pub fn open(path: &Path, opts: &OpenOptions) -> io::Result<File> { let path = maybe_verbatim(path)?; + // SAFETY: maybe_verbatim returns null-terminated strings + let path = unsafe { WCStr::from_wchars_with_null_unchecked(&path) }; Self::open_native(&path, opts) } - fn open_native(path: &[u16], opts: &OpenOptions) -> io::Result<File> { + fn open_native(path: &WCStr, opts: &OpenOptions) -> io::Result<File> { let creation = opts.get_creation_mode()?; let handle = unsafe { c::CreateFileW( @@ -1212,9 +1214,8 @@ pub fn readdir(p: &Path) -> io::Result<ReadDir> { } } -pub fn unlink(p: &Path) -> io::Result<()> { - let p_u16s = maybe_verbatim(p)?; - if unsafe { c::DeleteFileW(p_u16s.as_ptr()) } == 0 { +pub fn unlink(path: &WCStr) -> io::Result<()> { + if unsafe { c::DeleteFileW(path.as_ptr()) } == 0 { let err = api::get_last_error(); // if `DeleteFileW` fails with ERROR_ACCESS_DENIED then try to remove // the file while ignoring the readonly attribute. @@ -1223,7 +1224,7 @@ pub fn unlink(p: &Path) -> io::Result<()> { let mut opts = OpenOptions::new(); opts.access_mode(c::DELETE); opts.custom_flags(c::FILE_FLAG_OPEN_REPARSE_POINT); - if let Ok(f) = File::open_native(&p_u16s, &opts) { + if let Ok(f) = File::open_native(&path, &opts) { if f.posix_delete().is_ok() { return Ok(()); } @@ -1236,10 +1237,7 @@ pub fn unlink(p: &Path) -> io::Result<()> { } } -pub fn rename(old: &Path, new: &Path) -> io::Result<()> { - let old = maybe_verbatim(old)?; - let new = maybe_verbatim(new)?; - +pub fn rename(old: &WCStr, new: &WCStr) -> io::Result<()> { 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 @@ -1253,7 +1251,8 @@ pub fn rename(old: &Path, new: &Path) -> 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<u32, _> = ((new.len() - 1) * 2).try_into() + let Ok(new_len_without_nul_in_bytes): Result<u32, _> = + ((new.count_bytes() - 1) * 2).try_into() else { return Err(err).io_result(); }; @@ -1282,7 +1281,7 @@ pub fn rename(old: &Path, new: &Path) -> io::Result<()> { new.as_ptr().copy_to_nonoverlapping( (&raw mut (*file_rename_info).FileName).cast::<u16>(), - new.len(), + new.count_bytes(), ); } @@ -1309,20 +1308,19 @@ pub fn rename(old: &Path, new: &Path) -> io::Result<()> { Ok(()) } -pub fn rmdir(p: &Path) -> io::Result<()> { - let p = maybe_verbatim(p)?; +pub fn rmdir(p: &WCStr) -> io::Result<()> { cvt(unsafe { c::RemoveDirectoryW(p.as_ptr()) })?; Ok(()) } -pub fn remove_dir_all(path: &Path) -> io::Result<()> { +pub fn remove_dir_all(path: &WCStr) -> io::Result<()> { // Open a file or directory without following symlinks. let mut opts = OpenOptions::new(); opts.access_mode(c::FILE_LIST_DIRECTORY); // `FILE_FLAG_BACKUP_SEMANTICS` allows opening directories. // `FILE_FLAG_OPEN_REPARSE_POINT` opens a link instead of its target. opts.custom_flags(c::FILE_FLAG_BACKUP_SEMANTICS | c::FILE_FLAG_OPEN_REPARSE_POINT); - let file = File::open(path, &opts)?; + let file = File::open_native(path, &opts)?; // Test if the file is not a directory or a symlink to a directory. if (file.basic_info()?.FileAttributes & c::FILE_ATTRIBUTE_DIRECTORY) == 0 { @@ -1333,14 +1331,14 @@ pub fn remove_dir_all(path: &Path) -> io::Result<()> { remove_dir_all_iterative(file).io_result() } -pub fn readlink(path: &Path) -> io::Result<PathBuf> { +pub fn readlink(path: &WCStr) -> io::Result<PathBuf> { // Open the link with no access mode, instead of generic read. // By default FILE_LIST_DIRECTORY is denied for the junction "C:\Documents and Settings", so // this is needed for a common case. let mut opts = OpenOptions::new(); opts.access_mode(0); opts.custom_flags(c::FILE_FLAG_OPEN_REPARSE_POINT | c::FILE_FLAG_BACKUP_SEMANTICS); - let file = File::open(path, &opts)?; + let file = File::open_native(&path, &opts)?; file.readlink() } @@ -1378,19 +1376,17 @@ pub fn symlink_inner(original: &Path, link: &Path, dir: bool) -> io::Result<()> } #[cfg(not(target_vendor = "uwp"))] -pub fn link(original: &Path, link: &Path) -> io::Result<()> { - let original = maybe_verbatim(original)?; - let link = maybe_verbatim(link)?; +pub fn link(original: &WCStr, link: &WCStr) -> io::Result<()> { cvt(unsafe { c::CreateHardLinkW(link.as_ptr(), original.as_ptr(), ptr::null_mut()) })?; Ok(()) } #[cfg(target_vendor = "uwp")] -pub fn link(_original: &Path, _link: &Path) -> io::Result<()> { +pub fn link(_original: &WCStr, _link: &WCStr) -> io::Result<()> { return Err(io::const_error!(io::ErrorKind::Unsupported, "hard link are not supported on UWP")); } -pub fn stat(path: &Path) -> io::Result<FileAttr> { +pub fn stat(path: &WCStr) -> io::Result<FileAttr> { match metadata(path, ReparsePoint::Follow) { Err(err) if err.raw_os_error() == Some(c::ERROR_CANT_ACCESS_FILE as i32) => { if let Ok(attrs) = lstat(path) { @@ -1404,7 +1400,7 @@ pub fn stat(path: &Path) -> io::Result<FileAttr> { } } -pub fn lstat(path: &Path) -> io::Result<FileAttr> { +pub fn lstat(path: &WCStr) -> io::Result<FileAttr> { metadata(path, ReparsePoint::Open) } @@ -1420,7 +1416,7 @@ impl ReparsePoint { } } -fn metadata(path: &Path, reparse: ReparsePoint) -> io::Result<FileAttr> { +fn metadata(path: &WCStr, reparse: ReparsePoint) -> io::Result<FileAttr> { let mut opts = OpenOptions::new(); // No read or write permissions are necessary opts.access_mode(0); @@ -1429,7 +1425,7 @@ fn metadata(path: &Path, reparse: ReparsePoint) -> io::Result<FileAttr> { // Attempt to open the file normally. // If that fails with `ERROR_SHARING_VIOLATION` then retry using `FindFirstFileExW`. // If the fallback fails for any reason we return the original error. - match File::open(path, &opts) { + match File::open_native(&path, &opts) { Ok(file) => file.file_attr(), Err(e) if [Some(c::ERROR_SHARING_VIOLATION as _), Some(c::ERROR_ACCESS_DENIED as _)] @@ -1442,8 +1438,6 @@ fn metadata(path: &Path, reparse: ReparsePoint) -> io::Result<FileAttr> { // However, there are special system files, such as // `C:\hiberfil.sys`, that are locked in a way that denies even that. unsafe { - let path = maybe_verbatim(path)?; - // `FindFirstFileExW` accepts wildcard file names. // Fortunately wildcards are not valid file names and // `ERROR_SHARING_VIOLATION` means the file exists (but is locked) @@ -1482,8 +1476,7 @@ fn metadata(path: &Path, reparse: ReparsePoint) -> io::Result<FileAttr> { } } -pub fn set_perm(p: &Path, perm: FilePermissions) -> io::Result<()> { - let p = maybe_verbatim(p)?; +pub fn set_perm(p: &WCStr, perm: FilePermissions) -> io::Result<()> { unsafe { cvt(c::SetFileAttributesW(p.as_ptr(), perm.attrs))?; Ok(()) @@ -1499,17 +1492,17 @@ fn get_path(f: &File) -> io::Result<PathBuf> { ) } -pub fn canonicalize(p: &Path) -> io::Result<PathBuf> { +pub fn canonicalize(p: &WCStr) -> io::Result<PathBuf> { let mut opts = OpenOptions::new(); // No read or write permissions are necessary opts.access_mode(0); // This flag is so we can open directories too opts.custom_flags(c::FILE_FLAG_BACKUP_SEMANTICS); - let f = File::open(p, &opts)?; + let f = File::open_native(p, &opts)?; get_path(&f) } -pub fn copy(from: &Path, to: &Path) -> io::Result<u64> { +pub fn copy(from: &WCStr, to: &WCStr) -> io::Result<u64> { unsafe extern "system" fn callback( _TotalFileSize: i64, _TotalBytesTransferred: i64, @@ -1528,13 +1521,11 @@ pub fn copy(from: &Path, to: &Path) -> io::Result<u64> { c::PROGRESS_CONTINUE } } - let pfrom = maybe_verbatim(from)?; - let pto = maybe_verbatim(to)?; let mut size = 0i64; cvt(unsafe { c::CopyFileExW( - pfrom.as_ptr(), - pto.as_ptr(), + from.as_ptr(), + to.as_ptr(), Some(callback), (&raw mut size) as *mut _, ptr::null_mut(), @@ -1624,14 +1615,14 @@ pub fn junction_point(original: &Path, link: &Path) -> io::Result<()> { } // Try to see if a file exists but, unlike `exists`, report I/O errors. -pub fn exists(path: &Path) -> io::Result<bool> { +pub fn exists(path: &WCStr) -> io::Result<bool> { // Open the file to ensure any symlinks are followed to their target. let mut opts = OpenOptions::new(); // No read, write, etc access rights are needed. opts.access_mode(0); // Backup semantics enables opening directories as well as files. opts.custom_flags(c::FILE_FLAG_BACKUP_SEMANTICS); - match File::open(path, &opts) { + match File::open_native(path, &opts) { Err(e) => match e.kind() { // The file definitely does not exist io::ErrorKind::NotFound => Ok(false), diff --git a/library/std/src/sys/fs/windows/remove_dir_all.rs b/library/std/src/sys/fs/windows/remove_dir_all.rs index f51eced8416..06734f9e309 100644 --- a/library/std/src/sys/fs/windows/remove_dir_all.rs +++ b/library/std/src/sys/fs/windows/remove_dir_all.rs @@ -29,7 +29,7 @@ //! race but we do make a best effort such that it *should* do so. use core::ptr; -use core::sync::atomic::{AtomicU32, Ordering}; +use core::sync::atomic::{Atomic, AtomicU32, Ordering}; use super::{AsRawHandle, DirBuff, File, FromRawHandle}; use crate::sys::c; @@ -87,7 +87,7 @@ fn open_link_no_reparse( // The `OBJ_DONT_REPARSE` attribute ensures that we haven't been // tricked into following a symlink. However, it may not be available in // earlier versions of Windows. - static ATTRIBUTES: AtomicU32 = AtomicU32::new(c::OBJ_DONT_REPARSE); + static ATTRIBUTES: Atomic<u32> = AtomicU32::new(c::OBJ_DONT_REPARSE); let result = unsafe { let mut path_str = c::UNICODE_STRING::from_ref(path); @@ -95,7 +95,7 @@ fn open_link_no_reparse( ObjectName: &mut path_str, RootDirectory: parent.as_raw_handle(), Attributes: ATTRIBUTES.load(Ordering::Relaxed), - ..c::OBJECT_ATTRIBUTES::default() + ..c::OBJECT_ATTRIBUTES::with_length() }; let share = c::FILE_SHARE_DELETE | c::FILE_SHARE_READ | c::FILE_SHARE_WRITE; let options = c::FILE_OPEN_REPARSE_POINT | options; diff --git a/library/std/src/sys/mod.rs b/library/std/src/sys/mod.rs index f8f220fafd1..f9a02b522e5 100644 --- a/library/std/src/sys/mod.rs +++ b/library/std/src/sys/mod.rs @@ -9,8 +9,11 @@ mod alloc; mod personality; pub mod anonymous_pipe; +pub mod args; pub mod backtrace; pub mod cmath; +pub mod env; +pub mod env_consts; pub mod exit_guard; pub mod fd; pub mod fs; diff --git a/library/std/src/sys/net/connection/socket/unix.rs b/library/std/src/sys/net/connection/socket/unix.rs index bbe1e038dcc..b35d5d2aa84 100644 --- a/library/std/src/sys/net/connection/socket/unix.rs +++ b/library/std/src/sys/net/connection/socket/unix.rs @@ -1,5 +1,6 @@ use libc::{MSG_PEEK, c_int, c_void, size_t, sockaddr, socklen_t}; +#[cfg(not(any(target_os = "espidf", target_os = "nuttx")))] use crate::ffi::CStr; use crate::io::{self, BorrowedBuf, BorrowedCursor, IoSlice, IoSliceMut}; use crate::net::{Shutdown, SocketAddr}; diff --git a/library/std/src/sys/net/connection/xous/tcplistener.rs b/library/std/src/sys/net/connection/xous/tcplistener.rs index 7f13ca55920..bdf1fcd9302 100644 --- a/library/std/src/sys/net/connection/xous/tcplistener.rs +++ b/library/std/src/sys/net/connection/xous/tcplistener.rs @@ -1,5 +1,5 @@ use core::convert::TryInto; -use core::sync::atomic::{AtomicBool, AtomicU16, AtomicUsize, Ordering}; +use core::sync::atomic::{Atomic, AtomicBool, AtomicU16, AtomicUsize, Ordering}; use super::*; use crate::net::{IpAddr, Ipv4Addr, Ipv6Addr, SocketAddr}; @@ -18,10 +18,10 @@ macro_rules! unimpl { #[derive(Clone)] pub struct TcpListener { - fd: Arc<AtomicU16>, + fd: Arc<Atomic<u16>>, local: SocketAddr, - handle_count: Arc<AtomicUsize>, - nonblocking: Arc<AtomicBool>, + handle_count: Arc<Atomic<usize>>, + nonblocking: Arc<Atomic<bool>>, } impl TcpListener { diff --git a/library/std/src/sys/net/connection/xous/tcpstream.rs b/library/std/src/sys/net/connection/xous/tcpstream.rs index e8aea8b706a..54524767452 100644 --- a/library/std/src/sys/net/connection/xous/tcpstream.rs +++ b/library/std/src/sys/net/connection/xous/tcpstream.rs @@ -1,4 +1,4 @@ -use core::sync::atomic::{AtomicBool, AtomicU32, AtomicUsize, Ordering}; +use core::sync::atomic::{Atomic, AtomicBool, AtomicU32, AtomicUsize, Ordering}; use super::*; use crate::fmt; @@ -29,11 +29,11 @@ pub struct TcpStream { remote_port: u16, peer_addr: SocketAddr, // milliseconds - read_timeout: Arc<AtomicU32>, + read_timeout: Arc<Atomic<u32>>, // milliseconds - write_timeout: Arc<AtomicU32>, - handle_count: Arc<AtomicUsize>, - nonblocking: Arc<AtomicBool>, + write_timeout: Arc<Atomic<u32>>, + handle_count: Arc<Atomic<usize>>, + nonblocking: Arc<Atomic<bool>>, } fn sockaddr_to_buf(duration: Duration, addr: &SocketAddr, buf: &mut [u8]) { diff --git a/library/std/src/sys/net/connection/xous/udp.rs b/library/std/src/sys/net/connection/xous/udp.rs index c112c04ce94..2127d3267ed 100644 --- a/library/std/src/sys/net/connection/xous/udp.rs +++ b/library/std/src/sys/net/connection/xous/udp.rs @@ -1,5 +1,5 @@ use core::convert::TryInto; -use core::sync::atomic::{AtomicUsize, Ordering}; +use core::sync::atomic::{Atomic, AtomicUsize, Ordering}; use super::*; use crate::cell::Cell; @@ -27,7 +27,7 @@ pub struct UdpSocket { read_timeout: Cell<u64>, // in milliseconds. The setting applies only to `send` calls after the timeout is set. write_timeout: Cell<u64>, - handle_count: Arc<AtomicUsize>, + handle_count: Arc<Atomic<usize>>, nonblocking: Cell<bool>, } diff --git a/library/std/src/sys/pal/hermit/args.rs b/library/std/src/sys/pal/hermit/args.rs deleted file mode 100644 index 44024260277..00000000000 --- a/library/std/src/sys/pal/hermit/args.rs +++ /dev/null @@ -1,66 +0,0 @@ -use crate::ffi::{CStr, OsString, c_char}; -use crate::os::hermit::ffi::OsStringExt; -use crate::sync::atomic::Ordering::{Acquire, Relaxed, Release}; -use crate::sync::atomic::{AtomicIsize, AtomicPtr}; -use crate::{fmt, ptr, vec}; - -static ARGC: AtomicIsize = AtomicIsize::new(0); -static ARGV: AtomicPtr<*const u8> = AtomicPtr::new(ptr::null_mut()); - -/// One-time global initialization. -pub unsafe fn init(argc: isize, argv: *const *const u8) { - ARGC.store(argc, Relaxed); - // Use release ordering here to broadcast writes by the OS. - ARGV.store(argv as *mut *const u8, Release); -} - -/// Returns the command line arguments -pub fn args() -> Args { - // Synchronize with the store above. - let argv = ARGV.load(Acquire); - // If argv has not been initialized yet, do not return any arguments. - let argc = if argv.is_null() { 0 } else { ARGC.load(Relaxed) }; - let args: Vec<OsString> = (0..argc) - .map(|i| unsafe { - let cstr = CStr::from_ptr(*argv.offset(i) as *const c_char); - OsStringExt::from_vec(cstr.to_bytes().to_vec()) - }) - .collect(); - - Args { iter: args.into_iter() } -} - -pub struct Args { - iter: vec::IntoIter<OsString>, -} - -impl fmt::Debug for Args { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - self.iter.as_slice().fmt(f) - } -} - -impl !Send for Args {} -impl !Sync for Args {} - -impl Iterator for Args { - type Item = OsString; - fn next(&mut self) -> Option<OsString> { - self.iter.next() - } - fn size_hint(&self) -> (usize, Option<usize>) { - self.iter.size_hint() - } -} - -impl ExactSizeIterator for Args { - fn len(&self) -> usize { - self.iter.len() - } -} - -impl DoubleEndedIterator for Args { - fn next_back(&mut self) -> Option<OsString> { - self.iter.next_back() - } -} diff --git a/library/std/src/sys/pal/hermit/env.rs b/library/std/src/sys/pal/hermit/env.rs deleted file mode 100644 index 7a0fcb31ef2..00000000000 --- a/library/std/src/sys/pal/hermit/env.rs +++ /dev/null @@ -1,9 +0,0 @@ -pub mod os { - pub const FAMILY: &str = ""; - pub const OS: &str = "hermit"; - pub const DLL_PREFIX: &str = ""; - pub const DLL_SUFFIX: &str = ""; - pub const DLL_EXTENSION: &str = ""; - pub const EXE_SUFFIX: &str = ""; - pub const EXE_EXTENSION: &str = ""; -} diff --git a/library/std/src/sys/pal/hermit/futex.rs b/library/std/src/sys/pal/hermit/futex.rs index 670383b45ac..78c86071fdd 100644 --- a/library/std/src/sys/pal/hermit/futex.rs +++ b/library/std/src/sys/pal/hermit/futex.rs @@ -1,19 +1,19 @@ use super::hermit_abi; use crate::ptr::null; -use crate::sync::atomic::AtomicU32; +use crate::sync::atomic::Atomic; use crate::time::Duration; /// An atomic for use as a futex that is at least 32-bits but may be larger -pub type Futex = AtomicU32; +pub type Futex = Atomic<Primitive>; /// Must be the underlying type of Futex pub type Primitive = u32; /// An atomic for use as a futex that is at least 8-bits but may be larger. -pub type SmallFutex = AtomicU32; +pub type SmallFutex = Atomic<SmallPrimitive>; /// Must be the underlying type of SmallFutex pub type SmallPrimitive = u32; -pub fn futex_wait(futex: &AtomicU32, expected: u32, timeout: Option<Duration>) -> bool { +pub fn futex_wait(futex: &Atomic<u32>, expected: u32, timeout: Option<Duration>) -> bool { // Calculate the timeout as a relative timespec. // // Overflows are rounded up to an infinite timeout (None). @@ -37,12 +37,12 @@ pub fn futex_wait(futex: &AtomicU32, expected: u32, timeout: Option<Duration>) - } #[inline] -pub fn futex_wake(futex: &AtomicU32) -> bool { +pub fn futex_wake(futex: &Atomic<u32>) -> bool { unsafe { hermit_abi::futex_wake(futex.as_ptr(), 1) > 0 } } #[inline] -pub fn futex_wake_all(futex: &AtomicU32) { +pub fn futex_wake_all(futex: &Atomic<u32>) { unsafe { hermit_abi::futex_wake(futex.as_ptr(), i32::MAX); } diff --git a/library/std/src/sys/pal/hermit/mod.rs b/library/std/src/sys/pal/hermit/mod.rs index 26211bcb152..ea636938d70 100644 --- a/library/std/src/sys/pal/hermit/mod.rs +++ b/library/std/src/sys/pal/hermit/mod.rs @@ -16,10 +16,11 @@ #![deny(unsafe_op_in_unsafe_fn)] #![allow(missing_docs, nonstandard_style)] +use crate::io::ErrorKind; +use crate::os::hermit::hermit_abi; use crate::os::raw::c_char; +use crate::sys::env; -pub mod args; -pub mod env; pub mod futex; pub mod os; #[path = "../unsupported/pipe.rs"] @@ -27,9 +28,6 @@ pub mod pipe; pub mod thread; pub mod time; -use crate::io::ErrorKind; -use crate::os::hermit::hermit_abi; - pub fn unsupported<T>() -> crate::io::Result<T> { Err(unsupported_err()) } @@ -58,7 +56,7 @@ pub extern "C" fn __rust_abort() { // NOTE: this is not guaranteed to run, for example when Rust code is called externally. pub unsafe fn init(argc: isize, argv: *const *const u8, _sigpipe: u8) { unsafe { - args::init(argc, argv); + crate::sys::args::init(argc, argv); } } @@ -78,7 +76,7 @@ pub unsafe extern "C" fn runtime_entry( } // initialize environment - os::init_environment(env); + env::init(env); let result = unsafe { main(argc as isize, argv) }; diff --git a/library/std/src/sys/pal/hermit/os.rs b/library/std/src/sys/pal/hermit/os.rs index 791cdb1e57e..a998c3165e5 100644 --- a/library/std/src/sys/pal/hermit/os.rs +++ b/library/std/src/sys/pal/hermit/os.rs @@ -1,15 +1,10 @@ -use core::slice::memchr; - use super::hermit_abi; -use crate::collections::HashMap; use crate::error::Error as StdError; -use crate::ffi::{CStr, OsStr, OsString, c_char}; +use crate::ffi::{OsStr, OsString}; use crate::marker::PhantomData; -use crate::os::hermit::ffi::OsStringExt; use crate::path::{self, PathBuf}; -use crate::sync::Mutex; use crate::sys::unsupported; -use crate::{fmt, io, str, vec}; +use crate::{fmt, io, str}; pub fn errno() -> i32 { unsafe { hermit_abi::get_errno() } @@ -68,115 +63,6 @@ pub fn current_exe() -> io::Result<PathBuf> { unsupported() } -static ENV: Mutex<Option<HashMap<OsString, OsString>>> = Mutex::new(None); - -pub fn init_environment(env: *const *const c_char) { - let mut guard = ENV.lock().unwrap(); - let map = guard.insert(HashMap::new()); - - if env.is_null() { - return; - } - - unsafe { - let mut environ = env; - while !(*environ).is_null() { - if let Some((key, value)) = parse(CStr::from_ptr(*environ).to_bytes()) { - map.insert(key, value); - } - environ = environ.add(1); - } - } - - fn parse(input: &[u8]) -> Option<(OsString, OsString)> { - // Strategy (copied from glibc): Variable name and value are separated - // by an ASCII equals sign '='. Since a variable name must not be - // empty, allow variable names starting with an equals sign. Skip all - // malformed lines. - if input.is_empty() { - return None; - } - let pos = memchr::memchr(b'=', &input[1..]).map(|p| p + 1); - pos.map(|p| { - ( - OsStringExt::from_vec(input[..p].to_vec()), - OsStringExt::from_vec(input[p + 1..].to_vec()), - ) - }) - } -} - -pub struct Env { - iter: vec::IntoIter<(OsString, OsString)>, -} - -// FIXME(https://github.com/rust-lang/rust/issues/114583): Remove this when <OsStr as Debug>::fmt matches <str as Debug>::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<usize>) { - 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::<Vec<_>>(); - - Env { iter: result.into_iter() } -} - -pub fn getenv(k: &OsStr) -> Option<OsString> { - ENV.lock().unwrap().as_ref().unwrap().get(k).cloned() -} - -pub unsafe fn setenv(k: &OsStr, v: &OsStr) -> io::Result<()> { - let (k, v) = (k.to_owned(), v.to_owned()); - ENV.lock().unwrap().as_mut().unwrap().insert(k, v); - Ok(()) -} - -pub unsafe fn unsetenv(k: &OsStr) -> io::Result<()> { - ENV.lock().unwrap().as_mut().unwrap().remove(k); - Ok(()) -} - pub fn temp_dir() -> PathBuf { PathBuf::from("/tmp") } diff --git a/library/std/src/sys/pal/itron/spin.rs b/library/std/src/sys/pal/itron/spin.rs index 6a9a7c72deb..bc4f83260bb 100644 --- a/library/std/src/sys/pal/itron/spin.rs +++ b/library/std/src/sys/pal/itron/spin.rs @@ -1,12 +1,12 @@ use super::abi; use crate::cell::UnsafeCell; use crate::mem::MaybeUninit; -use crate::sync::atomic::{AtomicBool, AtomicUsize, Ordering}; +use crate::sync::atomic::{Atomic, AtomicBool, AtomicUsize, Ordering}; /// A mutex implemented by `dis_dsp` (for intra-core synchronization) and a /// spinlock (for inter-core synchronization). pub struct SpinMutex<T = ()> { - locked: AtomicBool, + locked: Atomic<bool>, data: UnsafeCell<T>, } @@ -19,7 +19,7 @@ impl<T> SpinMutex<T> { /// Acquire a lock. #[inline] pub fn with_locked<R>(&self, f: impl FnOnce(&mut T) -> R) -> R { - struct SpinMutexGuard<'a>(&'a AtomicBool); + struct SpinMutexGuard<'a>(&'a Atomic<bool>); impl Drop for SpinMutexGuard<'_> { #[inline] @@ -50,7 +50,7 @@ impl<T> SpinMutex<T> { /// It's assumed that `0` is not a valid ID, and all kernel /// object IDs fall into range `1..=usize::MAX`. pub struct SpinIdOnceCell<T = ()> { - id: AtomicUsize, + id: Atomic<usize>, spin: SpinMutex<()>, extra: UnsafeCell<MaybeUninit<T>>, } diff --git a/library/std/src/sys/pal/itron/thread.rs b/library/std/src/sys/pal/itron/thread.rs index d1481f827e1..a974f4f17ae 100644 --- a/library/std/src/sys/pal/itron/thread.rs +++ b/library/std/src/sys/pal/itron/thread.rs @@ -9,7 +9,7 @@ use crate::ffi::CStr; use crate::mem::ManuallyDrop; use crate::num::NonZero; use crate::ptr::NonNull; -use crate::sync::atomic::{AtomicUsize, Ordering}; +use crate::sync::atomic::{Atomic, AtomicUsize, Ordering}; use crate::time::Duration; use crate::{hint, io}; @@ -64,7 +64,7 @@ struct ThreadInner { /// '--> JOIN_FINALIZE ---' /// (-1) /// - lifecycle: AtomicUsize, + lifecycle: Atomic<usize>, } // Safety: The only `!Sync` field, `ThreadInner::start`, is only touched by diff --git a/library/std/src/sys/pal/sgx/abi/mod.rs b/library/std/src/sys/pal/sgx/abi/mod.rs index 2c805a4d0af..57247cffad3 100644 --- a/library/std/src/sys/pal/sgx/abi/mod.rs +++ b/library/std/src/sys/pal/sgx/abi/mod.rs @@ -1,7 +1,7 @@ #![cfg_attr(test, allow(unused))] // RT initialization logic is not compiled for test use core::arch::global_asm; -use core::sync::atomic::{AtomicUsize, Ordering}; +use core::sync::atomic::{Atomic, AtomicUsize, Ordering}; use crate::io::Write; @@ -31,7 +31,7 @@ unsafe extern "C" fn tcs_init(secondary: bool) { const BUSY: usize = 1; const DONE: usize = 2; // Three-state spin-lock - static RELOC_STATE: AtomicUsize = AtomicUsize::new(UNINIT); + static RELOC_STATE: Atomic<usize> = AtomicUsize::new(UNINIT); if secondary && RELOC_STATE.load(Ordering::Relaxed) != DONE { rtabort!("Entered secondary TCS before main TCS!") diff --git a/library/std/src/sys/pal/sgx/abi/tls/mod.rs b/library/std/src/sys/pal/sgx/abi/tls/mod.rs index 8e2b271f1c9..41e38b69616 100644 --- a/library/std/src/sys/pal/sgx/abi/tls/mod.rs +++ b/library/std/src/sys/pal/sgx/abi/tls/mod.rs @@ -3,7 +3,7 @@ mod sync_bitset; use self::sync_bitset::*; use crate::cell::Cell; use crate::num::NonZero; -use crate::sync::atomic::{AtomicUsize, Ordering}; +use crate::sync::atomic::{Atomic, AtomicUsize, Ordering}; use crate::{mem, ptr}; #[cfg(target_pointer_width = "64")] @@ -11,16 +11,14 @@ const USIZE_BITS: usize = 64; const TLS_KEYS: usize = 128; // Same as POSIX minimum const TLS_KEYS_BITSET_SIZE: usize = (TLS_KEYS + (USIZE_BITS - 1)) / USIZE_BITS; +// Specifying linkage/symbol name is solely to ensure a single instance between this crate and its unit tests #[cfg_attr(test, linkage = "available_externally")] -#[unsafe(export_name = "_ZN16__rust_internals3std3sys3sgx3abi3tls14TLS_KEY_IN_USEE")] +#[unsafe(export_name = "_ZN16__rust_internals3std3sys3pal3sgx3abi3tls14TLS_KEY_IN_USEE")] static TLS_KEY_IN_USE: SyncBitset = SYNC_BITSET_INIT; -macro_rules! dup { - ((* $($exp:tt)*) $($val:tt)*) => (dup!( ($($exp)*) $($val)* $($val)* )); - (() $($val:tt)*) => ([$($val),*]) -} +// Specifying linkage/symbol name is solely to ensure a single instance between this crate and its unit tests #[cfg_attr(test, linkage = "available_externally")] -#[unsafe(export_name = "_ZN16__rust_internals3std3sys3sgx3abi3tls14TLS_DESTRUCTORE")] -static TLS_DESTRUCTOR: [AtomicUsize; TLS_KEYS] = dup!((* * * * * * *) (AtomicUsize::new(0))); +#[unsafe(export_name = "_ZN16__rust_internals3std3sys3pal3sgx3abi3tls14TLS_DESTRUCTORE")] +static TLS_DESTRUCTOR: [Atomic<usize>; TLS_KEYS] = [const { AtomicUsize::new(0) }; TLS_KEYS]; unsafe extern "C" { fn get_tls_ptr() -> *const u8; @@ -82,7 +80,7 @@ impl<'a> Drop for ActiveTls<'a> { impl Tls { pub fn new() -> Tls { - Tls { data: dup!((* * * * * * *) (Cell::new(ptr::null_mut()))) } + Tls { data: [const { Cell::new(ptr::null_mut()) }; TLS_KEYS] } } pub unsafe fn activate(&self) -> ActiveTls<'_> { diff --git a/library/std/src/sys/pal/sgx/abi/tls/sync_bitset.rs b/library/std/src/sys/pal/sgx/abi/tls/sync_bitset.rs index 4eeff8f6ef7..9087168589a 100644 --- a/library/std/src/sys/pal/sgx/abi/tls/sync_bitset.rs +++ b/library/std/src/sys/pal/sgx/abi/tls/sync_bitset.rs @@ -4,10 +4,10 @@ mod tests; use super::{TLS_KEYS_BITSET_SIZE, USIZE_BITS}; use crate::iter::{Enumerate, Peekable}; use crate::slice::Iter; -use crate::sync::atomic::{AtomicUsize, Ordering}; +use crate::sync::atomic::{Atomic, AtomicUsize, Ordering}; /// A bitset that can be used synchronously. -pub(super) struct SyncBitset([AtomicUsize; TLS_KEYS_BITSET_SIZE]); +pub(super) struct SyncBitset([Atomic<usize>; TLS_KEYS_BITSET_SIZE]); pub(super) const SYNC_BITSET_INIT: SyncBitset = SyncBitset([AtomicUsize::new(0), AtomicUsize::new(0)]); @@ -58,7 +58,7 @@ impl SyncBitset { } pub(super) struct SyncBitsetIter<'a> { - iter: Peekable<Enumerate<Iter<'a, AtomicUsize>>>, + iter: Peekable<Enumerate<Iter<'a, Atomic<usize>>>>, elem_idx: usize, } diff --git a/library/std/src/sys/pal/sgx/abi/usercalls/alloc.rs b/library/std/src/sys/pal/sgx/abi/usercalls/alloc.rs index 3fe6dee3d6f..a60b83213fd 100644 --- a/library/std/src/sys/pal/sgx/abi/usercalls/alloc.rs +++ b/library/std/src/sys/pal/sgx/abi/usercalls/alloc.rs @@ -675,7 +675,7 @@ where /// Obtain the number of elements in this user slice. pub fn len(&self) -> usize { - unsafe { (*self.0.get()).len() } + unsafe { self.0.get().len() } } /// Copies the value from user memory and appends it to `dest`. diff --git a/library/std/src/sys/pal/sgx/env.rs b/library/std/src/sys/pal/sgx/env.rs deleted file mode 100644 index 8043b7c5213..00000000000 --- a/library/std/src/sys/pal/sgx/env.rs +++ /dev/null @@ -1,9 +0,0 @@ -pub mod os { - pub const FAMILY: &str = ""; - pub const OS: &str = ""; - pub const DLL_PREFIX: &str = ""; - pub const DLL_SUFFIX: &str = ".sgxs"; - pub const DLL_EXTENSION: &str = "sgxs"; - pub const EXE_SUFFIX: &str = ".sgxs"; - pub const EXE_EXTENSION: &str = "sgxs"; -} diff --git a/library/std/src/sys/pal/sgx/mod.rs b/library/std/src/sys/pal/sgx/mod.rs index 52684e18ac2..3932f64c0ef 100644 --- a/library/std/src/sys/pal/sgx/mod.rs +++ b/library/std/src/sys/pal/sgx/mod.rs @@ -6,11 +6,9 @@ #![allow(fuzzy_provenance_casts)] // FIXME: this entire module systematically confuses pointers and integers use crate::io::ErrorKind; -use crate::sync::atomic::{AtomicBool, Ordering}; +use crate::sync::atomic::{Atomic, AtomicBool, Ordering}; pub mod abi; -pub mod args; -pub mod env; mod libunwind_integration; pub mod os; #[path = "../unsupported/pipe.rs"] @@ -24,7 +22,7 @@ pub mod waitqueue; // NOTE: this is not guaranteed to run, for example when Rust code is called externally. pub unsafe fn init(argc: isize, argv: *const *const u8, _sigpipe: u8) { unsafe { - args::init(argc, argv); + crate::sys::args::init(argc, argv); } } @@ -48,7 +46,7 @@ pub fn unsupported_err() -> crate::io::Error { /// what happens when `SGX_INEFFECTIVE_ERROR` is set to `true`. If it is /// `false`, the behavior is the same as `unsupported`. pub fn sgx_ineffective<T>(v: T) -> crate::io::Result<T> { - static SGX_INEFFECTIVE_ERROR: AtomicBool = AtomicBool::new(false); + static SGX_INEFFECTIVE_ERROR: Atomic<bool> = AtomicBool::new(false); if SGX_INEFFECTIVE_ERROR.load(Ordering::Relaxed) { Err(crate::io::const_error!( ErrorKind::Uncategorized, diff --git a/library/std/src/sys/pal/sgx/os.rs b/library/std/src/sys/pal/sgx/os.rs index b1ec2afd764..70f838679c9 100644 --- a/library/std/src/sys/pal/sgx/os.rs +++ b/library/std/src/sys/pal/sgx/os.rs @@ -1,14 +1,11 @@ use fortanix_sgx_abi::{Error, RESULT_SUCCESS}; -use crate::collections::HashMap; use crate::error::Error as StdError; use crate::ffi::{OsStr, OsString}; use crate::marker::PhantomData; use crate::path::{self, PathBuf}; -use crate::sync::atomic::{AtomicUsize, Ordering}; -use crate::sync::{Mutex, Once}; use crate::sys::{decode_error_kind, sgx_ineffective, unsupported}; -use crate::{fmt, io, str, vec}; +use crate::{fmt, io, str}; pub fn errno() -> i32 { RESULT_SUCCESS @@ -73,99 +70,6 @@ pub fn current_exe() -> io::Result<PathBuf> { unsupported() } -#[cfg_attr(test, linkage = "available_externally")] -#[unsafe(export_name = "_ZN16__rust_internals3std3sys3sgx2os3ENVE")] -static ENV: AtomicUsize = AtomicUsize::new(0); -#[cfg_attr(test, linkage = "available_externally")] -#[unsafe(export_name = "_ZN16__rust_internals3std3sys3sgx2os8ENV_INITE")] -static ENV_INIT: Once = Once::new(); -type EnvStore = Mutex<HashMap<OsString, OsString>>; - -fn get_env_store() -> Option<&'static EnvStore> { - unsafe { (ENV.load(Ordering::Relaxed) as *const EnvStore).as_ref() } -} - -fn create_env_store() -> &'static EnvStore { - ENV_INIT.call_once(|| { - ENV.store(Box::into_raw(Box::new(EnvStore::default())) as _, Ordering::Relaxed) - }); - 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 <OsStr as Debug>::fmt matches <str as Debug>::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<usize>) { - self.iter.size_hint() - } -} - -pub fn env() -> Env { - let clone_to_vec = |map: &HashMap<OsString, OsString>| -> 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 } -} - -pub fn getenv(k: &OsStr) -> Option<OsString> { - get_env_store().and_then(|s| s.lock().unwrap().get(k).cloned()) -} - -pub unsafe fn setenv(k: &OsStr, v: &OsStr) -> io::Result<()> { - let (k, v) = (k.to_owned(), v.to_owned()); - create_env_store().lock().unwrap().insert(k, v); - Ok(()) -} - -pub unsafe fn unsetenv(k: &OsStr) -> io::Result<()> { - if let Some(env) = get_env_store() { - env.lock().unwrap().remove(k); - } - Ok(()) -} - pub fn temp_dir() -> PathBuf { panic!("no filesystem in SGX") } diff --git a/library/std/src/sys/pal/sgx/thread.rs b/library/std/src/sys/pal/sgx/thread.rs index b6932df431f..219ef1b7a98 100644 --- a/library/std/src/sys/pal/sgx/thread.rs +++ b/library/std/src/sys/pal/sgx/thread.rs @@ -45,8 +45,9 @@ mod task_queue { } } + // Specifying linkage/symbol name is solely to ensure a single instance between this crate and its unit tests #[cfg_attr(test, linkage = "available_externally")] - #[unsafe(export_name = "_ZN16__rust_internals3std3sys3sgx6thread10TASK_QUEUEE")] + #[unsafe(export_name = "_ZN16__rust_internals3std3sys3pal3sgx6thread10TASK_QUEUEE")] static TASK_QUEUE: Mutex<Vec<Task>> = Mutex::new(Vec::new()); pub(super) fn lock() -> MutexGuard<'static, Vec<Task>> { diff --git a/library/std/src/sys/pal/sgx/waitqueue/spin_mutex.rs b/library/std/src/sys/pal/sgx/waitqueue/spin_mutex.rs index f6e851ccadd..73c7a101d60 100644 --- a/library/std/src/sys/pal/sgx/waitqueue/spin_mutex.rs +++ b/library/std/src/sys/pal/sgx/waitqueue/spin_mutex.rs @@ -7,12 +7,12 @@ mod tests; use crate::cell::UnsafeCell; use crate::hint; use crate::ops::{Deref, DerefMut}; -use crate::sync::atomic::{AtomicBool, Ordering}; +use crate::sync::atomic::{Atomic, AtomicBool, Ordering}; #[derive(Default)] pub struct SpinMutex<T> { value: UnsafeCell<T>, - lock: AtomicBool, + lock: Atomic<bool>, } unsafe impl<T: Send> Send for SpinMutex<T> {} diff --git a/library/std/src/sys/pal/solid/env.rs b/library/std/src/sys/pal/solid/env.rs deleted file mode 100644 index 6855c113b28..00000000000 --- a/library/std/src/sys/pal/solid/env.rs +++ /dev/null @@ -1,9 +0,0 @@ -pub mod os { - pub const FAMILY: &str = "itron"; - pub const OS: &str = "solid"; - pub const DLL_PREFIX: &str = ""; - pub const DLL_SUFFIX: &str = ".so"; - pub const DLL_EXTENSION: &str = "so"; - pub const EXE_SUFFIX: &str = ""; - pub const EXE_EXTENSION: &str = ""; -} diff --git a/library/std/src/sys/pal/solid/mod.rs b/library/std/src/sys/pal/solid/mod.rs index 22052a168fd..0011cf256df 100644 --- a/library/std/src/sys/pal/solid/mod.rs +++ b/library/std/src/sys/pal/solid/mod.rs @@ -16,9 +16,6 @@ pub mod itron { use super::unsupported; } -#[path = "../unsupported/args.rs"] -pub mod args; -pub mod env; // `error` is `pub(crate)` so that it can be accessed by `itron/error.rs` as // `crate::sys::error` pub(crate) mod error; diff --git a/library/std/src/sys/pal/solid/os.rs b/library/std/src/sys/pal/solid/os.rs index e3b2e0aa50f..8f5976b0592 100644 --- a/library/std/src/sys/pal/solid/os.rs +++ b/library/std/src/sys/pal/solid/os.rs @@ -1,14 +1,8 @@ -use core::slice::memchr; - use super::{error, itron, unsupported}; use crate::error::Error as StdError; -use crate::ffi::{CStr, OsStr, OsString}; -use crate::os::raw::{c_char, c_int}; -use crate::os::solid::ffi::{OsStrExt, OsStringExt}; +use crate::ffi::{OsStr, OsString}; use crate::path::{self, PathBuf}; -use crate::sync::{PoisonError, RwLock}; -use crate::sys::common::small_c_string::run_with_cstr; -use crate::{fmt, io, vec}; +use crate::{fmt, io}; // `solid` directly maps `errno`s to μITRON error codes. impl itron::error::ItronError { @@ -75,138 +69,6 @@ pub fn current_exe() -> io::Result<PathBuf> { unsupported() } -static ENV_LOCK: RwLock<()> = RwLock::new(()); - -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 <OsStr as Debug>::fmt matches <str as Debug>::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<usize>) { - 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 { - unsafe extern "C" { - static mut environ: *const *const c_char; - } - - unsafe { - let _guard = env_read_lock(); - let mut result = Vec::new(); - if !environ.is_null() { - while !(*environ).is_null() { - if let Some(key_value) = parse(CStr::from_ptr(*environ).to_bytes()) { - result.push(key_value); - } - environ = environ.add(1); - } - } - return Env { iter: result.into_iter() }; - } - - fn parse(input: &[u8]) -> Option<(OsString, OsString)> { - // Strategy (copied from glibc): Variable name and value are separated - // by an ASCII equals sign '='. Since a variable name must not be - // empty, allow variable names starting with an equals sign. Skip all - // malformed lines. - if input.is_empty() { - return None; - } - let pos = memchr::memchr(b'=', &input[1..]).map(|p| p + 1); - pos.map(|p| { - ( - OsStringExt::from_vec(input[..p].to_vec()), - OsStringExt::from_vec(input[p + 1..].to_vec()), - ) - }) - } -} - -pub fn getenv(k: &OsStr) -> Option<OsString> { - // environment variables with a nul byte can't be set, so their value is - // always None as well - run_with_cstr(k.as_bytes(), &|k| { - let _guard = env_read_lock(); - let v = unsafe { libc::getenv(k.as_ptr()) } as *const libc::c_char; - - if v.is_null() { - Ok(None) - } else { - // SAFETY: `v` cannot be mutated while executing this line since we've a read lock - let bytes = unsafe { CStr::from_ptr(v) }.to_bytes().to_vec(); - - Ok(Some(OsStringExt::from_vec(bytes))) - } - }) - .ok() - .flatten() -} - -pub unsafe fn setenv(k: &OsStr, v: &OsStr) -> io::Result<()> { - run_with_cstr(k.as_bytes(), &|k| { - run_with_cstr(v.as_bytes(), &|v| { - let _guard = ENV_LOCK.write(); - cvt_env(unsafe { libc::setenv(k.as_ptr(), v.as_ptr(), 1) }).map(drop) - }) - }) -} - -pub unsafe fn unsetenv(n: &OsStr) -> io::Result<()> { - run_with_cstr(n.as_bytes(), &|nbuf| { - let _guard = ENV_LOCK.write(); - cvt_env(unsafe { libc::unsetenv(nbuf.as_ptr()) }).map(drop) - }) -} - -/// In kmclib, `setenv` and `unsetenv` don't always set `errno`, so this -/// function just returns a generic error. -fn cvt_env(t: c_int) -> io::Result<c_int> { - if t == -1 { Err(io::const_error!(io::ErrorKind::Uncategorized, "failure")) } else { Ok(t) } -} - pub fn temp_dir() -> PathBuf { panic!("no standard temporary directory on this platform") } diff --git a/library/std/src/sys/pal/teeos/mod.rs b/library/std/src/sys/pal/teeos/mod.rs index c1921a2f40d..c7b17777258 100644 --- a/library/std/src/sys/pal/teeos/mod.rs +++ b/library/std/src/sys/pal/teeos/mod.rs @@ -6,11 +6,6 @@ #![allow(unused_variables)] #![allow(dead_code)] -#[path = "../unsupported/args.rs"] -pub mod args; -#[path = "../unsupported/env.rs"] -pub mod env; -//pub mod fd; pub mod os; #[path = "../unsupported/pipe.rs"] pub mod pipe; diff --git a/library/std/src/sys/pal/teeos/os.rs b/library/std/src/sys/pal/teeos/os.rs index bf6945811ab..03f3c72b022 100644 --- a/library/std/src/sys/pal/teeos/os.rs +++ b/library/std/src/sys/pal/teeos/os.rs @@ -73,47 +73,6 @@ pub fn current_exe() -> io::Result<PathBuf> { unsupported() } -pub struct Env(!); - -impl Env { - // FIXME(https://github.com/rust-lang/rust/issues/114583): Remove this when <OsStr as Debug>::fmt matches <str as Debug>::fmt. - pub fn str_debug(&self) -> impl fmt::Debug + '_ { - let Self(inner) = self; - match *inner {} - } -} - -impl fmt::Debug for Env { - fn fmt(&self, _: &mut fmt::Formatter<'_>) -> fmt::Result { - let Self(inner) = self; - match *inner {} - } -} - -impl Iterator for Env { - type Item = (OsString, OsString); - fn next(&mut self) -> Option<(OsString, OsString)> { - let Self(inner) = self; - match *inner {} - } -} - -pub fn env() -> Env { - panic!("not supported on this platform") -} - -pub fn getenv(_: &OsStr) -> Option<OsString> { - None -} - -pub unsafe fn setenv(_: &OsStr, _: &OsStr) -> io::Result<()> { - Err(io::const_error!(io::ErrorKind::Unsupported, "cannot set env vars on this platform")) -} - -pub unsafe fn unsetenv(_: &OsStr) -> io::Result<()> { - Err(io::const_error!(io::ErrorKind::Unsupported, "cannot unset env vars on this platform")) -} - pub fn temp_dir() -> PathBuf { panic!("no filesystem on this platform") } diff --git a/library/std/src/sys/pal/trusty/mod.rs b/library/std/src/sys/pal/trusty/mod.rs index 5295d3fdc91..275f6062463 100644 --- a/library/std/src/sys/pal/trusty/mod.rs +++ b/library/std/src/sys/pal/trusty/mod.rs @@ -1,12 +1,8 @@ //! System bindings for the Trusty OS. -#[path = "../unsupported/args.rs"] -pub mod args; #[path = "../unsupported/common.rs"] #[deny(unsafe_op_in_unsafe_fn)] mod common; -#[path = "../unsupported/env.rs"] -pub mod env; #[path = "../unsupported/os.rs"] pub mod os; #[path = "../unsupported/pipe.rs"] diff --git a/library/std/src/sys/pal/uefi/env.rs b/library/std/src/sys/pal/uefi/env.rs deleted file mode 100644 index c106d5fed3e..00000000000 --- a/library/std/src/sys/pal/uefi/env.rs +++ /dev/null @@ -1,9 +0,0 @@ -pub mod os { - pub const FAMILY: &str = ""; - pub const OS: &str = "uefi"; - pub const DLL_PREFIX: &str = ""; - pub const DLL_SUFFIX: &str = ""; - pub const DLL_EXTENSION: &str = ""; - pub const EXE_SUFFIX: &str = ".efi"; - pub const EXE_EXTENSION: &str = "efi"; -} diff --git a/library/std/src/sys/pal/uefi/helpers.rs b/library/std/src/sys/pal/uefi/helpers.rs index 309022bcccf..6ee3e0a8b66 100644 --- a/library/std/src/sys/pal/uefi/helpers.rs +++ b/library/std/src/sys/pal/uefi/helpers.rs @@ -22,7 +22,7 @@ use crate::os::uefi::{self}; use crate::path::Path; use crate::ptr::NonNull; use crate::slice; -use crate::sync::atomic::{AtomicPtr, Ordering}; +use crate::sync::atomic::{Atomic, AtomicPtr, Ordering}; use crate::sys_common::wstr::WStrUnits; type BootInstallMultipleProtocolInterfaces = @@ -157,7 +157,7 @@ pub(crate) fn device_path_to_text(path: NonNull<device_path::Protocol>) -> io::R Ok(path) } - static LAST_VALID_HANDLE: AtomicPtr<crate::ffi::c_void> = + static LAST_VALID_HANDLE: Atomic<*mut crate::ffi::c_void> = AtomicPtr::new(crate::ptr::null_mut()); if let Some(handle) = NonNull::new(LAST_VALID_HANDLE.load(Ordering::Acquire)) { @@ -269,7 +269,7 @@ impl OwnedDevicePath { .ok_or_else(|| const_error!(io::ErrorKind::InvalidFilename, "invalid Device Path")) } - static LAST_VALID_HANDLE: AtomicPtr<crate::ffi::c_void> = + static LAST_VALID_HANDLE: Atomic<*mut crate::ffi::c_void> = AtomicPtr::new(crate::ptr::null_mut()); if let Some(handle) = NonNull::new(LAST_VALID_HANDLE.load(Ordering::Acquire)) { @@ -606,7 +606,7 @@ pub(crate) fn os_string_to_raw(s: &OsStr) -> Option<Box<[r_efi::efi::Char16]>> { } pub(crate) fn open_shell() -> Option<NonNull<shell::Protocol>> { - static LAST_VALID_HANDLE: AtomicPtr<crate::ffi::c_void> = + static LAST_VALID_HANDLE: Atomic<*mut crate::ffi::c_void> = AtomicPtr::new(crate::ptr::null_mut()); if let Some(handle) = NonNull::new(LAST_VALID_HANDLE.load(Ordering::Acquire)) { diff --git a/library/std/src/sys/pal/uefi/mod.rs b/library/std/src/sys/pal/uefi/mod.rs index 9760a23084a..78fcfcb3b77 100644 --- a/library/std/src/sys/pal/uefi/mod.rs +++ b/library/std/src/sys/pal/uefi/mod.rs @@ -13,8 +13,6 @@ //! [`OsString`]: crate::ffi::OsString #![forbid(unsafe_op_in_unsafe_fn)] -pub mod args; -pub mod env; pub mod helpers; pub mod os; #[path = "../unsupported/pipe.rs"] @@ -30,9 +28,9 @@ pub type RawOsError = usize; use crate::io as std_io; use crate::os::uefi; use crate::ptr::NonNull; -use crate::sync::atomic::{AtomicPtr, Ordering}; +use crate::sync::atomic::{Atomic, AtomicPtr, Ordering}; -static EXIT_BOOT_SERVICE_EVENT: AtomicPtr<crate::ffi::c_void> = +static EXIT_BOOT_SERVICE_EVENT: Atomic<*mut crate::ffi::c_void> = AtomicPtr::new(crate::ptr::null_mut()); /// # SAFETY diff --git a/library/std/src/sys/pal/uefi/os.rs b/library/std/src/sys/pal/uefi/os.rs index d26d61890c1..bfd4dc81cb4 100644 --- a/library/std/src/sys/pal/uefi/os.rs +++ b/library/std/src/sys/pal/uefi/os.rs @@ -131,60 +131,6 @@ pub fn current_exe() -> io::Result<PathBuf> { helpers::device_path_to_text(protocol).map(PathBuf::from) } -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 <OsStr as Debug>::fmt matches <str as Debug>::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) - } -} - -pub fn env() -> Env { - let env = uefi_env::get_all().expect("not supported on this platform"); - Env(env.into_iter()) -} - -pub fn getenv(key: &OsStr) -> Option<OsString> { - uefi_env::get(key) -} - -pub unsafe fn setenv(key: &OsStr, val: &OsStr) -> io::Result<()> { - uefi_env::set(key, val) -} - -pub unsafe fn unsetenv(key: &OsStr) -> io::Result<()> { - uefi_env::unset(key) -} - pub fn temp_dir() -> PathBuf { panic!("no filesystem on this platform") } @@ -213,85 +159,3 @@ pub fn exit(code: i32) -> ! { pub fn getpid() -> u32 { panic!("no pids on this platform") } - -mod uefi_env { - use crate::ffi::{OsStr, OsString}; - use crate::io; - use crate::os::uefi::ffi::OsStringExt; - use crate::ptr::NonNull; - use crate::sys::{helpers, unsupported_err}; - - pub(crate) fn get(key: &OsStr) -> Option<OsString> { - let shell = helpers::open_shell()?; - let mut key_ptr = helpers::os_string_to_raw(key)?; - unsafe { get_raw(shell, key_ptr.as_mut_ptr()) } - } - - pub(crate) fn set(key: &OsStr, val: &OsStr) -> io::Result<()> { - let mut key_ptr = helpers::os_string_to_raw(key) - .ok_or(io::const_error!(io::ErrorKind::InvalidInput, "invalid key"))?; - let mut val_ptr = helpers::os_string_to_raw(val) - .ok_or(io::const_error!(io::ErrorKind::InvalidInput, "invalid value"))?; - unsafe { set_raw(key_ptr.as_mut_ptr(), val_ptr.as_mut_ptr()) } - } - - pub(crate) fn unset(key: &OsStr) -> io::Result<()> { - let mut key_ptr = helpers::os_string_to_raw(key) - .ok_or(io::const_error!(io::ErrorKind::InvalidInput, "invalid key"))?; - unsafe { set_raw(key_ptr.as_mut_ptr(), crate::ptr::null_mut()) } - } - - pub(crate) fn get_all() -> io::Result<Vec<(OsString, OsString)>> { - let shell = helpers::open_shell().ok_or(unsupported_err())?; - - let mut vars = Vec::new(); - let val = unsafe { ((*shell.as_ptr()).get_env)(crate::ptr::null_mut()) }; - - if val.is_null() { - return Ok(vars); - } - - let mut start = 0; - - // UEFI Shell returns all keys separated by NULL. - // End of string is denoted by two NULLs - for i in 0.. { - if unsafe { *val.add(i) } == 0 { - // Two NULL signal end of string - if i == start { - break; - } - - let key = OsString::from_wide(unsafe { - crate::slice::from_raw_parts(val.add(start), i - start) - }); - // SAFETY: val.add(start) is always NULL terminated - let val = unsafe { get_raw(shell, val.add(start)) } - .ok_or(io::const_error!(io::ErrorKind::InvalidInput, "invalid value"))?; - - vars.push((key, val)); - start = i + 1; - } - } - - Ok(vars) - } - - unsafe fn get_raw( - shell: NonNull<r_efi::efi::protocols::shell::Protocol>, - key_ptr: *mut r_efi::efi::Char16, - ) -> Option<OsString> { - let val = unsafe { ((*shell.as_ptr()).get_env)(key_ptr) }; - helpers::os_string_from_raw(val) - } - - unsafe fn set_raw( - key_ptr: *mut r_efi::efi::Char16, - val_ptr: *mut r_efi::efi::Char16, - ) -> io::Result<()> { - let shell = helpers::open_shell().ok_or(unsupported_err())?; - let r = - unsafe { ((*shell.as_ptr()).set_env)(key_ptr, val_ptr, r_efi::efi::Boolean::FALSE) }; - if r.is_error() { Err(io::Error::from_raw_os_error(r.as_usize())) } else { Ok(()) } - } -} diff --git a/library/std/src/sys/pal/uefi/time.rs b/library/std/src/sys/pal/uefi/time.rs index c4ff3015ac6..eeb2c35ffbb 100644 --- a/library/std/src/sys/pal/uefi/time.rs +++ b/library/std/src/sys/pal/uefi/time.rs @@ -121,7 +121,7 @@ pub(crate) mod instant_internal { use super::*; use crate::mem::MaybeUninit; use crate::ptr::NonNull; - use crate::sync::atomic::{AtomicPtr, Ordering}; + use crate::sync::atomic::{Atomic, AtomicPtr, Ordering}; use crate::sys_common::mul_div_u64; const NS_PER_SEC: u64 = 1_000_000_000; @@ -142,7 +142,7 @@ pub(crate) mod instant_internal { Some(mul_div_u64(ts, NS_PER_SEC, freq)) } - static LAST_VALID_HANDLE: AtomicPtr<crate::ffi::c_void> = + static LAST_VALID_HANDLE: Atomic<*mut crate::ffi::c_void> = AtomicPtr::new(crate::ptr::null_mut()); if let Some(handle) = NonNull::new(LAST_VALID_HANDLE.load(Ordering::Acquire)) { diff --git a/library/std/src/sys/pal/unix/futex.rs b/library/std/src/sys/pal/unix/futex.rs index 87ba13ca932..8d89163c42c 100644 --- a/library/std/src/sys/pal/unix/futex.rs +++ b/library/std/src/sys/pal/unix/futex.rs @@ -8,16 +8,16 @@ target_os = "fuchsia", ))] -use crate::sync::atomic::AtomicU32; +use crate::sync::atomic::Atomic; use crate::time::Duration; /// An atomic for use as a futex that is at least 32-bits but may be larger -pub type Futex = AtomicU32; +pub type Futex = Atomic<Primitive>; /// Must be the underlying type of Futex pub type Primitive = u32; /// An atomic for use as a futex that is at least 8-bits but may be larger. -pub type SmallFutex = AtomicU32; +pub type SmallFutex = Atomic<SmallPrimitive>; /// Must be the underlying type of SmallFutex pub type SmallPrimitive = u32; @@ -27,7 +27,7 @@ pub type SmallPrimitive = u32; /// /// Returns false on timeout, and true in all other cases. #[cfg(any(target_os = "linux", target_os = "android", target_os = "freebsd"))] -pub fn futex_wait(futex: &AtomicU32, expected: u32, timeout: Option<Duration>) -> bool { +pub fn futex_wait(futex: &Atomic<u32>, expected: u32, timeout: Option<Duration>) -> bool { use super::time::Timespec; use crate::ptr::null; use crate::sync::atomic::Ordering::Relaxed; @@ -60,7 +60,7 @@ pub fn futex_wait(futex: &AtomicU32, expected: u32, timeout: Option<Duration>) - let umtx_timeout_ptr = umtx_timeout.as_ref().map_or(null(), |t| t as *const _); let umtx_timeout_size = umtx_timeout.as_ref().map_or(0, |t| size_of_val(t)); libc::_umtx_op( - futex as *const AtomicU32 as *mut _, + futex as *const Atomic<u32> as *mut _, libc::UMTX_OP_WAIT_UINT_PRIVATE, expected as libc::c_ulong, crate::ptr::without_provenance_mut(umtx_timeout_size), @@ -71,7 +71,7 @@ pub fn futex_wait(futex: &AtomicU32, expected: u32, timeout: Option<Duration>) - // absolute time rather than a relative time. libc::syscall( libc::SYS_futex, - futex as *const AtomicU32, + futex as *const Atomic<u32>, libc::FUTEX_WAIT_BITSET | libc::FUTEX_PRIVATE_FLAG, expected, timespec.as_ref().map_or(null(), |t| t as *const libc::timespec), @@ -99,16 +99,16 @@ pub fn futex_wait(futex: &AtomicU32, expected: u32, timeout: Option<Duration>) - /// /// On some platforms, this always returns false. #[cfg(any(target_os = "linux", target_os = "android"))] -pub fn futex_wake(futex: &AtomicU32) -> bool { - let ptr = futex as *const AtomicU32; +pub fn futex_wake(futex: &Atomic<u32>) -> bool { + let ptr = futex as *const Atomic<u32>; let op = libc::FUTEX_WAKE | libc::FUTEX_PRIVATE_FLAG; unsafe { libc::syscall(libc::SYS_futex, ptr, op, 1) > 0 } } /// Wakes up all threads that are waiting on `futex_wait` on this futex. #[cfg(any(target_os = "linux", target_os = "android"))] -pub fn futex_wake_all(futex: &AtomicU32) { - let ptr = futex as *const AtomicU32; +pub fn futex_wake_all(futex: &Atomic<u32>) { + let ptr = futex as *const Atomic<u32>; let op = libc::FUTEX_WAKE | libc::FUTEX_PRIVATE_FLAG; unsafe { libc::syscall(libc::SYS_futex, ptr, op, i32::MAX); @@ -117,11 +117,11 @@ pub fn futex_wake_all(futex: &AtomicU32) { // FreeBSD doesn't tell us how many threads are woken up, so this always returns false. #[cfg(target_os = "freebsd")] -pub fn futex_wake(futex: &AtomicU32) -> bool { +pub fn futex_wake(futex: &Atomic<u32>) -> bool { use crate::ptr::null_mut; unsafe { libc::_umtx_op( - futex as *const AtomicU32 as *mut _, + futex as *const Atomic<u32> as *mut _, libc::UMTX_OP_WAKE_PRIVATE, 1, null_mut(), @@ -132,11 +132,11 @@ pub fn futex_wake(futex: &AtomicU32) -> bool { } #[cfg(target_os = "freebsd")] -pub fn futex_wake_all(futex: &AtomicU32) { +pub fn futex_wake_all(futex: &Atomic<u32>) { use crate::ptr::null_mut; unsafe { libc::_umtx_op( - futex as *const AtomicU32 as *mut _, + futex as *const Atomic<u32> as *mut _, libc::UMTX_OP_WAKE_PRIVATE, i32::MAX as libc::c_ulong, null_mut(), @@ -146,7 +146,7 @@ pub fn futex_wake_all(futex: &AtomicU32) { } #[cfg(target_os = "openbsd")] -pub fn futex_wait(futex: &AtomicU32, expected: u32, timeout: Option<Duration>) -> bool { +pub fn futex_wait(futex: &Atomic<u32>, expected: u32, timeout: Option<Duration>) -> bool { use super::time::Timespec; use crate::ptr::{null, null_mut}; @@ -157,7 +157,7 @@ pub fn futex_wait(futex: &AtomicU32, expected: u32, timeout: Option<Duration>) - let r = unsafe { libc::futex( - futex as *const AtomicU32 as *mut u32, + futex as *const Atomic<u32> as *mut u32, libc::FUTEX_WAIT, expected as i32, timespec.as_ref().map_or(null(), |t| t as *const libc::timespec), @@ -169,20 +169,25 @@ pub fn futex_wait(futex: &AtomicU32, expected: u32, timeout: Option<Duration>) - } #[cfg(target_os = "openbsd")] -pub fn futex_wake(futex: &AtomicU32) -> bool { +pub fn futex_wake(futex: &Atomic<u32>) -> bool { use crate::ptr::{null, null_mut}; unsafe { - libc::futex(futex as *const AtomicU32 as *mut u32, libc::FUTEX_WAKE, 1, null(), null_mut()) - > 0 + libc::futex( + futex as *const Atomic<u32> as *mut u32, + libc::FUTEX_WAKE, + 1, + null(), + null_mut(), + ) > 0 } } #[cfg(target_os = "openbsd")] -pub fn futex_wake_all(futex: &AtomicU32) { +pub fn futex_wake_all(futex: &Atomic<u32>) { use crate::ptr::{null, null_mut}; unsafe { libc::futex( - futex as *const AtomicU32 as *mut u32, + futex as *const Atomic<u32> as *mut u32, libc::FUTEX_WAKE, i32::MAX, null(), @@ -192,7 +197,7 @@ pub fn futex_wake_all(futex: &AtomicU32) { } #[cfg(target_os = "dragonfly")] -pub fn futex_wait(futex: &AtomicU32, expected: u32, timeout: Option<Duration>) -> bool { +pub fn futex_wait(futex: &Atomic<u32>, expected: u32, timeout: Option<Duration>) -> bool { // A timeout of 0 means infinite. // We round smaller timeouts up to 1 millisecond. // Overflows are rounded up to an infinite timeout. @@ -200,7 +205,7 @@ pub fn futex_wait(futex: &AtomicU32, expected: u32, timeout: Option<Duration>) - timeout.and_then(|d| Some(i32::try_from(d.as_millis()).ok()?.max(1))).unwrap_or(0); let r = unsafe { - libc::umtx_sleep(futex as *const AtomicU32 as *const i32, expected as i32, timeout_ms) + libc::umtx_sleep(futex as *const Atomic<u32> as *const i32, expected as i32, timeout_ms) }; r == 0 || super::os::errno() != libc::ETIMEDOUT @@ -208,28 +213,28 @@ pub fn futex_wait(futex: &AtomicU32, expected: u32, timeout: Option<Duration>) - // DragonflyBSD doesn't tell us how many threads are woken up, so this always returns false. #[cfg(target_os = "dragonfly")] -pub fn futex_wake(futex: &AtomicU32) -> bool { - unsafe { libc::umtx_wakeup(futex as *const AtomicU32 as *const i32, 1) }; +pub fn futex_wake(futex: &Atomic<u32>) -> bool { + unsafe { libc::umtx_wakeup(futex as *const Atomic<u32> as *const i32, 1) }; false } #[cfg(target_os = "dragonfly")] -pub fn futex_wake_all(futex: &AtomicU32) { - unsafe { libc::umtx_wakeup(futex as *const AtomicU32 as *const i32, i32::MAX) }; +pub fn futex_wake_all(futex: &Atomic<u32>) { + unsafe { libc::umtx_wakeup(futex as *const Atomic<u32> as *const i32, i32::MAX) }; } #[cfg(target_os = "emscripten")] unsafe extern "C" { - fn emscripten_futex_wake(addr: *const AtomicU32, count: libc::c_int) -> libc::c_int; + fn emscripten_futex_wake(addr: *const Atomic<u32>, count: libc::c_int) -> libc::c_int; fn emscripten_futex_wait( - addr: *const AtomicU32, + addr: *const Atomic<u32>, val: libc::c_uint, max_wait_ms: libc::c_double, ) -> libc::c_int; } #[cfg(target_os = "emscripten")] -pub fn futex_wait(futex: &AtomicU32, expected: u32, timeout: Option<Duration>) -> bool { +pub fn futex_wait(futex: &Atomic<u32>, expected: u32, timeout: Option<Duration>) -> bool { unsafe { emscripten_futex_wait( futex, @@ -240,18 +245,18 @@ pub fn futex_wait(futex: &AtomicU32, expected: u32, timeout: Option<Duration>) - } #[cfg(target_os = "emscripten")] -pub fn futex_wake(futex: &AtomicU32) -> bool { +pub fn futex_wake(futex: &Atomic<u32>) -> bool { unsafe { emscripten_futex_wake(futex, 1) > 0 } } #[cfg(target_os = "emscripten")] -pub fn futex_wake_all(futex: &AtomicU32) { +pub fn futex_wake_all(futex: &Atomic<u32>) { unsafe { emscripten_futex_wake(futex, i32::MAX) }; } #[cfg(target_os = "fuchsia")] pub mod zircon { - pub type zx_futex_t = crate::sync::atomic::AtomicU32; + pub type zx_futex_t = crate::sync::atomic::Atomic<u32>; pub type zx_handle_t = u32; pub type zx_status_t = i32; pub type zx_time_t = i64; @@ -282,7 +287,7 @@ pub mod zircon { } #[cfg(target_os = "fuchsia")] -pub fn futex_wait(futex: &AtomicU32, expected: u32, timeout: Option<Duration>) -> bool { +pub fn futex_wait(futex: &Atomic<u32>, expected: u32, timeout: Option<Duration>) -> bool { // Sleep forever if the timeout is longer than fits in a i64. let deadline = timeout .and_then(|d| { @@ -293,19 +298,23 @@ pub fn futex_wait(futex: &AtomicU32, expected: u32, timeout: Option<Duration>) - .unwrap_or(zircon::ZX_TIME_INFINITE); unsafe { - zircon::zx_futex_wait(futex, AtomicU32::new(expected), zircon::ZX_HANDLE_INVALID, deadline) - != zircon::ZX_ERR_TIMED_OUT + zircon::zx_futex_wait( + futex, + core::sync::atomic::AtomicU32::new(expected), + zircon::ZX_HANDLE_INVALID, + deadline, + ) != zircon::ZX_ERR_TIMED_OUT } } // Fuchsia doesn't tell us how many threads are woken up, so this always returns false. #[cfg(target_os = "fuchsia")] -pub fn futex_wake(futex: &AtomicU32) -> bool { +pub fn futex_wake(futex: &Atomic<u32>) -> bool { unsafe { zircon::zx_futex_wake(futex, 1) }; false } #[cfg(target_os = "fuchsia")] -pub fn futex_wake_all(futex: &AtomicU32) { +pub fn futex_wake_all(futex: &Atomic<u32>) { unsafe { zircon::zx_futex_wake(futex, u32::MAX) }; } diff --git a/library/std/src/sys/pal/unix/kernel_copy.rs b/library/std/src/sys/pal/unix/kernel_copy.rs index d42a7e2a7fc..b984afa149d 100644 --- a/library/std/src/sys/pal/unix/kernel_copy.rs +++ b/library/std/src/sys/pal/unix/kernel_copy.rs @@ -62,7 +62,7 @@ use crate::os::unix::io::{AsRawFd, FromRawFd, RawFd}; use crate::os::unix::net::UnixStream; use crate::process::{ChildStderr, ChildStdin, ChildStdout}; use crate::ptr; -use crate::sync::atomic::{AtomicBool, AtomicU8, Ordering}; +use crate::sync::atomic::{Atomic, AtomicBool, AtomicU8, Ordering}; use crate::sys::cvt; use crate::sys::fs::CachedFileMetadata; use crate::sys::weak::syscall; @@ -596,7 +596,7 @@ pub(super) fn copy_regular_files(reader: RawFd, writer: RawFd, max_len: u64) -> // Kernel prior to 4.5 don't have copy_file_range // We store the availability in a global to avoid unnecessary syscalls - static HAS_COPY_FILE_RANGE: AtomicU8 = AtomicU8::new(NOT_PROBED); + static HAS_COPY_FILE_RANGE: Atomic<u8> = AtomicU8::new(NOT_PROBED); let mut have_probed = match HAS_COPY_FILE_RANGE.load(Ordering::Relaxed) { NOT_PROBED => false, @@ -721,8 +721,8 @@ enum SpliceMode { /// performs splice or sendfile between file descriptors /// Does _not_ fall back to a generic copy loop. fn sendfile_splice(mode: SpliceMode, reader: RawFd, writer: RawFd, len: u64) -> CopyResult { - static HAS_SENDFILE: AtomicBool = AtomicBool::new(true); - static HAS_SPLICE: AtomicBool = AtomicBool::new(true); + static HAS_SENDFILE: Atomic<bool> = AtomicBool::new(true); + static HAS_SPLICE: Atomic<bool> = AtomicBool::new(true); // Android builds use feature level 14, but the libc wrapper for splice is // gated on feature level 21+, so we have to invoke the syscall directly. diff --git a/library/std/src/sys/pal/unix/mod.rs b/library/std/src/sys/pal/unix/mod.rs index d7106c33974..ba9e14b8009 100644 --- a/library/std/src/sys/pal/unix/mod.rs +++ b/library/std/src/sys/pal/unix/mod.rs @@ -6,8 +6,6 @@ use crate::io::ErrorKind; #[macro_use] pub mod weak; -pub mod args; -pub mod env; #[cfg(target_os = "fuchsia")] pub mod fuchsia; pub mod futex; @@ -27,6 +25,7 @@ pub mod time; pub fn init(_argc: isize, _argv: *const *const u8, _sigpipe: u8) {} #[cfg(not(target_os = "espidf"))] +#[cfg_attr(target_os = "vita", allow(unused_variables))] // SAFETY: must be called only once during runtime initialization. // NOTE: this is not guaranteed to run, for example when Rust code is called externally. // See `fn init()` in `library/std/src/rt.rs` for docs on `sigpipe`. @@ -47,7 +46,8 @@ pub unsafe fn init(argc: isize, argv: *const *const u8, sigpipe: u8) { reset_sigpipe(sigpipe); stack_overflow::init(); - args::init(argc, argv); + #[cfg(not(target_os = "vita"))] + crate::sys::args::init(argc, argv); // Normally, `thread::spawn` will call `Thread::set_name` but since this thread // already exists, we have to call it ourselves. We only do this on Apple targets @@ -204,7 +204,7 @@ pub unsafe fn init(argc: isize, argv: *const *const u8, sigpipe: u8) { target_os = "vxworks", target_os = "vita", )))] -static ON_BROKEN_PIPE_FLAG_USED: crate::sync::atomic::AtomicBool = +static ON_BROKEN_PIPE_FLAG_USED: crate::sync::atomic::Atomic<bool> = crate::sync::atomic::AtomicBool::new(false); #[cfg(not(any( @@ -273,6 +273,7 @@ pub fn decode_error_kind(errno: i32) -> ErrorKind { libc::ETXTBSY => ExecutableFileBusy, libc::EXDEV => CrossesDevices, libc::EINPROGRESS => InProgress, + libc::EOPNOTSUPP => Unsupported, libc::EACCES | libc::EPERM => PermissionDenied, diff --git a/library/std/src/sys/pal/unix/os.rs b/library/std/src/sys/pal/unix/os.rs index f47421c6705..48609030aed 100644 --- a/library/std/src/sys/pal/unix/os.rs +++ b/library/std/src/sys/pal/unix/os.rs @@ -5,20 +5,15 @@ #[cfg(test)] mod tests; -use core::slice::memchr; - use libc::{c_char, c_int, c_void}; use crate::error::Error as StdError; -use crate::ffi::{CStr, CString, OsStr, OsString}; +use crate::ffi::{CStr, OsStr, OsString}; use crate::os::unix::prelude::*; use crate::path::{self, PathBuf}; -use crate::sync::{PoisonError, RwLock}; -use crate::sys::common::small_c_string::{run_path_with_cstr, run_with_cstr}; -#[cfg(all(target_env = "gnu", not(target_os = "vxworks")))] -use crate::sys::weak::weak; -use crate::sys::{cvt, fd}; -use crate::{fmt, io, iter, mem, ptr, slice, str, vec}; +use crate::sys::common::small_c_string::run_path_with_cstr; +use crate::sys::cvt; +use crate::{fmt, io, iter, mem, ptr, slice, str}; const TMPBUF_SZ: usize = 128; @@ -61,7 +56,7 @@ unsafe extern "C" { #[cfg_attr(target_os = "aix", link_name = "_Errno")] // SAFETY: this will always return the same pointer on a given thread. #[unsafe(ffi_const)] - fn errno_location() -> *mut c_int; + pub safe fn errno_location() -> *mut c_int; } /// Returns the platform-specific value of errno @@ -552,166 +547,6 @@ pub fn current_exe() -> io::Result<PathBuf> { if !path.is_absolute() { getcwd().map(|cwd| cwd.join(path)) } else { Ok(path) } } -pub struct Env { - iter: vec::IntoIter<(OsString, OsString)>, -} - -// FIXME(https://github.com/rust-lang/rust/issues/114583): Remove this when <OsStr as Debug>::fmt matches <str as Debug>::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<usize>) { - self.iter.size_hint() - } -} - -// Use `_NSGetEnviron` on Apple platforms. -// -// `_NSGetEnviron` is the documented alternative (see `man environ`), and has -// been available since the first versions of both macOS and iOS. -// -// Nowadays, specifically since macOS 10.8, `environ` has been exposed through -// `libdyld.dylib`, which is linked via. `libSystem.dylib`: -// <https://github.com/apple-oss-distributions/dyld/blob/dyld-1160.6/libdyld/libdyldGlue.cpp#L913> -// -// So in the end, it likely doesn't really matter which option we use, but the -// performance cost of using `_NSGetEnviron` is extremely miniscule, and it -// might be ever so slightly more supported, so let's just use that. -// -// NOTE: The header where this is defined (`crt_externs.h`) was added to the -// iOS 13.0 SDK, which has been the source of a great deal of confusion in the -// past about the availability of this API. -// -// NOTE(madsmtm): Neither this nor using `environ` has been verified to not -// cause App Store rejections; if this is found to be the case, an alternative -// implementation of this is possible using `[NSProcessInfo environment]` -// - which internally uses `_NSGetEnviron` and a system-wide lock on the -// environment variables to protect against `setenv`, so using that might be -// desirable anyhow? Though it also means that we have to link to Foundation. -#[cfg(target_vendor = "apple")] -pub unsafe fn environ() -> *mut *const *const c_char { - libc::_NSGetEnviron() as *mut *const *const c_char -} - -// Use the `environ` static which is part of POSIX. -#[cfg(not(target_vendor = "apple"))] -pub unsafe fn environ() -> *mut *const *const c_char { - unsafe extern "C" { - static mut environ: *const *const c_char; - } - &raw mut environ -} - -static ENV_LOCK: RwLock<()> = RwLock::new(()); - -pub fn env_read_lock() -> impl Drop { - ENV_LOCK.read().unwrap_or_else(PoisonError::into_inner) -} - -/// Returns a vector of (variable, value) byte-vector pairs for all the -/// environment variables of the current process. -pub fn env() -> Env { - unsafe { - let _guard = env_read_lock(); - let mut environ = *environ(); - let mut result = Vec::new(); - if !environ.is_null() { - while !(*environ).is_null() { - if let Some(key_value) = parse(CStr::from_ptr(*environ).to_bytes()) { - result.push(key_value); - } - environ = environ.add(1); - } - } - return Env { iter: result.into_iter() }; - } - - fn parse(input: &[u8]) -> Option<(OsString, OsString)> { - // Strategy (copied from glibc): Variable name and value are separated - // by an ASCII equals sign '='. Since a variable name must not be - // empty, allow variable names starting with an equals sign. Skip all - // malformed lines. - if input.is_empty() { - return None; - } - let pos = memchr::memchr(b'=', &input[1..]).map(|p| p + 1); - pos.map(|p| { - ( - OsStringExt::from_vec(input[..p].to_vec()), - OsStringExt::from_vec(input[p + 1..].to_vec()), - ) - }) - } -} - -pub fn getenv(k: &OsStr) -> Option<OsString> { - // environment variables with a nul byte can't be set, so their value is - // always None as well - run_with_cstr(k.as_bytes(), &|k| { - let _guard = env_read_lock(); - let v = unsafe { libc::getenv(k.as_ptr()) } as *const libc::c_char; - - if v.is_null() { - Ok(None) - } else { - // SAFETY: `v` cannot be mutated while executing this line since we've a read lock - let bytes = unsafe { CStr::from_ptr(v) }.to_bytes().to_vec(); - - Ok(Some(OsStringExt::from_vec(bytes))) - } - }) - .ok() - .flatten() -} - -pub unsafe fn setenv(k: &OsStr, v: &OsStr) -> io::Result<()> { - run_with_cstr(k.as_bytes(), &|k| { - run_with_cstr(v.as_bytes(), &|v| { - let _guard = ENV_LOCK.write(); - cvt(libc::setenv(k.as_ptr(), v.as_ptr(), 1)).map(drop) - }) - }) -} - -pub unsafe fn unsetenv(n: &OsStr) -> io::Result<()> { - run_with_cstr(n.as_bytes(), &|nbuf| { - let _guard = ENV_LOCK.write(); - cvt(libc::unsetenv(nbuf.as_ptr())).map(drop) - }) -} - #[cfg(not(target_os = "espidf"))] pub fn page_size() -> usize { unsafe { libc::sysconf(libc::_SC_PAGESIZE) as usize } diff --git a/library/std/src/sys/pal/unix/stack_overflow.rs b/library/std/src/sys/pal/unix/stack_overflow.rs index 34b3948e3f6..8bf6d833515 100644 --- a/library/std/src/sys/pal/unix/stack_overflow.rs +++ b/library/std/src/sys/pal/unix/stack_overflow.rs @@ -49,7 +49,7 @@ mod imp { use crate::cell::Cell; use crate::ops::Range; use crate::sync::OnceLock; - use crate::sync::atomic::{AtomicBool, AtomicPtr, AtomicUsize, Ordering}; + use crate::sync::atomic::{Atomic, AtomicBool, AtomicPtr, AtomicUsize, Ordering}; use crate::sys::pal::unix::os; use crate::{io, mem, ptr, thread}; @@ -118,9 +118,9 @@ mod imp { } } - static PAGE_SIZE: AtomicUsize = AtomicUsize::new(0); - static MAIN_ALTSTACK: AtomicPtr<libc::c_void> = AtomicPtr::new(ptr::null_mut()); - static NEED_ALTSTACK: AtomicBool = AtomicBool::new(false); + static PAGE_SIZE: Atomic<usize> = AtomicUsize::new(0); + static MAIN_ALTSTACK: Atomic<*mut libc::c_void> = AtomicPtr::new(ptr::null_mut()); + static NEED_ALTSTACK: Atomic<bool> = AtomicBool::new(false); /// # Safety /// Must be called only once diff --git a/library/std/src/sys/pal/unix/sync/condvar.rs b/library/std/src/sys/pal/unix/sync/condvar.rs index 73631053e9f..efa6f8d7765 100644 --- a/library/std/src/sys/pal/unix/sync/condvar.rs +++ b/library/std/src/sys/pal/unix/sync/condvar.rs @@ -64,7 +64,10 @@ impl Condvar { // https://gist.github.com/stepancheg/198db4623a20aad2ad7cddb8fda4a63c // // To work around this issue, the timeout is clamped to 1000 years. - #[cfg(target_vendor = "apple")] + // + // Cygwin implementation is based on NT API and a super large timeout + // makes the syscall block forever. + #[cfg(any(target_vendor = "apple", target_os = "cygwin"))] let dur = Duration::min(dur, Duration::from_secs(1000 * 365 * 86400)); let timeout = Timespec::now(Self::CLOCK).checked_add_duration(&dur); diff --git a/library/std/src/sys/pal/unix/thread.rs b/library/std/src/sys/pal/unix/thread.rs index 9078dd1c231..4cdc2eaf0e5 100644 --- a/library/std/src/sys/pal/unix/thread.rs +++ b/library/std/src/sys/pal/unix/thread.rs @@ -8,14 +8,19 @@ use crate::sys::weak::weak; use crate::sys::{os, stack_overflow}; use crate::time::Duration; use crate::{cmp, io, ptr}; -#[cfg(not(any(target_os = "l4re", target_os = "vxworks", target_os = "espidf")))] +#[cfg(not(any( + target_os = "l4re", + target_os = "vxworks", + target_os = "espidf", + target_os = "nuttx" +)))] pub const DEFAULT_MIN_STACK_SIZE: usize = 2 * 1024 * 1024; #[cfg(target_os = "l4re")] pub const DEFAULT_MIN_STACK_SIZE: usize = 1024 * 1024; #[cfg(target_os = "vxworks")] pub const DEFAULT_MIN_STACK_SIZE: usize = 256 * 1024; -#[cfg(target_os = "espidf")] -pub const DEFAULT_MIN_STACK_SIZE: usize = 0; // 0 indicates that the stack size configured in the ESP-IDF menuconfig system should be used +#[cfg(any(target_os = "espidf", target_os = "nuttx"))] +pub const DEFAULT_MIN_STACK_SIZE: usize = 0; // 0 indicates that the stack size configured in the ESP-IDF/NuttX menuconfig system should be used #[cfg(target_os = "fuchsia")] mod zircon { @@ -52,10 +57,10 @@ impl Thread { let mut attr: mem::MaybeUninit<libc::pthread_attr_t> = mem::MaybeUninit::uninit(); assert_eq!(libc::pthread_attr_init(attr.as_mut_ptr()), 0); - #[cfg(target_os = "espidf")] + #[cfg(any(target_os = "espidf", target_os = "nuttx"))] if stack > 0 { // Only set the stack if a non-zero value is passed - // 0 is used as an indication that the default stack size configured in the ESP-IDF menuconfig system should be used + // 0 is used as an indication that the default stack size configured in the ESP-IDF/NuttX menuconfig system should be used assert_eq!( libc::pthread_attr_setstacksize( attr.as_mut_ptr(), @@ -65,7 +70,7 @@ impl Thread { ); } - #[cfg(not(target_os = "espidf"))] + #[cfg(not(any(target_os = "espidf", target_os = "nuttx")))] { let stack_size = cmp::max(stack, min_stack_size(attr.as_ptr())); @@ -189,9 +194,6 @@ impl Thread { } #[cfg(any(target_os = "solaris", target_os = "illumos", target_os = "nto"))] - // FIXME(#115199): Rust currently omits weak function definitions - // and its metadata from LLVM IR. - #[no_sanitize(cfi)] pub fn set_name(name: &CStr) { weak!( fn pthread_setname_np( diff --git a/library/std/src/sys/pal/unix/time.rs b/library/std/src/sys/pal/unix/time.rs index b8469b1681f..0074d767474 100644 --- a/library/std/src/sys/pal/unix/time.rs +++ b/library/std/src/sys/pal/unix/time.rs @@ -96,17 +96,6 @@ impl Timespec { } } - // FIXME(#115199): Rust currently omits weak function definitions - // and its metadata from LLVM IR. - #[cfg_attr( - all( - target_os = "linux", - target_env = "gnu", - target_pointer_width = "32", - not(target_arch = "riscv32") - ), - no_sanitize(cfi) - )] pub fn now(clock: libc::clockid_t) -> Timespec { use crate::mem::MaybeUninit; use crate::sys::cvt; diff --git a/library/std/src/sys/pal/unix/weak.rs b/library/std/src/sys/pal/unix/weak.rs index e4c814fba8c..c8cf75b876c 100644 --- a/library/std/src/sys/pal/unix/weak.rs +++ b/library/std/src/sys/pal/unix/weak.rs @@ -24,7 +24,7 @@ use crate::ffi::CStr; use crate::marker::PhantomData; -use crate::sync::atomic::{self, AtomicPtr, Ordering}; +use crate::sync::atomic::{self, Atomic, AtomicPtr, Ordering}; use crate::{mem, ptr}; // We can use true weak linkage on ELF targets. @@ -80,7 +80,7 @@ pub(crate) macro dlsym { } pub(crate) struct DlsymWeak<F> { name: &'static str, - func: AtomicPtr<libc::c_void>, + func: Atomic<*mut libc::c_void>, _marker: PhantomData<F>, } @@ -155,9 +155,6 @@ unsafe fn fetch(name: &str) -> *mut libc::c_void { #[cfg(not(any(target_os = "linux", target_os = "android")))] pub(crate) macro syscall { (fn $name:ident($($param:ident : $t:ty),* $(,)?) -> $ret:ty;) => ( - // FIXME(#115199): Rust currently omits weak function definitions - // and its metadata from LLVM IR. - #[no_sanitize(cfi)] unsafe fn $name($($param: $t),*) -> $ret { weak!(fn $name($($param: $t),*) -> $ret;); diff --git a/library/std/src/sys/pal/unsupported/env.rs b/library/std/src/sys/pal/unsupported/env.rs deleted file mode 100644 index d2efec506c5..00000000000 --- a/library/std/src/sys/pal/unsupported/env.rs +++ /dev/null @@ -1,9 +0,0 @@ -pub mod os { - pub const FAMILY: &str = ""; - pub const OS: &str = ""; - pub const DLL_PREFIX: &str = ""; - pub const DLL_SUFFIX: &str = ""; - pub const DLL_EXTENSION: &str = ""; - pub const EXE_SUFFIX: &str = ""; - pub const EXE_EXTENSION: &str = ""; -} diff --git a/library/std/src/sys/pal/unsupported/mod.rs b/library/std/src/sys/pal/unsupported/mod.rs index 38838b915b5..5e3295b1331 100644 --- a/library/std/src/sys/pal/unsupported/mod.rs +++ b/library/std/src/sys/pal/unsupported/mod.rs @@ -1,7 +1,5 @@ #![deny(unsafe_op_in_unsafe_fn)] -pub mod args; -pub mod env; pub mod os; pub mod pipe; pub mod thread; diff --git a/library/std/src/sys/pal/unsupported/os.rs b/library/std/src/sys/pal/unsupported/os.rs index 48de4312885..a8ef97ecf67 100644 --- a/library/std/src/sys/pal/unsupported/os.rs +++ b/library/std/src/sys/pal/unsupported/os.rs @@ -62,47 +62,6 @@ pub fn current_exe() -> io::Result<PathBuf> { unsupported() } -pub struct Env(!); - -impl Env { - // FIXME(https://github.com/rust-lang/rust/issues/114583): Remove this when <OsStr as Debug>::fmt matches <str as Debug>::fmt. - pub fn str_debug(&self) -> impl fmt::Debug + '_ { - let Self(inner) = self; - match *inner {} - } -} - -impl fmt::Debug for Env { - fn fmt(&self, _: &mut fmt::Formatter<'_>) -> fmt::Result { - let Self(inner) = self; - match *inner {} - } -} - -impl Iterator for Env { - type Item = (OsString, OsString); - fn next(&mut self) -> Option<(OsString, OsString)> { - let Self(inner) = self; - match *inner {} - } -} - -pub fn env() -> Env { - panic!("not supported on this platform") -} - -pub fn getenv(_: &OsStr) -> Option<OsString> { - None -} - -pub unsafe fn setenv(_: &OsStr, _: &OsStr) -> io::Result<()> { - Err(io::const_error!(io::ErrorKind::Unsupported, "cannot set env vars on this platform")) -} - -pub unsafe fn unsetenv(_: &OsStr) -> io::Result<()> { - Err(io::const_error!(io::ErrorKind::Unsupported, "cannot unset env vars on this platform")) -} - pub fn temp_dir() -> PathBuf { panic!("no filesystem on this platform") } diff --git a/library/std/src/sys/pal/wasi/args.rs b/library/std/src/sys/pal/wasi/args.rs deleted file mode 100644 index 52cfa202af8..00000000000 --- a/library/std/src/sys/pal/wasi/args.rs +++ /dev/null @@ -1,61 +0,0 @@ -#![forbid(unsafe_op_in_unsafe_fn)] - -use crate::ffi::{CStr, OsStr, OsString}; -use crate::os::wasi::ffi::OsStrExt; -use crate::{fmt, vec}; - -pub struct Args { - iter: vec::IntoIter<OsString>, -} - -impl !Send for Args {} -impl !Sync for Args {} - -/// Returns the command line arguments -pub fn args() -> Args { - Args { iter: maybe_args().unwrap_or(Vec::new()).into_iter() } -} - -fn maybe_args() -> Option<Vec<OsString>> { - unsafe { - let (argc, buf_size) = wasi::args_sizes_get().ok()?; - let mut argv = Vec::with_capacity(argc); - let mut buf = Vec::with_capacity(buf_size); - wasi::args_get(argv.as_mut_ptr(), buf.as_mut_ptr()).ok()?; - argv.set_len(argc); - let mut ret = Vec::with_capacity(argc); - for ptr in argv { - let s = CStr::from_ptr(ptr.cast()); - ret.push(OsStr::from_bytes(s.to_bytes()).to_owned()); - } - Some(ret) - } -} - -impl fmt::Debug for Args { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - self.iter.as_slice().fmt(f) - } -} - -impl Iterator for Args { - type Item = OsString; - fn next(&mut self) -> Option<OsString> { - self.iter.next() - } - fn size_hint(&self) -> (usize, Option<usize>) { - self.iter.size_hint() - } -} - -impl ExactSizeIterator for Args { - fn len(&self) -> usize { - self.iter.len() - } -} - -impl DoubleEndedIterator for Args { - fn next_back(&mut self) -> Option<OsString> { - self.iter.next_back() - } -} diff --git a/library/std/src/sys/pal/wasi/env.rs b/library/std/src/sys/pal/wasi/env.rs deleted file mode 100644 index 8d444982673..00000000000 --- a/library/std/src/sys/pal/wasi/env.rs +++ /dev/null @@ -1,11 +0,0 @@ -#![forbid(unsafe_op_in_unsafe_fn)] - -pub mod os { - pub const FAMILY: &str = ""; - pub const OS: &str = ""; - pub const DLL_PREFIX: &str = ""; - pub const DLL_SUFFIX: &str = ".wasm"; - pub const DLL_EXTENSION: &str = "wasm"; - pub const EXE_SUFFIX: &str = ".wasm"; - pub const EXE_EXTENSION: &str = "wasm"; -} diff --git a/library/std/src/sys/pal/wasi/mod.rs b/library/std/src/sys/pal/wasi/mod.rs index 80853e7b5a2..61dd1c3f98b 100644 --- a/library/std/src/sys/pal/wasi/mod.rs +++ b/library/std/src/sys/pal/wasi/mod.rs @@ -13,8 +13,6 @@ //! compiling for wasm. That way it's a compile time error for something that's //! guaranteed to be a runtime error! -pub mod args; -pub mod env; #[allow(unused)] #[path = "../wasm/atomics/futex.rs"] pub mod futex; diff --git a/library/std/src/sys/pal/wasi/os.rs b/library/std/src/sys/pal/wasi/os.rs index ba2b65a1f40..672cf70d1a5 100644 --- a/library/std/src/sys/pal/wasi/os.rs +++ b/library/std/src/sys/pal/wasi/os.rs @@ -1,19 +1,16 @@ #![forbid(unsafe_op_in_unsafe_fn)] -use core::slice::memchr; - use crate::error::Error as StdError; use crate::ffi::{CStr, OsStr, OsString}; use crate::marker::PhantomData; -use crate::ops::Drop; use crate::os::wasi::prelude::*; use crate::path::{self, PathBuf}; -use crate::sys::common::small_c_string::{run_path_with_cstr, run_with_cstr}; +use crate::sys::common::small_c_string::run_path_with_cstr; use crate::sys::unsupported; -use crate::{fmt, io, str, vec}; +use crate::{fmt, io, str}; // Add a few symbols not in upstream `libc` just yet. -mod libc { +pub mod libc { pub use libc::*; unsafe extern "C" { @@ -23,28 +20,6 @@ mod libc { } } -cfg_if::cfg_if! { - if #[cfg(target_feature = "atomics")] { - // Access to the environment must be protected by a lock in multi-threaded scenarios. - use crate::sync::{PoisonError, RwLock}; - static ENV_LOCK: RwLock<()> = RwLock::new(()); - pub fn env_read_lock() -> impl Drop { - ENV_LOCK.read().unwrap_or_else(PoisonError::into_inner) - } - pub fn env_write_lock() -> impl Drop { - ENV_LOCK.write().unwrap_or_else(PoisonError::into_inner) - } - } else { - // No need for a lock if we are single-threaded. - pub fn env_read_lock() -> impl Drop { - Box::new(()) - } - pub fn env_write_lock() -> impl Drop { - Box::new(()) - } - } -} - pub fn errno() -> i32 { unsafe extern "C" { #[thread_local] @@ -141,123 +116,6 @@ pub fn current_exe() -> io::Result<PathBuf> { unsupported() } -pub struct Env { - iter: vec::IntoIter<(OsString, OsString)>, -} - -// FIXME(https://github.com/rust-lang/rust/issues/114583): Remove this when <OsStr as Debug>::fmt matches <str as Debug>::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<usize>) { - self.iter.size_hint() - } -} - -pub fn env() -> Env { - unsafe { - let _guard = env_read_lock(); - - // Use `__wasilibc_get_environ` instead of `environ` here so that we - // don't require wasi-libc to eagerly initialize the environment - // variables. - let mut environ = libc::__wasilibc_get_environ(); - - let mut result = Vec::new(); - if !environ.is_null() { - while !(*environ).is_null() { - if let Some(key_value) = parse(CStr::from_ptr(*environ).to_bytes()) { - result.push(key_value); - } - environ = environ.add(1); - } - } - return Env { iter: result.into_iter() }; - } - - // See src/libstd/sys/pal/unix/os.rs, same as that - fn parse(input: &[u8]) -> Option<(OsString, OsString)> { - if input.is_empty() { - return None; - } - let pos = memchr::memchr(b'=', &input[1..]).map(|p| p + 1); - pos.map(|p| { - ( - OsStringExt::from_vec(input[..p].to_vec()), - OsStringExt::from_vec(input[p + 1..].to_vec()), - ) - }) - } -} - -pub fn getenv(k: &OsStr) -> Option<OsString> { - // environment variables with a nul byte can't be set, so their value is - // always None as well - run_with_cstr(k.as_bytes(), &|k| { - let _guard = env_read_lock(); - let v = unsafe { libc::getenv(k.as_ptr()) } as *const libc::c_char; - - if v.is_null() { - Ok(None) - } else { - // SAFETY: `v` cannot be mutated while executing this line since we've a read lock - let bytes = unsafe { CStr::from_ptr(v) }.to_bytes().to_vec(); - - Ok(Some(OsStringExt::from_vec(bytes))) - } - }) - .ok() - .flatten() -} - -pub unsafe fn setenv(k: &OsStr, v: &OsStr) -> io::Result<()> { - run_with_cstr(k.as_bytes(), &|k| { - run_with_cstr(v.as_bytes(), &|v| unsafe { - let _guard = env_write_lock(); - cvt(libc::setenv(k.as_ptr(), v.as_ptr(), 1)).map(drop) - }) - }) -} - -pub unsafe fn unsetenv(n: &OsStr) -> io::Result<()> { - run_with_cstr(n.as_bytes(), &|nbuf| unsafe { - let _guard = env_write_lock(); - cvt(libc::unsetenv(nbuf.as_ptr())).map(drop) - }) -} - #[allow(dead_code)] pub fn page_size() -> usize { unsafe { libc::sysconf(libc::_SC_PAGESIZE) as usize } @@ -294,6 +152,6 @@ macro_rules! impl_is_minus_one { impl_is_minus_one! { i8 i16 i32 i64 isize } -fn cvt<T: IsMinusOne>(t: T) -> io::Result<T> { +pub fn cvt<T: IsMinusOne>(t: T) -> io::Result<T> { if t.is_minus_one() { Err(io::Error::last_os_error()) } else { Ok(t) } } diff --git a/library/std/src/sys/pal/wasip2/mod.rs b/library/std/src/sys/pal/wasip2/mod.rs index 504b947d09e..47fe3221c90 100644 --- a/library/std/src/sys/pal/wasip2/mod.rs +++ b/library/std/src/sys/pal/wasip2/mod.rs @@ -6,10 +6,6 @@ //! To begin with, this target mirrors the wasi target 1 to 1, but over //! time this will change significantly. -#[path = "../wasi/args.rs"] -pub mod args; -#[path = "../wasi/env.rs"] -pub mod env; #[allow(unused)] #[path = "../wasm/atomics/futex.rs"] pub mod futex; diff --git a/library/std/src/sys/pal/wasm/atomics/futex.rs b/library/std/src/sys/pal/wasm/atomics/futex.rs index bdad0da73f0..6676aa7e8e3 100644 --- a/library/std/src/sys/pal/wasm/atomics/futex.rs +++ b/library/std/src/sys/pal/wasm/atomics/futex.rs @@ -3,16 +3,16 @@ use core::arch::wasm32 as wasm; #[cfg(target_arch = "wasm64")] use core::arch::wasm64 as wasm; -use crate::sync::atomic::AtomicU32; +use crate::sync::atomic::Atomic; use crate::time::Duration; /// An atomic for use as a futex that is at least 32-bits but may be larger -pub type Futex = AtomicU32; +pub type Futex = Atomic<Primitive>; /// Must be the underlying type of Futex pub type Primitive = u32; /// An atomic for use as a futex that is at least 8-bits but may be larger. -pub type SmallFutex = AtomicU32; +pub type SmallFutex = Atomic<SmallPrimitive>; /// Must be the underlying type of SmallFutex pub type SmallPrimitive = u32; @@ -21,11 +21,14 @@ pub type SmallPrimitive = u32; /// Returns directly if the futex doesn't hold the expected value. /// /// Returns false on timeout, and true in all other cases. -pub fn futex_wait(futex: &AtomicU32, expected: u32, timeout: Option<Duration>) -> bool { +pub fn futex_wait(futex: &Atomic<u32>, expected: u32, timeout: Option<Duration>) -> bool { let timeout = timeout.and_then(|t| t.as_nanos().try_into().ok()).unwrap_or(-1); unsafe { - wasm::memory_atomic_wait32(futex as *const AtomicU32 as *mut i32, expected as i32, timeout) - < 2 + wasm::memory_atomic_wait32( + futex as *const Atomic<u32> as *mut i32, + expected as i32, + timeout, + ) < 2 } } @@ -33,13 +36,13 @@ pub fn futex_wait(futex: &AtomicU32, expected: u32, timeout: Option<Duration>) - /// /// Returns true if this actually woke up such a thread, /// or false if no thread was waiting on this futex. -pub fn futex_wake(futex: &AtomicU32) -> bool { - unsafe { wasm::memory_atomic_notify(futex as *const AtomicU32 as *mut i32, 1) > 0 } +pub fn futex_wake(futex: &Atomic<u32>) -> bool { + unsafe { wasm::memory_atomic_notify(futex as *const Atomic<u32> as *mut i32, 1) > 0 } } /// Wakes up all threads that are waiting on `futex_wait` on this futex. -pub fn futex_wake_all(futex: &AtomicU32) { +pub fn futex_wake_all(futex: &Atomic<u32>) { unsafe { - wasm::memory_atomic_notify(futex as *const AtomicU32 as *mut i32, i32::MAX as u32); + wasm::memory_atomic_notify(futex as *const Atomic<u32> as *mut i32, i32::MAX as u32); } } diff --git a/library/std/src/sys/pal/wasm/env.rs b/library/std/src/sys/pal/wasm/env.rs deleted file mode 100644 index 730e356d7fe..00000000000 --- a/library/std/src/sys/pal/wasm/env.rs +++ /dev/null @@ -1,9 +0,0 @@ -pub mod os { - pub const FAMILY: &str = ""; - pub const OS: &str = ""; - pub const DLL_PREFIX: &str = ""; - pub const DLL_SUFFIX: &str = ".wasm"; - pub const DLL_EXTENSION: &str = "wasm"; - pub const EXE_SUFFIX: &str = ".wasm"; - pub const EXE_EXTENSION: &str = "wasm"; -} diff --git a/library/std/src/sys/pal/wasm/mod.rs b/library/std/src/sys/pal/wasm/mod.rs index 8d39b70d039..37cb46a8f6b 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/args.rs"] -pub mod args; -pub mod env; #[path = "../unsupported/os.rs"] pub mod os; #[path = "../unsupported/pipe.rs"] diff --git a/library/std/src/sys/pal/windows/c.rs b/library/std/src/sys/pal/windows/c.rs index 004cbee52f6..ac1c5e9932e 100644 --- a/library/std/src/sys/pal/windows/c.rs +++ b/library/std/src/sys/pal/windows/c.rs @@ -44,8 +44,8 @@ impl UNICODE_STRING { } } -impl Default for OBJECT_ATTRIBUTES { - fn default() -> Self { +impl OBJECT_ATTRIBUTES { + pub fn with_length() -> Self { Self { Length: size_of::<Self>() as _, RootDirectory: ptr::null_mut(), diff --git a/library/std/src/sys/pal/windows/c/bindings.txt b/library/std/src/sys/pal/windows/c/bindings.txt index e2c21633279..d5fbb453c6f 100644 --- a/library/std/src/sys/pal/windows/c/bindings.txt +++ b/library/std/src/sys/pal/windows/c/bindings.txt @@ -1,7 +1,8 @@ --out windows_sys.rs --flat --sys ---no-core +--no-deps +--link windows_targets --filter !INVALID_HANDLE_VALUE ABOVE_NORMAL_PRIORITY_CLASS @@ -19,7 +20,6 @@ ALL_PROCESSOR_GROUPS ARM64_NT_NEON128 BELOW_NORMAL_PRIORITY_CLASS bind -BOOL BY_HANDLE_FILE_INFORMATION CALLBACK_CHUNK_FINISHED CALLBACK_STREAM_SWITCH diff --git a/library/std/src/sys/pal/windows/c/windows_sys.rs b/library/std/src/sys/pal/windows/c/windows_sys.rs index 1d0e89f5d0f..eb2914b8644 100644 --- a/library/std/src/sys/pal/windows/c/windows_sys.rs +++ b/library/std/src/sys/pal/windows/c/windows_sys.rs @@ -1,4 +1,4 @@ -// Bindings generated by `windows-bindgen` 0.59.0 +// Bindings generated by `windows-bindgen` 0.61.0 #![allow(non_snake_case, non_upper_case_globals, non_camel_case_types, dead_code, clippy::all)] @@ -141,7 +141,7 @@ windows_targets::link!("ws2_32.dll" "system" fn setsockopt(s : SOCKET, level : i windows_targets::link!("ws2_32.dll" "system" fn shutdown(s : SOCKET, how : WINSOCK_SHUTDOWN_HOW) -> i32); pub const ABOVE_NORMAL_PRIORITY_CLASS: PROCESS_CREATION_FLAGS = 32768u32; #[repr(C)] -#[derive(Clone, Copy)] +#[derive(Clone, Copy, Default)] pub struct ACL { pub AclRevision: u8, pub Sbz1: u8, @@ -162,6 +162,11 @@ pub struct ADDRINFOA { pub ai_addr: *mut SOCKADDR, pub ai_next: *mut ADDRINFOA, } +impl Default for ADDRINFOA { + fn default() -> Self { + unsafe { core::mem::zeroed() } + } +} pub const AF_INET: ADDRESS_FAMILY = 2u16; pub const AF_INET6: ADDRESS_FAMILY = 23u16; pub const AF_UNIX: u16 = 1u16; @@ -176,8 +181,13 @@ pub union ARM64_NT_NEON128 { pub H: [u16; 8], pub B: [u8; 16], } +impl Default for ARM64_NT_NEON128 { + fn default() -> Self { + unsafe { core::mem::zeroed() } + } +} #[repr(C)] -#[derive(Clone, Copy)] +#[derive(Clone, Copy, Default)] pub struct ARM64_NT_NEON128_0 { pub Low: u64, pub High: i64, @@ -185,7 +195,7 @@ pub struct ARM64_NT_NEON128_0 { pub const BELOW_NORMAL_PRIORITY_CLASS: PROCESS_CREATION_FLAGS = 16384u32; pub type BOOL = i32; #[repr(C)] -#[derive(Clone, Copy)] +#[derive(Clone, Copy, Default)] pub struct BY_HANDLE_FILE_INFORMATION { pub dwFileAttributes: u32, pub ftCreationTime: FILETIME, @@ -206,9 +216,14 @@ pub type COMPARESTRING_RESULT = i32; pub struct CONDITION_VARIABLE { pub Ptr: *mut core::ffi::c_void, } +impl Default for CONDITION_VARIABLE { + fn default() -> Self { + unsafe { core::mem::zeroed() } + } +} pub type CONSOLE_MODE = u32; #[repr(C)] -#[derive(Clone, Copy)] +#[derive(Clone, Copy, Default)] pub struct CONSOLE_READCONSOLE_CONTROL { pub nLength: u32, pub nInitialChars: u32, @@ -245,6 +260,12 @@ pub struct CONTEXT { pub SegSs: u32, pub ExtendedRegisters: [u8; 512], } +#[cfg(target_arch = "x86")] +impl Default for CONTEXT { + fn default() -> Self { + unsafe { core::mem::zeroed() } + } +} #[repr(C)] #[cfg(any(target_arch = "arm64ec", target_arch = "x86_64"))] #[derive(Clone, Copy)] @@ -296,6 +317,12 @@ pub struct CONTEXT { pub LastExceptionToRip: u64, pub LastExceptionFromRip: u64, } +#[cfg(any(target_arch = "arm64ec", target_arch = "x86_64"))] +impl Default for CONTEXT { + fn default() -> Self { + unsafe { core::mem::zeroed() } + } +} #[repr(C)] #[cfg(any(target_arch = "arm64ec", target_arch = "x86_64"))] #[derive(Clone, Copy)] @@ -303,6 +330,12 @@ pub union CONTEXT_0 { pub FltSave: XSAVE_FORMAT, pub Anonymous: CONTEXT_0_0, } +#[cfg(any(target_arch = "arm64ec", target_arch = "x86_64"))] +impl Default for CONTEXT_0 { + fn default() -> Self { + unsafe { core::mem::zeroed() } + } +} #[repr(C)] #[cfg(any(target_arch = "arm64ec", target_arch = "x86_64"))] #[derive(Clone, Copy)] @@ -326,6 +359,12 @@ pub struct CONTEXT_0_0 { pub Xmm14: M128A, pub Xmm15: M128A, } +#[cfg(any(target_arch = "arm64ec", target_arch = "x86_64"))] +impl Default for CONTEXT_0_0 { + fn default() -> Self { + unsafe { core::mem::zeroed() } + } +} #[repr(C)] #[cfg(target_arch = "aarch64")] #[derive(Clone, Copy)] @@ -343,6 +382,12 @@ pub struct CONTEXT { pub Wcr: [u32; 2], pub Wvr: [u64; 2], } +#[cfg(target_arch = "aarch64")] +impl Default for CONTEXT { + fn default() -> Self { + unsafe { core::mem::zeroed() } + } +} #[repr(C)] #[cfg(target_arch = "aarch64")] #[derive(Clone, Copy)] @@ -350,9 +395,15 @@ pub union CONTEXT_0 { pub Anonymous: CONTEXT_0_0, pub X: [u64; 31], } +#[cfg(target_arch = "aarch64")] +impl Default for CONTEXT_0 { + fn default() -> Self { + unsafe { core::mem::zeroed() } + } +} #[repr(C)] #[cfg(target_arch = "aarch64")] -#[derive(Clone, Copy)] +#[derive(Clone, Copy, Default)] pub struct CONTEXT_0_0 { pub X0: u64, pub X1: u64, @@ -2305,6 +2356,11 @@ pub struct EXCEPTION_POINTERS { pub ExceptionRecord: *mut EXCEPTION_RECORD, pub ContextRecord: *mut CONTEXT, } +impl Default for EXCEPTION_POINTERS { + fn default() -> Self { + unsafe { core::mem::zeroed() } + } +} #[repr(C)] #[derive(Clone, Copy)] pub struct EXCEPTION_RECORD { @@ -2315,6 +2371,11 @@ pub struct EXCEPTION_RECORD { pub NumberParameters: u32, pub ExceptionInformation: [usize; 15], } +impl Default for EXCEPTION_RECORD { + fn default() -> Self { + unsafe { core::mem::zeroed() } + } +} pub const EXCEPTION_STACK_OVERFLOW: NTSTATUS = 0xC00000FD_u32 as _; pub const EXTENDED_STARTUPINFO_PRESENT: PROCESS_CREATION_FLAGS = 524288u32; pub const E_NOTIMPL: HRESULT = 0x80004001_u32 as _; @@ -2333,8 +2394,13 @@ pub struct FD_SET { pub fd_count: u32, pub fd_array: [SOCKET; 64], } +impl Default for FD_SET { + fn default() -> Self { + unsafe { core::mem::zeroed() } + } +} #[repr(C)] -#[derive(Clone, Copy)] +#[derive(Clone, Copy, Default)] pub struct FILETIME { pub dwLowDateTime: u32, pub dwHighDateTime: u32, @@ -2343,7 +2409,7 @@ pub type FILE_ACCESS_RIGHTS = u32; pub const FILE_ADD_FILE: FILE_ACCESS_RIGHTS = 2u32; pub const FILE_ADD_SUBDIRECTORY: FILE_ACCESS_RIGHTS = 4u32; #[repr(C)] -#[derive(Clone, Copy)] +#[derive(Clone, Copy, Default)] pub struct FILE_ALLOCATION_INFO { pub AllocationSize: i64, } @@ -2369,7 +2435,7 @@ pub const FILE_ATTRIBUTE_REPARSE_POINT: FILE_FLAGS_AND_ATTRIBUTES = 1024u32; pub const FILE_ATTRIBUTE_SPARSE_FILE: FILE_FLAGS_AND_ATTRIBUTES = 512u32; pub const FILE_ATTRIBUTE_SYSTEM: FILE_FLAGS_AND_ATTRIBUTES = 4u32; #[repr(C)] -#[derive(Clone, Copy)] +#[derive(Clone, Copy, Default)] pub struct FILE_ATTRIBUTE_TAG_INFO { pub FileAttributes: u32, pub ReparseTag: u32, @@ -2378,7 +2444,7 @@ pub const FILE_ATTRIBUTE_TEMPORARY: FILE_FLAGS_AND_ATTRIBUTES = 256u32; pub const FILE_ATTRIBUTE_UNPINNED: FILE_FLAGS_AND_ATTRIBUTES = 1048576u32; pub const FILE_ATTRIBUTE_VIRTUAL: FILE_FLAGS_AND_ATTRIBUTES = 65536u32; #[repr(C)] -#[derive(Clone, Copy)] +#[derive(Clone, Copy, Default)] pub struct FILE_BASIC_INFO { pub CreationTime: i64, pub LastAccessTime: i64, @@ -2405,19 +2471,19 @@ pub const FILE_DISPOSITION_FLAG_IGNORE_READONLY_ATTRIBUTE: FILE_DISPOSITION_INFO pub const FILE_DISPOSITION_FLAG_ON_CLOSE: FILE_DISPOSITION_INFO_EX_FLAGS = 8u32; pub const FILE_DISPOSITION_FLAG_POSIX_SEMANTICS: FILE_DISPOSITION_INFO_EX_FLAGS = 2u32; #[repr(C)] -#[derive(Clone, Copy)] +#[derive(Clone, Copy, Default)] pub struct FILE_DISPOSITION_INFO { pub DeleteFile: bool, } #[repr(C)] -#[derive(Clone, Copy)] +#[derive(Clone, Copy, Default)] pub struct FILE_DISPOSITION_INFO_EX { pub Flags: FILE_DISPOSITION_INFO_EX_FLAGS, } pub type FILE_DISPOSITION_INFO_EX_FLAGS = u32; pub const FILE_END: SET_FILE_POINTER_MOVE_METHOD = 2u32; #[repr(C)] -#[derive(Clone, Copy)] +#[derive(Clone, Copy, Default)] pub struct FILE_END_OF_FILE_INFO { pub EndOfFile: i64, } @@ -2457,9 +2523,14 @@ pub struct FILE_ID_BOTH_DIR_INFO { pub FileId: i64, pub FileName: [u16; 1], } +impl Default for FILE_ID_BOTH_DIR_INFO { + fn default() -> Self { + unsafe { core::mem::zeroed() } + } +} pub type FILE_INFO_BY_HANDLE_CLASS = i32; #[repr(C)] -#[derive(Clone, Copy)] +#[derive(Clone, Copy, Default)] pub struct FILE_IO_PRIORITY_HINT_INFO { pub PriorityHint: PRIORITY_HINT, } @@ -2494,12 +2565,22 @@ pub struct FILE_RENAME_INFO { pub FileNameLength: u32, pub FileName: [u16; 1], } +impl Default for FILE_RENAME_INFO { + fn default() -> Self { + unsafe { core::mem::zeroed() } + } +} #[repr(C)] #[derive(Clone, Copy)] pub union FILE_RENAME_INFO_0 { pub ReplaceIfExists: bool, pub Flags: u32, } +impl Default for FILE_RENAME_INFO_0 { + fn default() -> Self { + unsafe { core::mem::zeroed() } + } +} pub const FILE_RESERVE_OPFILTER: NTCREATEFILE_CREATE_OPTIONS = 1048576u32; pub const FILE_SEQUENTIAL_ONLY: NTCREATEFILE_CREATE_OPTIONS = 4u32; pub const FILE_SESSION_AWARE: NTCREATEFILE_CREATE_OPTIONS = 262144u32; @@ -2509,7 +2590,7 @@ pub const FILE_SHARE_NONE: FILE_SHARE_MODE = 0u32; pub const FILE_SHARE_READ: FILE_SHARE_MODE = 1u32; pub const FILE_SHARE_WRITE: FILE_SHARE_MODE = 2u32; #[repr(C)] -#[derive(Clone, Copy)] +#[derive(Clone, Copy, Default)] pub struct FILE_STANDARD_INFO { pub AllocationSize: i64, pub EndOfFile: i64, @@ -2549,6 +2630,12 @@ pub struct FLOATING_SAVE_AREA { pub RegisterArea: [u8; 80], pub Spare0: u32, } +#[cfg(target_arch = "x86")] +impl Default for FLOATING_SAVE_AREA { + fn default() -> Self { + unsafe { core::mem::zeroed() } + } +} #[repr(C)] #[cfg(any(target_arch = "aarch64", target_arch = "arm64ec", target_arch = "x86_64"))] #[derive(Clone, Copy)] @@ -2563,6 +2650,12 @@ pub struct FLOATING_SAVE_AREA { pub RegisterArea: [u8; 80], pub Cr0NpxState: u32, } +#[cfg(any(target_arch = "aarch64", target_arch = "arm64ec", target_arch = "x86_64"))] +impl Default for FLOATING_SAVE_AREA { + fn default() -> Self { + unsafe { core::mem::zeroed() } + } +} pub const FORMAT_MESSAGE_ALLOCATE_BUFFER: FORMAT_MESSAGE_OPTIONS = 256u32; pub const FORMAT_MESSAGE_ARGUMENT_ARRAY: FORMAT_MESSAGE_OPTIONS = 8192u32; pub const FORMAT_MESSAGE_FROM_HMODULE: FORMAT_MESSAGE_OPTIONS = 2048u32; @@ -2639,12 +2732,22 @@ pub const IDLE_PRIORITY_CLASS: PROCESS_CREATION_FLAGS = 64u32; pub struct IN6_ADDR { pub u: IN6_ADDR_0, } +impl Default for IN6_ADDR { + fn default() -> Self { + unsafe { core::mem::zeroed() } + } +} #[repr(C)] #[derive(Clone, Copy)] pub union IN6_ADDR_0 { pub Byte: [u8; 16], pub Word: [u16; 8], } +impl Default for IN6_ADDR_0 { + fn default() -> Self { + unsafe { core::mem::zeroed() } + } +} pub const INFINITE: u32 = 4294967295u32; pub const INHERIT_CALLER_PRIORITY: PROCESS_CREATION_FLAGS = 131072u32; pub const INHERIT_PARENT_AFFINITY: PROCESS_CREATION_FLAGS = 65536u32; @@ -2653,6 +2756,11 @@ pub const INHERIT_PARENT_AFFINITY: PROCESS_CREATION_FLAGS = 65536u32; pub union INIT_ONCE { pub Ptr: *mut core::ffi::c_void, } +impl Default for INIT_ONCE { + fn default() -> Self { + unsafe { core::mem::zeroed() } + } +} pub const INIT_ONCE_INIT_FAILED: u32 = 4u32; pub const INVALID_FILE_ATTRIBUTES: u32 = 4294967295u32; pub const INVALID_SOCKET: SOCKET = -1i32 as _; @@ -2661,6 +2769,11 @@ pub const INVALID_SOCKET: SOCKET = -1i32 as _; pub struct IN_ADDR { pub S_un: IN_ADDR_0, } +impl Default for IN_ADDR { + fn default() -> Self { + unsafe { core::mem::zeroed() } + } +} #[repr(C)] #[derive(Clone, Copy)] pub union IN_ADDR_0 { @@ -2668,8 +2781,13 @@ pub union IN_ADDR_0 { pub S_un_w: IN_ADDR_0_1, pub S_addr: u32, } +impl Default for IN_ADDR_0 { + fn default() -> Self { + unsafe { core::mem::zeroed() } + } +} #[repr(C)] -#[derive(Clone, Copy)] +#[derive(Clone, Copy, Default)] pub struct IN_ADDR_0_0 { pub s_b1: u8, pub s_b2: u8, @@ -2677,7 +2795,7 @@ pub struct IN_ADDR_0_0 { pub s_b4: u8, } #[repr(C)] -#[derive(Clone, Copy)] +#[derive(Clone, Copy, Default)] pub struct IN_ADDR_0_1 { pub s_w1: u16, pub s_w2: u16, @@ -2690,12 +2808,22 @@ pub struct IO_STATUS_BLOCK { pub Anonymous: IO_STATUS_BLOCK_0, pub Information: usize, } +impl Default for IO_STATUS_BLOCK { + fn default() -> Self { + unsafe { core::mem::zeroed() } + } +} #[repr(C)] #[derive(Clone, Copy)] pub union IO_STATUS_BLOCK_0 { pub Status: NTSTATUS, pub Pointer: *mut core::ffi::c_void, } +impl Default for IO_STATUS_BLOCK_0 { + fn default() -> Self { + unsafe { core::mem::zeroed() } + } +} pub type IPPROTO = i32; pub const IPPROTO_AH: IPPROTO = 51i32; pub const IPPROTO_CBT: IPPROTO = 7i32; @@ -2742,6 +2870,11 @@ pub struct IPV6_MREQ { pub ipv6mr_multiaddr: IN6_ADDR, pub ipv6mr_interface: u32, } +impl Default for IPV6_MREQ { + fn default() -> Self { + unsafe { core::mem::zeroed() } + } +} pub const IPV6_MULTICAST_LOOP: i32 = 11i32; pub const IPV6_V6ONLY: i32 = 27i32; pub const IP_ADD_MEMBERSHIP: i32 = 12i32; @@ -2752,11 +2885,16 @@ pub struct IP_MREQ { pub imr_multiaddr: IN_ADDR, pub imr_interface: IN_ADDR, } +impl Default for IP_MREQ { + fn default() -> Self { + unsafe { core::mem::zeroed() } + } +} pub const IP_MULTICAST_LOOP: i32 = 11i32; pub const IP_MULTICAST_TTL: i32 = 10i32; pub const IP_TTL: i32 = 4i32; #[repr(C)] -#[derive(Clone, Copy)] +#[derive(Clone, Copy, Default)] pub struct LINGER { pub l_onoff: u16, pub l_linger: u16, @@ -2797,7 +2935,7 @@ pub type LPWSAOVERLAPPED_COMPLETION_ROUTINE = Option< ), >; #[repr(C)] -#[derive(Clone, Copy)] +#[derive(Clone, Copy, Default)] pub struct M128A { pub Low: u64, pub High: i64, @@ -2838,6 +2976,11 @@ pub struct OBJECT_ATTRIBUTES { pub SecurityDescriptor: *const SECURITY_DESCRIPTOR, pub SecurityQualityOfService: *const SECURITY_QUALITY_OF_SERVICE, } +impl Default for OBJECT_ATTRIBUTES { + fn default() -> Self { + unsafe { core::mem::zeroed() } + } +} pub type OBJECT_ATTRIBUTE_FLAGS = u32; pub const OBJ_DONT_REPARSE: OBJECT_ATTRIBUTE_FLAGS = 4096u32; pub const OPEN_ALWAYS: FILE_CREATION_DISPOSITION = 4u32; @@ -2850,14 +2993,24 @@ pub struct OVERLAPPED { pub Anonymous: OVERLAPPED_0, pub hEvent: HANDLE, } +impl Default for OVERLAPPED { + fn default() -> Self { + unsafe { core::mem::zeroed() } + } +} #[repr(C)] #[derive(Clone, Copy)] pub union OVERLAPPED_0 { pub Anonymous: OVERLAPPED_0_0, pub Pointer: *mut core::ffi::c_void, } +impl Default for OVERLAPPED_0 { + fn default() -> Self { + unsafe { core::mem::zeroed() } + } +} #[repr(C)] -#[derive(Clone, Copy)] +#[derive(Clone, Copy, Default)] pub struct OVERLAPPED_0_0 { pub Offset: u32, pub OffsetHigh: u32, @@ -2895,6 +3048,11 @@ pub struct PROCESS_INFORMATION { pub dwProcessId: u32, pub dwThreadId: u32, } +impl Default for PROCESS_INFORMATION { + fn default() -> Self { + unsafe { core::mem::zeroed() } + } +} pub const PROCESS_MODE_BACKGROUND_BEGIN: PROCESS_CREATION_FLAGS = 1048576u32; pub const PROCESS_MODE_BACKGROUND_END: PROCESS_CREATION_FLAGS = 2097152u32; pub const PROFILE_KERNEL: PROCESS_CREATION_FLAGS = 536870912u32; @@ -2926,6 +3084,11 @@ pub struct SECURITY_ATTRIBUTES { pub lpSecurityDescriptor: *mut core::ffi::c_void, pub bInheritHandle: BOOL, } +impl Default for SECURITY_ATTRIBUTES { + fn default() -> Self { + unsafe { core::mem::zeroed() } + } +} pub const SECURITY_CONTEXT_TRACKING: FILE_FLAGS_AND_ATTRIBUTES = 262144u32; pub const SECURITY_DELEGATION: FILE_FLAGS_AND_ATTRIBUTES = 196608u32; #[repr(C)] @@ -2939,13 +3102,18 @@ pub struct SECURITY_DESCRIPTOR { pub Sacl: *mut ACL, pub Dacl: *mut ACL, } +impl Default for SECURITY_DESCRIPTOR { + fn default() -> Self { + unsafe { core::mem::zeroed() } + } +} pub type SECURITY_DESCRIPTOR_CONTROL = u16; pub const SECURITY_EFFECTIVE_ONLY: FILE_FLAGS_AND_ATTRIBUTES = 524288u32; pub const SECURITY_IDENTIFICATION: FILE_FLAGS_AND_ATTRIBUTES = 65536u32; pub const SECURITY_IMPERSONATION: FILE_FLAGS_AND_ATTRIBUTES = 131072u32; pub type SECURITY_IMPERSONATION_LEVEL = i32; #[repr(C)] -#[derive(Clone, Copy)] +#[derive(Clone, Copy, Default)] pub struct SECURITY_QUALITY_OF_SERVICE { pub Length: u32, pub ImpersonationLevel: SECURITY_IMPERSONATION_LEVEL, @@ -2962,6 +3130,11 @@ pub struct SOCKADDR { pub sa_family: ADDRESS_FAMILY, pub sa_data: [i8; 14], } +impl Default for SOCKADDR { + fn default() -> Self { + unsafe { core::mem::zeroed() } + } +} #[repr(C)] #[derive(Clone, Copy)] pub struct SOCKADDR_STORAGE { @@ -2970,12 +3143,22 @@ pub struct SOCKADDR_STORAGE { pub __ss_align: i64, pub __ss_pad2: [i8; 112], } +impl Default for SOCKADDR_STORAGE { + fn default() -> Self { + unsafe { core::mem::zeroed() } + } +} #[repr(C)] #[derive(Clone, Copy)] pub struct SOCKADDR_UN { pub sun_family: ADDRESS_FAMILY, pub sun_path: [i8; 108], } +impl Default for SOCKADDR_UN { + fn default() -> Self { + unsafe { core::mem::zeroed() } + } +} pub type SOCKET = usize; pub const SOCKET_ERROR: i32 = -1i32; pub const SOCK_DGRAM: WINSOCK_SOCKET_TYPE = 2i32; @@ -2995,6 +3178,11 @@ pub const SPECIFIC_RIGHTS_ALL: FILE_ACCESS_RIGHTS = 65535u32; pub struct SRWLOCK { pub Ptr: *mut core::ffi::c_void, } +impl Default for SRWLOCK { + fn default() -> Self { + unsafe { core::mem::zeroed() } + } +} pub const STACK_SIZE_PARAM_IS_A_RESERVATION: THREAD_CREATION_FLAGS = 65536u32; pub const STANDARD_RIGHTS_ALL: FILE_ACCESS_RIGHTS = 2031616u32; pub const STANDARD_RIGHTS_EXECUTE: FILE_ACCESS_RIGHTS = 131072u32; @@ -3021,6 +3209,11 @@ pub struct STARTUPINFOEXW { pub StartupInfo: STARTUPINFOW, pub lpAttributeList: LPPROC_THREAD_ATTRIBUTE_LIST, } +impl Default for STARTUPINFOEXW { + fn default() -> Self { + unsafe { core::mem::zeroed() } + } +} #[repr(C)] #[derive(Clone, Copy)] pub struct STARTUPINFOW { @@ -3043,6 +3236,11 @@ pub struct STARTUPINFOW { pub hStdOutput: HANDLE, pub hStdError: HANDLE, } +impl Default for STARTUPINFOW { + fn default() -> Self { + unsafe { core::mem::zeroed() } + } +} pub type STARTUPINFOW_FLAGS = u32; pub const STATUS_DELETE_PENDING: NTSTATUS = 0xC0000056_u32 as _; pub const STATUS_DIRECTORY_NOT_EMPTY: NTSTATUS = 0xC0000101_u32 as _; @@ -3078,14 +3276,24 @@ pub struct SYSTEM_INFO { pub wProcessorLevel: u16, pub wProcessorRevision: u16, } +impl Default for SYSTEM_INFO { + fn default() -> Self { + unsafe { core::mem::zeroed() } + } +} #[repr(C)] #[derive(Clone, Copy)] pub union SYSTEM_INFO_0 { pub dwOemId: u32, pub Anonymous: SYSTEM_INFO_0_0, } +impl Default for SYSTEM_INFO_0 { + fn default() -> Self { + unsafe { core::mem::zeroed() } + } +} #[repr(C)] -#[derive(Clone, Copy)] +#[derive(Clone, Copy, Default)] pub struct SYSTEM_INFO_0_0 { pub wProcessorArchitecture: PROCESSOR_ARCHITECTURE, pub wReserved: u16, @@ -3097,7 +3305,7 @@ pub type THREAD_CREATION_FLAGS = u32; pub const TIMER_ALL_ACCESS: SYNCHRONIZATION_ACCESS_RIGHTS = 2031619u32; pub const TIMER_MODIFY_STATE: SYNCHRONIZATION_ACCESS_RIGHTS = 2u32; #[repr(C)] -#[derive(Clone, Copy)] +#[derive(Clone, Copy, Default)] pub struct TIMEVAL { pub tv_sec: i32, pub tv_usec: i32, @@ -3134,6 +3342,11 @@ pub struct UNICODE_STRING { pub MaximumLength: u16, pub Buffer: PWSTR, } +impl Default for UNICODE_STRING { + fn default() -> Self { + unsafe { core::mem::zeroed() } + } +} pub const VOLUME_NAME_DOS: GETFINALPATHNAMEBYHANDLE_FLAGS = 0u32; pub const VOLUME_NAME_GUID: GETFINALPATHNAMEBYHANDLE_FLAGS = 1u32; pub const VOLUME_NAME_NONE: GETFINALPATHNAMEBYHANDLE_FLAGS = 4u32; @@ -3160,6 +3373,11 @@ pub struct WIN32_FIND_DATAW { pub cFileName: [u16; 260], pub cAlternateFileName: [u16; 14], } +impl Default for WIN32_FIND_DATAW { + fn default() -> Self { + unsafe { core::mem::zeroed() } + } +} pub type WINSOCK_SHUTDOWN_HOW = i32; pub type WINSOCK_SOCKET_TYPE = i32; pub const WRITE_DAC: FILE_ACCESS_RIGHTS = 262144u32; @@ -3171,6 +3389,11 @@ pub struct WSABUF { pub len: u32, pub buf: PSTR, } +impl Default for WSABUF { + fn default() -> Self { + unsafe { core::mem::zeroed() } + } +} #[repr(C)] #[cfg(target_arch = "x86")] #[derive(Clone, Copy)] @@ -3183,6 +3406,12 @@ pub struct WSADATA { pub iMaxUdpDg: u16, pub lpVendorInfo: PSTR, } +#[cfg(target_arch = "x86")] +impl Default for WSADATA { + fn default() -> Self { + unsafe { core::mem::zeroed() } + } +} #[repr(C)] #[cfg(any(target_arch = "aarch64", target_arch = "arm64ec", target_arch = "x86_64"))] #[derive(Clone, Copy)] @@ -3195,6 +3424,12 @@ pub struct WSADATA { pub szDescription: [i8; 257], pub szSystemStatus: [i8; 129], } +#[cfg(any(target_arch = "aarch64", target_arch = "arm64ec", target_arch = "x86_64"))] +impl Default for WSADATA { + fn default() -> Self { + unsafe { core::mem::zeroed() } + } +} pub const WSAEACCES: WSA_ERROR = 10013i32; pub const WSAEADDRINUSE: WSA_ERROR = 10048i32; pub const WSAEADDRNOTAVAIL: WSA_ERROR = 10049i32; @@ -3255,6 +3490,11 @@ pub struct WSAPROTOCOLCHAIN { pub ChainLen: i32, pub ChainEntries: [u32; 7], } +impl Default for WSAPROTOCOLCHAIN { + fn default() -> Self { + unsafe { core::mem::zeroed() } + } +} #[repr(C)] #[derive(Clone, Copy)] pub struct WSAPROTOCOL_INFOW { @@ -3279,6 +3519,11 @@ pub struct WSAPROTOCOL_INFOW { pub dwProviderReserved: u32, pub szProtocol: [u16; 256], } +impl Default for WSAPROTOCOL_INFOW { + fn default() -> Self { + unsafe { core::mem::zeroed() } + } +} pub const WSASERVICE_NOT_FOUND: WSA_ERROR = 10108i32; pub const WSASYSCALLFAILURE: WSA_ERROR = 10107i32; pub const WSASYSNOTREADY: WSA_ERROR = 10091i32; @@ -3348,6 +3593,12 @@ pub struct XSAVE_FORMAT { pub XmmRegisters: [M128A; 8], pub Reserved4: [u8; 224], } +#[cfg(target_arch = "x86")] +impl Default for XSAVE_FORMAT { + fn default() -> Self { + unsafe { core::mem::zeroed() } + } +} #[repr(C)] #[cfg(any(target_arch = "aarch64", target_arch = "arm64ec", target_arch = "x86_64"))] #[derive(Clone, Copy)] @@ -3369,6 +3620,12 @@ pub struct XSAVE_FORMAT { pub XmmRegisters: [M128A; 16], pub Reserved4: [u8; 96], } +#[cfg(any(target_arch = "aarch64", target_arch = "arm64ec", target_arch = "x86_64"))] +impl Default for XSAVE_FORMAT { + fn default() -> Self { + unsafe { core::mem::zeroed() } + } +} #[cfg(target_arch = "arm")] #[repr(C)] diff --git a/library/std/src/sys/pal/windows/compat.rs b/library/std/src/sys/pal/windows/compat.rs index 2b9838437e9..14f2c8d881c 100644 --- a/library/std/src/sys/pal/windows/compat.rs +++ b/library/std/src/sys/pal/windows/compat.rs @@ -145,7 +145,7 @@ macro_rules! compat_fn_with_fallback { use super::*; use crate::mem; use crate::ffi::CStr; - use crate::sync::atomic::{AtomicPtr, Ordering}; + use crate::sync::atomic::{Atomic, AtomicPtr, Ordering}; use crate::sys::compat::Module; type F = unsafe extern "system" fn($($argtype),*) -> $rettype; @@ -155,7 +155,7 @@ macro_rules! compat_fn_with_fallback { /// When that is called it attempts to load the requested symbol. /// If it succeeds, `PTR` is set to the address of that symbol. /// If it fails, then `PTR` is set to `fallback`. - static PTR: AtomicPtr<c_void> = AtomicPtr::new(load as *mut _); + static PTR: Atomic<*mut c_void> = AtomicPtr::new(load as *mut _); unsafe extern "system" fn load($($argname: $argtype),*) -> $rettype { unsafe { @@ -212,9 +212,9 @@ macro_rules! compat_fn_optional { use crate::ffi::c_void; use crate::mem; use crate::ptr::{self, NonNull}; - use crate::sync::atomic::{AtomicPtr, Ordering}; + use crate::sync::atomic::{Atomic, AtomicPtr, Ordering}; - pub(in crate::sys) static PTR: AtomicPtr<c_void> = AtomicPtr::new(ptr::null_mut()); + pub(in crate::sys) static PTR: Atomic<*mut c_void> = AtomicPtr::new(ptr::null_mut()); type F = unsafe extern "system" fn($($argtype),*) $(-> $rettype)?; diff --git a/library/std/src/sys/pal/windows/env.rs b/library/std/src/sys/pal/windows/env.rs deleted file mode 100644 index f0a99d6200c..00000000000 --- a/library/std/src/sys/pal/windows/env.rs +++ /dev/null @@ -1,9 +0,0 @@ -pub mod os { - pub const FAMILY: &str = "windows"; - pub const OS: &str = "windows"; - pub const DLL_PREFIX: &str = ""; - pub const DLL_SUFFIX: &str = ".dll"; - pub const DLL_EXTENSION: &str = "dll"; - pub const EXE_SUFFIX: &str = ".exe"; - pub const EXE_EXTENSION: &str = "exe"; -} diff --git a/library/std/src/sys/pal/windows/futex.rs b/library/std/src/sys/pal/windows/futex.rs index aebf638239c..cfa0a6b3815 100644 --- a/library/std/src/sys/pal/windows/futex.rs +++ b/library/std/src/sys/pal/windows/futex.rs @@ -1,8 +1,8 @@ use core::ffi::c_void; use core::ptr; use core::sync::atomic::{ - AtomicBool, AtomicI8, AtomicI16, AtomicI32, AtomicI64, AtomicIsize, AtomicPtr, AtomicU8, - AtomicU16, AtomicU32, AtomicU64, AtomicUsize, + Atomic, AtomicBool, AtomicI8, AtomicI16, AtomicI32, AtomicI64, AtomicIsize, AtomicPtr, + AtomicU8, AtomicU16, AtomicU32, AtomicU64, AtomicUsize, }; use core::time::Duration; @@ -10,12 +10,12 @@ use super::api::{self, WinError}; use crate::sys::{c, dur2timeout}; /// An atomic for use as a futex that is at least 32-bits but may be larger -pub type Futex = AtomicU32; +pub type Futex = Atomic<Primitive>; /// Must be the underlying type of Futex pub type Primitive = u32; /// An atomic for use as a futex that is at least 8-bits but may be larger. -pub type SmallFutex = AtomicU8; +pub type SmallFutex = Atomic<SmallPrimitive>; /// Must be the underlying type of SmallFutex pub type SmallPrimitive = u8; @@ -47,10 +47,10 @@ unsafe_waitable_int! { (usize, AtomicUsize), } unsafe impl<T> Waitable for *const T { - type Futex = AtomicPtr<T>; + type Futex = Atomic<*mut T>; } unsafe impl<T> Waitable for *mut T { - type Futex = AtomicPtr<T>; + type Futex = Atomic<*mut T>; } unsafe impl<T> Futexable for AtomicPtr<T> {} diff --git a/library/std/src/sys/pal/windows/mod.rs b/library/std/src/sys/pal/windows/mod.rs index bdf0cc2c59c..4f18c4009ab 100644 --- a/library/std/src/sys/pal/windows/mod.rs +++ b/library/std/src/sys/pal/windows/mod.rs @@ -14,9 +14,7 @@ pub mod compat; pub mod api; -pub mod args; pub mod c; -pub mod env; #[cfg(not(target_vendor = "win7"))] pub mod futex; pub mod handle; diff --git a/library/std/src/sys/pal/windows/os.rs b/library/std/src/sys/pal/windows/os.rs index 044dc2e8cd8..f331282d2d7 100644 --- a/library/std/src/sys/pal/windows/os.rs +++ b/library/std/src/sys/pal/windows/os.rs @@ -5,16 +5,16 @@ #[cfg(test)] mod tests; +use super::api; #[cfg(not(target_vendor = "uwp"))] use super::api::WinError; -use super::{api, to_u16s}; use crate::error::Error as StdError; use crate::ffi::{OsStr, OsString}; use crate::os::windows::ffi::EncodeWide; use crate::os::windows::prelude::*; use crate::path::{self, PathBuf}; -use crate::sys::{c, cvt}; -use crate::{fmt, io, ptr, slice}; +use crate::sys::pal::{c, cvt}; +use crate::{fmt, io, ptr}; pub fn errno() -> i32 { api::get_last_error().code as i32 @@ -76,108 +76,6 @@ pub fn error_string(mut errnum: i32) -> String { } } -pub struct Env { - base: *mut c::WCHAR, - iter: EnvIterator, -} - -// FIXME(https://github.com/rust-lang/rust/issues/114583): Remove this when <OsStr as Debug>::fmt matches <str as Debug>::fmt. -pub struct EnvStrDebug<'a> { - iter: &'a EnvIterator, -} - -impl fmt::Debug for EnvStrDebug<'_> { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - let Self { iter } = self; - let iter: EnvIterator = (*iter).clone(); - let mut list = f.debug_list(); - for (a, b) in iter { - list.entry(&(a.to_str().unwrap(), b.to_str().unwrap())); - } - list.finish() - } -} - -impl Env { - pub fn str_debug(&self) -> impl fmt::Debug + '_ { - let Self { base: _, iter } = self; - EnvStrDebug { iter } - } -} - -impl fmt::Debug for Env { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - let Self { base: _, iter } = self; - f.debug_list().entries(iter.clone()).finish() - } -} - -impl Iterator for Env { - type Item = (OsString, OsString); - - fn next(&mut self) -> Option<(OsString, OsString)> { - let Self { base: _, iter } = self; - iter.next() - } -} - -#[derive(Clone)] -struct EnvIterator(*mut c::WCHAR); - -impl Iterator for EnvIterator { - type Item = (OsString, OsString); - - fn next(&mut self) -> Option<(OsString, OsString)> { - let Self(cur) = self; - loop { - unsafe { - if **cur == 0 { - return None; - } - let p = *cur as *const u16; - let mut len = 0; - while *p.add(len) != 0 { - len += 1; - } - let s = slice::from_raw_parts(p, len); - *cur = cur.add(len + 1); - - // Windows allows environment variables to start with an equals - // symbol (in any other position, this is the separator between - // variable name and value). Since`s` has at least length 1 at - // this point (because the empty string terminates the array of - // environment variables), we can safely slice. - let pos = match s[1..].iter().position(|&u| u == b'=' as u16).map(|p| p + 1) { - Some(p) => p, - None => continue, - }; - return Some(( - OsStringExt::from_wide(&s[..pos]), - OsStringExt::from_wide(&s[pos + 1..]), - )); - } - } - } -} - -impl Drop for Env { - fn drop(&mut self) { - unsafe { - c::FreeEnvironmentStringsW(self.base); - } - } -} - -pub fn env() -> Env { - unsafe { - let ch = c::GetEnvironmentStringsW(); - if ch.is_null() { - panic!("failure getting env string from OS: {}", io::Error::last_os_error()); - } - Env { base: ch, iter: EnvIterator(ch) } - } -} - pub struct SplitPaths<'a> { data: EncodeWide<'a>, must_yield: bool, @@ -290,33 +188,6 @@ pub fn chdir(p: &path::Path) -> io::Result<()> { cvt(unsafe { c::SetCurrentDirectoryW(p.as_ptr()) }).map(drop) } -pub fn getenv(k: &OsStr) -> Option<OsString> { - let k = to_u16s(k).ok()?; - super::fill_utf16_buf( - |buf, sz| unsafe { c::GetEnvironmentVariableW(k.as_ptr(), buf, sz) }, - OsStringExt::from_wide, - ) - .ok() -} - -pub unsafe fn setenv(k: &OsStr, v: &OsStr) -> io::Result<()> { - // SAFETY: We ensure that k and v are null-terminated wide strings. - unsafe { - let k = to_u16s(k)?; - let v = to_u16s(v)?; - - cvt(c::SetEnvironmentVariableW(k.as_ptr(), v.as_ptr())).map(drop) - } -} - -pub unsafe fn unsetenv(n: &OsStr) -> io::Result<()> { - // SAFETY: We ensure that v is a null-terminated wide strings. - unsafe { - let v = to_u16s(n)?; - cvt(c::SetEnvironmentVariableW(v.as_ptr(), ptr::null())).map(drop) - } -} - pub fn temp_dir() -> PathBuf { super::fill_utf16_buf(|buf, sz| unsafe { c::GetTempPath2W(sz, buf) }, super::os2path).unwrap() } diff --git a/library/std/src/sys/pal/windows/pipe.rs b/library/std/src/sys/pal/windows/pipe.rs index 7fd62339619..00d469fbaf8 100644 --- a/library/std/src/sys/pal/windows/pipe.rs +++ b/library/std/src/sys/pal/windows/pipe.rs @@ -3,8 +3,8 @@ use crate::io::{self, BorrowedCursor, IoSlice, IoSliceMut}; use crate::os::windows::prelude::*; use crate::path::Path; use crate::random::{DefaultRandomSource, Random}; -use crate::sync::atomic::AtomicUsize; use crate::sync::atomic::Ordering::Relaxed; +use crate::sync::atomic::{Atomic, AtomicUsize}; use crate::sys::c; use crate::sys::fs::{File, OpenOptions}; use crate::sys::handle::Handle; @@ -192,7 +192,7 @@ pub fn spawn_pipe_relay( } fn random_number() -> usize { - static N: AtomicUsize = AtomicUsize::new(0); + static N: Atomic<usize> = AtomicUsize::new(0); loop { if N.load(Relaxed) != 0 { return N.fetch_add(1, Relaxed); diff --git a/library/std/src/sys/pal/windows/time.rs b/library/std/src/sys/pal/windows/time.rs index d9010e39961..68126bd8d2f 100644 --- a/library/std/src/sys/pal/windows/time.rs +++ b/library/std/src/sys/pal/windows/time.rs @@ -164,7 +164,7 @@ fn intervals2dur(intervals: u64) -> Duration { mod perf_counter { use super::NANOS_PER_SEC; - use crate::sync::atomic::{AtomicU64, Ordering}; + use crate::sync::atomic::{Atomic, AtomicU64, Ordering}; use crate::sys::{c, cvt}; use crate::sys_common::mul_div_u64; use crate::time::Duration; @@ -199,7 +199,7 @@ mod perf_counter { // uninitialized. Storing this as a single `AtomicU64` allows us to use // `Relaxed` operations, as we are only interested in the effects on a // single memory location. - static FREQUENCY: AtomicU64 = AtomicU64::new(0); + static FREQUENCY: Atomic<u64> = AtomicU64::new(0); let cached = FREQUENCY.load(Ordering::Relaxed); // If a previous thread has filled in this global state, use that. diff --git a/library/std/src/sys/pal/xous/args.rs b/library/std/src/sys/pal/xous/args.rs deleted file mode 100644 index 00c44ca220a..00000000000 --- a/library/std/src/sys/pal/xous/args.rs +++ /dev/null @@ -1,53 +0,0 @@ -use crate::ffi::OsString; -use crate::sys::pal::xous::os::get_application_parameters; -use crate::sys::pal::xous::os::params::ArgumentList; -use crate::{fmt, vec}; - -pub struct Args { - parsed_args_list: vec::IntoIter<OsString>, -} - -pub fn args() -> Args { - let Some(params) = get_application_parameters() else { - return Args { parsed_args_list: vec![].into_iter() }; - }; - - for param in params { - if let Ok(args) = ArgumentList::try_from(¶m) { - let mut parsed_args = vec![]; - for arg in args { - parsed_args.push(arg.into()); - } - return Args { parsed_args_list: parsed_args.into_iter() }; - } - } - Args { parsed_args_list: vec![].into_iter() } -} - -impl fmt::Debug for Args { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - self.parsed_args_list.as_slice().fmt(f) - } -} - -impl Iterator for Args { - type Item = OsString; - fn next(&mut self) -> Option<OsString> { - self.parsed_args_list.next() - } - fn size_hint(&self) -> (usize, Option<usize>) { - self.parsed_args_list.size_hint() - } -} - -impl DoubleEndedIterator for Args { - fn next_back(&mut self) -> Option<OsString> { - self.parsed_args_list.next_back() - } -} - -impl ExactSizeIterator for Args { - fn len(&self) -> usize { - self.parsed_args_list.len() - } -} diff --git a/library/std/src/sys/pal/xous/mod.rs b/library/std/src/sys/pal/xous/mod.rs index 58926e2beb1..383d031ed43 100644 --- a/library/std/src/sys/pal/xous/mod.rs +++ b/library/std/src/sys/pal/xous/mod.rs @@ -1,8 +1,5 @@ #![forbid(unsafe_op_in_unsafe_fn)] -pub mod args; -#[path = "../unsupported/env.rs"] -pub mod env; pub mod os; #[path = "../unsupported/pipe.rs"] pub mod pipe; diff --git a/library/std/src/sys/pal/xous/os.rs b/library/std/src/sys/pal/xous/os.rs index 2c87e7d91f2..2230dabe096 100644 --- a/library/std/src/sys/pal/xous/os.rs +++ b/library/std/src/sys/pal/xous/os.rs @@ -1,17 +1,15 @@ use super::unsupported; -use crate::collections::HashMap; use crate::error::Error as StdError; use crate::ffi::{OsStr, OsString}; use crate::marker::PhantomData; use crate::os::xous::ffi::Error as XousError; use crate::path::{self, PathBuf}; -use crate::sync::atomic::{AtomicPtr, AtomicUsize, Ordering}; -use crate::sync::{Mutex, Once}; -use crate::{fmt, io, vec}; +use crate::sync::atomic::{Atomic, AtomicPtr, Ordering}; +use crate::{fmt, io}; pub(crate) mod params; -static PARAMS_ADDRESS: AtomicPtr<u8> = AtomicPtr::new(core::ptr::null_mut()); +static PARAMS_ADDRESS: Atomic<*mut u8> = AtomicPtr::new(core::ptr::null_mut()); #[cfg(not(test))] #[cfg(feature = "panic_unwind")] @@ -136,100 +134,6 @@ pub(crate) fn get_application_parameters() -> Option<params::ApplicationParamete unsafe { params::ApplicationParameters::new_from_ptr(params_address) } } -// ---------- Environment handling ---------- // -static ENV: AtomicUsize = AtomicUsize::new(0); -static ENV_INIT: Once = Once::new(); -type EnvStore = Mutex<HashMap<OsString, OsString>>; - -fn get_env_store() -> &'static EnvStore { - ENV_INIT.call_once(|| { - let env_store = EnvStore::default(); - if let Some(params) = get_application_parameters() { - for param in params { - if let Ok(envs) = params::EnvironmentBlock::try_from(¶m) { - let mut env_store = env_store.lock().unwrap(); - for env in envs { - env_store.insert(env.key.into(), env.value.into()); - } - break; - } - } - } - ENV.store(Box::into_raw(Box::new(env_store)) as _, Ordering::Relaxed) - }); - unsafe { &*core::ptr::with_exposed_provenance::<EnvStore>(ENV.load(Ordering::Relaxed)) } -} - -pub struct Env { - iter: vec::IntoIter<(OsString, OsString)>, -} - -// FIXME(https://github.com/rust-lang/rust/issues/114583): Remove this when <OsStr as Debug>::fmt matches <str as Debug>::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 <OsStr as Debug>::fmt matches <str as Debug>::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<usize>) { - self.iter.size_hint() - } -} - -pub fn env() -> Env { - let clone_to_vec = |map: &HashMap<OsString, OsString>| -> 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 } -} - -pub fn getenv(k: &OsStr) -> Option<OsString> { - get_env_store().lock().unwrap().get(k).cloned() -} - -pub unsafe fn setenv(k: &OsStr, v: &OsStr) -> io::Result<()> { - let (k, v) = (k.to_owned(), v.to_owned()); - get_env_store().lock().unwrap().insert(k, v); - Ok(()) -} - -pub unsafe fn unsetenv(k: &OsStr) -> io::Result<()> { - get_env_store().lock().unwrap().remove(k); - Ok(()) -} - pub fn temp_dir() -> PathBuf { panic!("no filesystem on this platform") } diff --git a/library/std/src/sys/pal/zkvm/env.rs b/library/std/src/sys/pal/zkvm/env.rs deleted file mode 100644 index b85153642b1..00000000000 --- a/library/std/src/sys/pal/zkvm/env.rs +++ /dev/null @@ -1,9 +0,0 @@ -pub mod os { - pub const FAMILY: &str = ""; - pub const OS: &str = ""; - pub const DLL_PREFIX: &str = ""; - pub const DLL_SUFFIX: &str = ".elf"; - pub const DLL_EXTENSION: &str = "elf"; - pub const EXE_SUFFIX: &str = ".elf"; - pub const EXE_EXTENSION: &str = "elf"; -} diff --git a/library/std/src/sys/pal/zkvm/mod.rs b/library/std/src/sys/pal/zkvm/mod.rs index 4659dad16e8..e1efa240685 100644 --- a/library/std/src/sys/pal/zkvm/mod.rs +++ b/library/std/src/sys/pal/zkvm/mod.rs @@ -8,12 +8,9 @@ //! will likely change over time. #![forbid(unsafe_op_in_unsafe_fn)] -const WORD_SIZE: usize = size_of::<u32>(); +pub const WORD_SIZE: usize = size_of::<u32>(); pub mod abi; -#[path = "../zkvm/args.rs"] -pub mod args; -pub mod env; pub mod os; #[path = "../unsupported/pipe.rs"] pub mod pipe; diff --git a/library/std/src/sys/pal/zkvm/os.rs b/library/std/src/sys/pal/zkvm/os.rs index 868b19e33b6..a8ef97ecf67 100644 --- a/library/std/src/sys/pal/zkvm/os.rs +++ b/library/std/src/sys/pal/zkvm/os.rs @@ -1,10 +1,8 @@ -use super::{WORD_SIZE, abi, unsupported}; +use super::unsupported; use crate::error::Error as StdError; use crate::ffi::{OsStr, OsString}; use crate::marker::PhantomData; use crate::path::{self, PathBuf}; -use crate::sys::os_str; -use crate::sys_common::FromInner; use crate::{fmt, io}; pub fn errno() -> i32 { @@ -64,64 +62,6 @@ pub fn current_exe() -> io::Result<PathBuf> { unsupported() } -pub struct Env(!); - -impl Iterator for Env { - type Item = (OsString, OsString); - fn next(&mut self) -> Option<(OsString, OsString)> { - self.0 - } -} - -pub fn env() -> Env { - panic!("not supported on this platform") -} - -impl Env { - pub fn str_debug(&self) -> impl fmt::Debug + '_ { - let Self(inner) = self; - match *inner {} - } -} - -impl fmt::Debug for Env { - fn fmt(&self, _: &mut fmt::Formatter<'_>) -> fmt::Result { - let Self(inner) = self; - match *inner {} - } -} - -pub fn getenv(varname: &OsStr) -> Option<OsString> { - let varname = varname.as_encoded_bytes(); - let nbytes = - unsafe { abi::sys_getenv(crate::ptr::null_mut(), 0, varname.as_ptr(), varname.len()) }; - if nbytes == usize::MAX { - return None; - } - - let nwords = (nbytes + WORD_SIZE - 1) / WORD_SIZE; - let words = unsafe { abi::sys_alloc_words(nwords) }; - - let nbytes2 = unsafe { abi::sys_getenv(words, nwords, varname.as_ptr(), varname.len()) }; - debug_assert_eq!(nbytes, nbytes2); - - // Convert to OsString. - // - // FIXME: We can probably get rid of the extra copy here if we - // reimplement "os_str" instead of just using the generic unix - // "os_str". - let u8s: &[u8] = unsafe { crate::slice::from_raw_parts(words.cast() as *const u8, nbytes) }; - Some(OsString::from_inner(os_str::Buf { inner: u8s.to_vec() })) -} - -pub unsafe fn setenv(_: &OsStr, _: &OsStr) -> io::Result<()> { - Err(io::const_error!(io::ErrorKind::Unsupported, "cannot set env vars on this platform")) -} - -pub unsafe fn unsetenv(_: &OsStr) -> io::Result<()> { - Err(io::const_error!(io::ErrorKind::Unsupported, "cannot unset env vars on this platform")) -} - pub fn temp_dir() -> PathBuf { panic!("no filesystem on this platform") } diff --git a/library/std/src/sys/path/windows.rs b/library/std/src/sys/path/windows.rs index 6547ed9aa5f..e0e003f6a81 100644 --- a/library/std/src/sys/path/windows.rs +++ b/library/std/src/sys/path/windows.rs @@ -10,6 +10,40 @@ mod tests; pub const MAIN_SEP_STR: &str = "\\"; pub const MAIN_SEP: char = '\\'; +/// A null terminated wide string. +#[repr(transparent)] +pub struct WCStr([u16]); + +impl WCStr { + /// Convert a slice to a WCStr without checks. + /// + /// Though it is memory safe, the slice should also not contain interior nulls + /// as this may lead to unwanted truncation. + /// + /// # Safety + /// + /// The slice must end in a null. + pub unsafe fn from_wchars_with_null_unchecked(s: &[u16]) -> &Self { + unsafe { &*(s as *const [u16] as *const Self) } + } + + pub fn as_ptr(&self) -> *const u16 { + self.0.as_ptr() + } + + pub fn count_bytes(&self) -> usize { + self.0.len() + } +} + +#[inline] +pub fn with_native_path<T>(path: &Path, f: &dyn Fn(&WCStr) -> io::Result<T>) -> io::Result<T> { + let path = maybe_verbatim(path)?; + // SAFETY: maybe_verbatim returns null-terminated strings + let path = unsafe { WCStr::from_wchars_with_null_unchecked(&path) }; + f(path) +} + #[inline] pub fn is_sep_byte(b: u8) -> bool { b == b'/' || b == b'\\' diff --git a/library/std/src/sys/process/uefi.rs b/library/std/src/sys/process/uefi.rs index b46418ae9bb..5f922292d05 100644 --- a/library/std/src/sys/process/uefi.rs +++ b/library/std/src/sys/process/uefi.rs @@ -1,4 +1,4 @@ -use r_efi::protocols::simple_text_output; +use r_efi::protocols::{simple_text_input, simple_text_output}; use crate::collections::BTreeMap; pub use crate::ffi::OsString as EnvKey; @@ -23,6 +23,7 @@ pub struct Command { args: Vec<OsString>, stdout: Option<Stdio>, stderr: Option<Stdio>, + stdin: Option<Stdio>, env: CommandEnv, } @@ -48,6 +49,7 @@ impl Command { args: Vec::new(), stdout: None, stderr: None, + stdin: None, env: Default::default(), } } @@ -64,8 +66,8 @@ impl Command { panic!("unsupported") } - pub fn stdin(&mut self, _stdin: Stdio) { - panic!("unsupported") + pub fn stdin(&mut self, stdin: Stdio) { + self.stdin = Some(stdin); } pub fn stdout(&mut self, stdout: Stdio) { @@ -122,6 +124,22 @@ impl Command { } } + fn create_stdin( + s: Stdio, + ) -> io::Result<Option<helpers::OwnedProtocol<uefi_command_internal::InputProtocol>>> { + match s { + Stdio::Null => unsafe { + helpers::OwnedProtocol::create( + uefi_command_internal::InputProtocol::null(), + simple_text_input::PROTOCOL_GUID, + ) + } + .map(Some), + Stdio::Inherit => Ok(None), + Stdio::MakePipe => unsupported(), + } + } + pub fn output(&mut self) -> io::Result<(ExitStatus, Vec<u8>, Vec<u8>)> { let mut cmd = uefi_command_internal::Image::load_image(&self.prog)?; @@ -149,6 +167,15 @@ impl Command { cmd.stderr_inherit() }; + // Setup Stdin + let stdin = self.stdin.unwrap_or(Stdio::Null); + let stdin = Self::create_stdin(stdin)?; + if let Some(con) = stdin { + cmd.stdin_init(con) + } else { + cmd.stdin_inherit() + }; + let env = env_changes(&self.env); // Set any new vars @@ -334,7 +361,7 @@ impl<'a> fmt::Debug for CommandArgs<'a> { #[allow(dead_code)] mod uefi_command_internal { - use r_efi::protocols::{loaded_image, simple_text_output}; + use r_efi::protocols::{loaded_image, simple_text_input, simple_text_output}; use crate::ffi::{OsStr, OsString}; use crate::io::{self, const_error}; @@ -350,6 +377,7 @@ mod uefi_command_internal { handle: NonNull<crate::ffi::c_void>, stdout: Option<helpers::OwnedProtocol<PipeProtocol>>, stderr: Option<helpers::OwnedProtocol<PipeProtocol>>, + stdin: Option<helpers::OwnedProtocol<InputProtocol>>, st: OwnedTable<r_efi::efi::SystemTable>, args: Option<(*mut u16, usize)>, } @@ -384,7 +412,14 @@ mod uefi_command_internal { helpers::open_protocol(child_handle, loaded_image::PROTOCOL_GUID).unwrap(); let st = OwnedTable::from_table(unsafe { (*loaded_image.as_ptr()).system_table }); - Ok(Self { handle: child_handle, stdout: None, stderr: None, st, args: None }) + Ok(Self { + handle: child_handle, + stdout: None, + stderr: None, + stdin: None, + st, + args: None, + }) } } @@ -445,6 +480,17 @@ mod uefi_command_internal { } } + fn set_stdin( + &mut self, + handle: r_efi::efi::Handle, + protocol: *mut simple_text_input::Protocol, + ) { + unsafe { + (*self.st.as_mut_ptr()).console_in_handle = handle; + (*self.st.as_mut_ptr()).con_in = protocol; + } + } + pub fn stdout_init(&mut self, protocol: helpers::OwnedProtocol<PipeProtocol>) { self.set_stdout( protocol.handle().as_ptr(), @@ -471,6 +517,19 @@ mod uefi_command_internal { unsafe { self.set_stderr((*st.as_ptr()).standard_error_handle, (*st.as_ptr()).std_err) } } + pub(crate) fn stdin_init(&mut self, protocol: helpers::OwnedProtocol<InputProtocol>) { + self.set_stdin( + protocol.handle().as_ptr(), + protocol.as_ref() as *const InputProtocol as *mut simple_text_input::Protocol, + ); + self.stdin = Some(protocol); + } + + pub(crate) fn stdin_inherit(&mut self) { + let st: NonNull<r_efi::efi::SystemTable> = system_table().cast(); + unsafe { self.set_stdin((*st.as_ptr()).console_in_handle, (*st.as_ptr()).con_in) } + } + pub fn stderr(&self) -> io::Result<Vec<u8>> { match &self.stderr { Some(stderr) => stderr.as_ref().utf8(), @@ -722,6 +781,56 @@ mod uefi_command_internal { } } + #[repr(C)] + pub(crate) struct InputProtocol { + reset: simple_text_input::ProtocolReset, + read_key_stroke: simple_text_input::ProtocolReadKeyStroke, + wait_for_key: r_efi::efi::Event, + } + + impl InputProtocol { + pub(crate) fn null() -> Self { + let evt = helpers::OwnedEvent::new( + r_efi::efi::EVT_NOTIFY_WAIT, + r_efi::efi::TPL_CALLBACK, + Some(Self::empty_notify), + None, + ) + .unwrap(); + + Self { + reset: Self::null_reset, + read_key_stroke: Self::null_read_key, + wait_for_key: evt.into_raw(), + } + } + + extern "efiapi" fn null_reset( + _: *mut simple_text_input::Protocol, + _: r_efi::efi::Boolean, + ) -> r_efi::efi::Status { + r_efi::efi::Status::SUCCESS + } + + extern "efiapi" fn null_read_key( + _: *mut simple_text_input::Protocol, + _: *mut simple_text_input::InputKey, + ) -> r_efi::efi::Status { + r_efi::efi::Status::UNSUPPORTED + } + + extern "efiapi" fn empty_notify(_: r_efi::efi::Event, _: *mut crate::ffi::c_void) {} + } + + impl Drop for InputProtocol { + fn drop(&mut self) { + // Close wait_for_key + unsafe { + let _ = helpers::OwnedEvent::from_raw(self.wait_for_key); + } + } + } + pub fn create_args(prog: &OsStr, args: &[OsString]) -> Box<[u16]> { const QUOTE: u16 = 0x0022; const SPACE: u16 = 0x0020; diff --git a/library/std/src/sys/process/unix/unix.rs b/library/std/src/sys/process/unix/unix.rs index 191a09c8da9..ae1c9558281 100644 --- a/library/std/src/sys/process/unix/unix.rs +++ b/library/std/src/sys/process/unix/unix.rs @@ -88,7 +88,7 @@ impl Command { // in its own process. Thus the parent drops the lock guard immediately. // The child calls `mem::forget` to leak the lock, which is crucial because // releasing a lock is not async-signal-safe. - let env_lock = sys::os::env_read_lock(); + let env_lock = sys::env::env_read_lock(); let pid = unsafe { self.do_fork()? }; if pid == 0 { @@ -237,7 +237,7 @@ impl Command { // Similar to when forking, we want to ensure that access to // the environment is synchronized, so make sure to grab the // environment lock before we try to exec. - let _lock = sys::os::env_read_lock(); + let _lock = sys::env::env_read_lock(); let Err(e) = self.do_exec(theirs, envp.as_ref()); e @@ -386,13 +386,13 @@ impl Command { impl Drop for Reset { fn drop(&mut self) { unsafe { - *sys::os::environ() = self.0; + *sys::env::environ() = self.0; } } } - _reset = Some(Reset(*sys::os::environ())); - *sys::os::environ() = envp.as_ptr(); + _reset = Some(Reset(*sys::env::environ())); + *sys::env::environ() = envp.as_ptr(); } libc::execvp(self.get_program_cstr().as_ptr(), self.get_argv().as_ptr()); @@ -415,6 +415,7 @@ impl Command { all(target_os = "linux", target_env = "musl"), target_os = "nto", target_vendor = "apple", + target_os = "cygwin", )))] fn posix_spawn( &mut self, @@ -433,17 +434,15 @@ impl Command { all(target_os = "linux", target_env = "musl"), target_os = "nto", target_vendor = "apple", + target_os = "cygwin", ))] - // FIXME(#115199): Rust currently omits weak function definitions - // and its metadata from LLVM IR. - #[cfg_attr(target_os = "linux", no_sanitize(cfi))] fn posix_spawn( &mut self, stdio: &ChildPipes, envp: Option<&CStringArray>, ) -> io::Result<Option<Process>> { #[cfg(target_os = "linux")] - use core::sync::atomic::{AtomicU8, Ordering}; + use core::sync::atomic::{Atomic, AtomicU8, Ordering}; use crate::mem::MaybeUninit; use crate::sys::{self, cvt_nz, on_broken_pipe_flag_used}; @@ -476,7 +475,7 @@ impl Command { fn pidfd_getpid(pidfd: libc::c_int) -> libc::c_int; ); - static PIDFD_SUPPORTED: AtomicU8 = AtomicU8::new(0); + static PIDFD_SUPPORTED: Atomic<u8> = AtomicU8::new(0); const UNKNOWN: u8 = 0; const SPAWN: u8 = 1; // Obtaining a pidfd via the fork+exec path might work @@ -587,7 +586,7 @@ impl Command { /// Some platforms can set a new working directory for a spawned process in the /// `posix_spawn` path. This function looks up the function pointer for adding /// such an action to a `posix_spawn_file_actions_t` struct. - #[cfg(not(all(target_os = "linux", target_env = "musl")))] + #[cfg(not(any(all(target_os = "linux", target_env = "musl"), target_os = "cygwin")))] fn get_posix_spawn_addchdir() -> Option<PosixSpawnAddChdirFn> { use crate::sys::weak::weak; @@ -621,7 +620,9 @@ impl Command { /// Weak symbol lookup doesn't work with statically linked libcs, so in cases /// where static linking is possible we need to either check for the presence /// of the symbol at compile time or know about it upfront. - #[cfg(all(target_os = "linux", target_env = "musl"))] + /// + /// Cygwin doesn't support weak symbol, so just link it. + #[cfg(any(all(target_os = "linux", target_env = "musl"), target_os = "cygwin"))] fn get_posix_spawn_addchdir() -> Option<PosixSpawnAddChdirFn> { // Our minimum required musl supports this function, so we can just use it. Some(libc::posix_spawn_file_actions_addchdir_np) @@ -738,8 +739,8 @@ impl Command { cvt_nz(libc::posix_spawnattr_setflags(attrs.0.as_mut_ptr(), flags as _))?; // Make sure we synchronize access to the global `environ` resource - let _env_lock = sys::os::env_read_lock(); - let envp = envp.map(|c| c.as_ptr()).unwrap_or_else(|| *sys::os::environ() as *const _); + let _env_lock = sys::env::env_read_lock(); + let envp = envp.map(|c| c.as_ptr()).unwrap_or_else(|| *sys::env::environ() as *const _); #[cfg(not(target_os = "nto"))] let spawn_fn = libc::posix_spawnp; diff --git a/library/std/src/sys/process/unix/vxworks.rs b/library/std/src/sys/process/unix/vxworks.rs index 5f1727789a1..b92446f0cf6 100644 --- a/library/std/src/sys/process/unix/vxworks.rs +++ b/library/std/src/sys/process/unix/vxworks.rs @@ -67,7 +67,7 @@ impl Command { let c_envp = envp .as_ref() .map(|c| c.as_ptr()) - .unwrap_or_else(|| *sys::os::environ() as *const _); + .unwrap_or_else(|| *sys::env::environ() as *const _); let stack_size = crate::cmp::max( crate::env::var_os("RUST_MIN_STACK") .and_then(|s| s.to_str().and_then(|s| s.parse().ok())) @@ -76,7 +76,7 @@ impl Command { ); // ensure that access to the environment is synchronized - let _lock = sys::os::env_read_lock(); + let _lock = sys::env::env_read_lock(); let ret = libc::rtpSpawn( self.get_program_cstr().as_ptr(), diff --git a/library/std/src/sys/random/linux.rs b/library/std/src/sys/random/linux.rs index c0591ec0c15..18196fae28b 100644 --- a/library/std/src/sys/random/linux.rs +++ b/library/std/src/sys/random/linux.rs @@ -64,8 +64,8 @@ use crate::fs::File; use crate::io::Read; use crate::os::fd::AsRawFd; use crate::sync::OnceLock; -use crate::sync::atomic::AtomicBool; use crate::sync::atomic::Ordering::{Acquire, Relaxed, Release}; +use crate::sync::atomic::{Atomic, AtomicBool}; use crate::sys::pal::os::errno; use crate::sys::pal::weak::syscall; @@ -81,9 +81,9 @@ fn getrandom(mut bytes: &mut [u8], insecure: bool) { ) -> libc::ssize_t; ); - static GETRANDOM_AVAILABLE: AtomicBool = AtomicBool::new(true); - static GRND_INSECURE_AVAILABLE: AtomicBool = AtomicBool::new(true); - static URANDOM_READY: AtomicBool = AtomicBool::new(false); + static GETRANDOM_AVAILABLE: Atomic<bool> = AtomicBool::new(true); + static GRND_INSECURE_AVAILABLE: Atomic<bool> = AtomicBool::new(true); + static URANDOM_READY: Atomic<bool> = AtomicBool::new(false); static DEVICE: OnceLock<File> = OnceLock::new(); if GETRANDOM_AVAILABLE.load(Relaxed) { diff --git a/library/std/src/sys/random/vxworks.rs b/library/std/src/sys/random/vxworks.rs index d549ccebdb2..14f02e8ecd2 100644 --- a/library/std/src/sys/random/vxworks.rs +++ b/library/std/src/sys/random/vxworks.rs @@ -1,7 +1,7 @@ -use crate::sync::atomic::AtomicBool; use crate::sync::atomic::Ordering::Relaxed; +use crate::sync::atomic::{Atomic, AtomicBool}; -static RNG_INIT: AtomicBool = AtomicBool::new(false); +static RNG_INIT: Atomic<bool> = AtomicBool::new(false); pub fn fill_bytes(mut bytes: &mut [u8]) { while !RNG_INIT.load(Relaxed) { diff --git a/library/std/src/sys/stdio/uefi.rs b/library/std/src/sys/stdio/uefi.rs index 257e321dd03..ccd6bf658b0 100644 --- a/library/std/src/sys/stdio/uefi.rs +++ b/library/std/src/sys/stdio/uefi.rs @@ -142,8 +142,12 @@ impl io::Write for Stderr { // UTF-16 character should occupy 4 bytes at most in UTF-8 pub const STDIN_BUF_SIZE: usize = 4; -pub fn is_ebadf(_err: &io::Error) -> bool { - false +pub fn is_ebadf(err: &io::Error) -> bool { + if let Some(x) = err.raw_os_error() { + r_efi::efi::Status::UNSUPPORTED.as_usize() == x + } else { + false + } } pub fn panic_output() -> Option<impl io::Write> { diff --git a/library/std/src/sys/sync/condvar/pthread.rs b/library/std/src/sys/sync/condvar/pthread.rs index 5bb7431eecf..938b7071b88 100644 --- a/library/std/src/sys/sync/condvar/pthread.rs +++ b/library/std/src/sys/sync/condvar/pthread.rs @@ -2,15 +2,15 @@ use crate::pin::Pin; use crate::ptr; -use crate::sync::atomic::AtomicUsize; use crate::sync::atomic::Ordering::Relaxed; +use crate::sync::atomic::{Atomic, AtomicUsize}; use crate::sys::pal::sync as pal; use crate::sys::sync::{Mutex, OnceBox}; use crate::time::{Duration, Instant}; pub struct Condvar { cvar: OnceBox<pal::Condvar>, - mutex: AtomicUsize, + mutex: Atomic<usize>, } impl Condvar { diff --git a/library/std/src/sys/sync/condvar/xous.rs b/library/std/src/sys/sync/condvar/xous.rs index b9e5f47abfc..21a1587214a 100644 --- a/library/std/src/sys/sync/condvar/xous.rs +++ b/library/std/src/sys/sync/condvar/xous.rs @@ -1,4 +1,4 @@ -use core::sync::atomic::{AtomicUsize, Ordering}; +use core::sync::atomic::{Atomic, AtomicUsize, Ordering}; use crate::os::xous::ffi::{blocking_scalar, scalar}; use crate::os::xous::services::{TicktimerScalar, ticktimer_server}; @@ -11,8 +11,8 @@ use crate::time::Duration; const NOTIFY_TRIES: usize = 3; pub struct Condvar { - counter: AtomicUsize, - timed_out: AtomicUsize, + counter: Atomic<usize>, + timed_out: Atomic<usize>, } unsafe impl Send for Condvar {} diff --git a/library/std/src/sys/sync/mutex/fuchsia.rs b/library/std/src/sys/sync/mutex/fuchsia.rs index 3e871285bea..3d388a4564a 100644 --- a/library/std/src/sys/sync/mutex/fuchsia.rs +++ b/library/std/src/sys/sync/mutex/fuchsia.rs @@ -37,8 +37,8 @@ //! //! [mutex in Fuchsia's libsync]: https://cs.opensource.google/fuchsia/fuchsia/+/main:zircon/system/ulib/sync/mutex.c -use crate::sync::atomic::AtomicU32; use crate::sync::atomic::Ordering::{Acquire, Relaxed, Release}; +use crate::sync::atomic::{Atomic, AtomicU32}; use crate::sys::futex::zircon::{ ZX_ERR_BAD_HANDLE, ZX_ERR_BAD_STATE, ZX_ERR_INVALID_ARGS, ZX_ERR_TIMED_OUT, ZX_ERR_WRONG_TYPE, ZX_OK, ZX_TIME_INFINITE, zx_futex_wait, zx_futex_wake_single_owner, zx_handle_t, @@ -52,7 +52,7 @@ const CONTESTED_BIT: u32 = 1; const UNLOCKED: u32 = 0; pub struct Mutex { - futex: AtomicU32, + futex: Atomic<u32>, } #[inline] diff --git a/library/std/src/sys/sync/mutex/xous.rs b/library/std/src/sys/sync/mutex/xous.rs index c6b954c1711..d16faa5aea3 100644 --- a/library/std/src/sys/sync/mutex/xous.rs +++ b/library/std/src/sys/sync/mutex/xous.rs @@ -1,7 +1,7 @@ use crate::os::xous::ffi::{blocking_scalar, do_yield}; use crate::os::xous::services::{TicktimerScalar, ticktimer_server}; use crate::sync::atomic::Ordering::{Acquire, Relaxed, Release}; -use crate::sync::atomic::{AtomicBool, AtomicUsize}; +use crate::sync::atomic::{Atomic, AtomicBool, AtomicUsize}; pub struct Mutex { /// The "locked" value indicates how many threads are waiting on this @@ -14,12 +14,12 @@ pub struct Mutex { /// for a lock, or it is locked for long periods of time. Rather than /// spinning, these locks send a Message to the ticktimer server /// requesting that they be woken up when a lock is unlocked. - locked: AtomicUsize, + locked: Atomic<usize>, /// Whether this Mutex ever was contended, and therefore made a trip /// to the ticktimer server. If this was never set, then we were never /// on the slow path and can skip deregistering the mutex. - contended: AtomicBool, + contended: Atomic<bool>, } impl Mutex { diff --git a/library/std/src/sys/sync/once/queue.rs b/library/std/src/sys/sync/once/queue.rs index fde1e0ca510..6a2ab0dcf1b 100644 --- a/library/std/src/sys/sync/once/queue.rs +++ b/library/std/src/sys/sync/once/queue.rs @@ -57,7 +57,7 @@ use crate::cell::Cell; use crate::sync::atomic::Ordering::{AcqRel, Acquire, Release}; -use crate::sync::atomic::{AtomicBool, AtomicPtr}; +use crate::sync::atomic::{Atomic, AtomicBool, AtomicPtr}; use crate::sync::poison::once::ExclusiveState; use crate::thread::{self, Thread}; use crate::{fmt, ptr, sync as public}; @@ -65,7 +65,7 @@ use crate::{fmt, ptr, sync as public}; type StateAndQueue = *mut (); pub struct Once { - state_and_queue: AtomicPtr<()>, + state_and_queue: Atomic<*mut ()>, } pub struct OnceState { @@ -94,7 +94,7 @@ const QUEUE_MASK: usize = !STATE_MASK; #[repr(align(4))] // Ensure the two lower bits are free to use as state bits. struct Waiter { thread: Thread, - signaled: AtomicBool, + signaled: Atomic<bool>, next: Cell<*const Waiter>, } @@ -102,7 +102,7 @@ struct Waiter { // Every node is a struct on the stack of a waiting thread. // Will wake up the waiters when it gets dropped, i.e. also on panic. struct WaiterQueue<'a> { - state_and_queue: &'a AtomicPtr<()>, + state_and_queue: &'a Atomic<*mut ()>, set_state_on_drop_to: StateAndQueue, } @@ -232,7 +232,7 @@ impl Once { } fn wait( - state_and_queue: &AtomicPtr<()>, + state_and_queue: &Atomic<*mut ()>, mut current: StateAndQueue, return_on_poisoned: bool, ) -> StateAndQueue { diff --git a/library/std/src/sys/sync/once_box.rs b/library/std/src/sys/sync/once_box.rs index 6953b91999a..088f51aae78 100644 --- a/library/std/src/sys/sync/once_box.rs +++ b/library/std/src/sys/sync/once_box.rs @@ -8,11 +8,11 @@ use crate::mem::replace; use crate::pin::Pin; use crate::ptr::null_mut; -use crate::sync::atomic::AtomicPtr; use crate::sync::atomic::Ordering::{Acquire, Relaxed, Release}; +use crate::sync::atomic::{Atomic, AtomicPtr}; pub(crate) struct OnceBox<T> { - ptr: AtomicPtr<T>, + ptr: Atomic<*mut T>, } impl<T> OnceBox<T> { diff --git a/library/std/src/sys/sync/rwlock/queue.rs b/library/std/src/sys/sync/rwlock/queue.rs index bd15f8ee952..62f084acfd2 100644 --- a/library/std/src/sys/sync/rwlock/queue.rs +++ b/library/std/src/sys/sync/rwlock/queue.rs @@ -117,11 +117,11 @@ use crate::hint::spin_loop; use crate::mem; use crate::ptr::{self, NonNull, null_mut, without_provenance_mut}; use crate::sync::atomic::Ordering::{AcqRel, Acquire, Relaxed, Release}; -use crate::sync::atomic::{AtomicBool, AtomicPtr}; +use crate::sync::atomic::{Atomic, AtomicBool, AtomicPtr}; use crate::thread::{self, Thread}; /// The atomic lock state. -type AtomicState = AtomicPtr<()>; +type AtomicState = Atomic<State>; /// The inner lock state. type State = *mut (); @@ -181,11 +181,11 @@ struct Node { tail: AtomicLink, write: bool, thread: OnceCell<Thread>, - completed: AtomicBool, + completed: Atomic<bool>, } /// An atomic node pointer with relaxed operations. -struct AtomicLink(AtomicPtr<Node>); +struct AtomicLink(Atomic<*mut Node>); impl AtomicLink { fn new(v: Option<NonNull<Node>>) -> AtomicLink { diff --git a/library/std/src/sys/sync/thread_parking/darwin.rs b/library/std/src/sys/sync/thread_parking/darwin.rs index a0d24a91e7c..b9bcc538c65 100644 --- a/library/std/src/sys/sync/thread_parking/darwin.rs +++ b/library/std/src/sys/sync/thread_parking/darwin.rs @@ -13,8 +13,8 @@ #![allow(non_camel_case_types)] use crate::pin::Pin; -use crate::sync::atomic::AtomicI8; use crate::sync::atomic::Ordering::{Acquire, Release}; +use crate::sync::atomic::{Atomic, AtomicI8}; use crate::time::Duration; type dispatch_semaphore_t = *mut crate::ffi::c_void; @@ -38,7 +38,7 @@ const PARKED: i8 = -1; pub struct Parker { semaphore: dispatch_semaphore_t, - state: AtomicI8, + state: Atomic<i8>, } unsafe impl Sync for Parker {} diff --git a/library/std/src/sys/sync/thread_parking/id.rs b/library/std/src/sys/sync/thread_parking/id.rs index 64964351837..fcc6ecca628 100644 --- a/library/std/src/sys/sync/thread_parking/id.rs +++ b/library/std/src/sys/sync/thread_parking/id.rs @@ -10,12 +10,12 @@ use crate::cell::UnsafeCell; use crate::pin::Pin; use crate::sync::atomic::Ordering::{Acquire, Relaxed, Release}; -use crate::sync::atomic::{AtomicI8, fence}; +use crate::sync::atomic::{Atomic, AtomicI8, fence}; use crate::sys::thread_parking::{ThreadId, current, park, park_timeout, unpark}; use crate::time::Duration; pub struct Parker { - state: AtomicI8, + state: Atomic<i8>, tid: UnsafeCell<Option<ThreadId>>, } diff --git a/library/std/src/sys/sync/thread_parking/pthread.rs b/library/std/src/sys/sync/thread_parking/pthread.rs index 19cabd7dd75..14bc793c15d 100644 --- a/library/std/src/sys/sync/thread_parking/pthread.rs +++ b/library/std/src/sys/sync/thread_parking/pthread.rs @@ -1,8 +1,8 @@ //! Thread parking without `futex` using the `pthread` synchronization primitives. use crate::pin::Pin; -use crate::sync::atomic::AtomicUsize; use crate::sync::atomic::Ordering::{Acquire, Relaxed, Release}; +use crate::sync::atomic::{Atomic, AtomicUsize}; use crate::sys::pal::sync::{Condvar, Mutex}; use crate::time::Duration; @@ -11,7 +11,7 @@ const PARKED: usize = 1; const NOTIFIED: usize = 2; pub struct Parker { - state: AtomicUsize, + state: Atomic<usize>, lock: Mutex, cvar: Condvar, } diff --git a/library/std/src/sys/sync/thread_parking/windows7.rs b/library/std/src/sys/sync/thread_parking/windows7.rs index a1a0f8427cd..96e94a8053c 100644 --- a/library/std/src/sys/sync/thread_parking/windows7.rs +++ b/library/std/src/sys/sync/thread_parking/windows7.rs @@ -60,13 +60,13 @@ use core::ffi::c_void; use crate::pin::Pin; -use crate::sync::atomic::AtomicI8; use crate::sync::atomic::Ordering::{Acquire, Release}; +use crate::sync::atomic::{Atomic, AtomicI8}; use crate::sys::{c, dur2timeout}; use crate::time::Duration; pub struct Parker { - state: AtomicI8, + state: Atomic<i8>, } const PARKED: i8 = -1; @@ -186,8 +186,8 @@ impl Parker { mod keyed_events { use core::pin::Pin; use core::ptr; - use core::sync::atomic::AtomicPtr; use core::sync::atomic::Ordering::{Acquire, Relaxed}; + use core::sync::atomic::{Atomic, AtomicPtr}; use core::time::Duration; use super::{EMPTY, NOTIFIED, Parker}; @@ -244,7 +244,7 @@ mod keyed_events { fn keyed_event_handle() -> c::HANDLE { const INVALID: c::HANDLE = ptr::without_provenance_mut(!0); - static HANDLE: AtomicPtr<crate::ffi::c_void> = AtomicPtr::new(INVALID); + static HANDLE: Atomic<*mut crate::ffi::c_void> = AtomicPtr::new(INVALID); match HANDLE.load(Relaxed) { INVALID => { let mut handle = c::INVALID_HANDLE_VALUE; diff --git a/library/std/src/sys/sync/thread_parking/xous.rs b/library/std/src/sys/sync/thread_parking/xous.rs index 28c90249dc2..0f451c0ac29 100644 --- a/library/std/src/sys/sync/thread_parking/xous.rs +++ b/library/std/src/sys/sync/thread_parking/xous.rs @@ -2,8 +2,8 @@ use crate::os::xous::ffi::{blocking_scalar, scalar}; use crate::os::xous::services::{TicktimerScalar, ticktimer_server}; use crate::pin::Pin; use crate::ptr; -use crate::sync::atomic::AtomicI8; use crate::sync::atomic::Ordering::{Acquire, Release}; +use crate::sync::atomic::{Atomic, AtomicI8}; use crate::time::Duration; const NOTIFIED: i8 = 1; @@ -11,7 +11,7 @@ const EMPTY: i8 = 0; const PARKED: i8 = -1; pub struct Parker { - state: AtomicI8, + state: Atomic<i8>, } impl Parker { diff --git a/library/std/src/sys/thread_local/destructors/linux_like.rs b/library/std/src/sys/thread_local/destructors/linux_like.rs index 817941229ee..d7cbaeb89f4 100644 --- a/library/std/src/sys/thread_local/destructors/linux_like.rs +++ b/library/std/src/sys/thread_local/destructors/linux_like.rs @@ -12,9 +12,6 @@ use crate::mem::transmute; -// FIXME: The Rust compiler currently omits weakly function definitions (i.e., -// __cxa_thread_atexit_impl) and its metadata from LLVM IR. -#[no_sanitize(cfi, kcfi)] pub unsafe fn register(t: *mut u8, dtor: unsafe extern "C" fn(*mut u8)) { /// This is necessary because the __cxa_thread_atexit_impl implementation /// std links to by default may be a C or C++ implementation that was not diff --git a/library/std/src/sys/thread_local/key/racy.rs b/library/std/src/sys/thread_local/key/racy.rs index e1bc08eabb3..a12ff7ac36b 100644 --- a/library/std/src/sys/thread_local/key/racy.rs +++ b/library/std/src/sys/thread_local/key/racy.rs @@ -6,7 +6,7 @@ //! should be more lightweight and avoids circular dependencies with the rest of //! `std`. -use crate::sync::atomic::{self, AtomicUsize, Ordering}; +use crate::sync::atomic::{Atomic, AtomicUsize, Ordering}; /// A type for TLS keys that are statically allocated. /// @@ -14,7 +14,7 @@ use crate::sync::atomic::{self, AtomicUsize, Ordering}; /// dependencies with the rest of `std`. pub struct LazyKey { /// Inner static TLS key (internals). - key: AtomicUsize, + key: Atomic<usize>, /// Destructor for the TLS value. dtor: Option<unsafe extern "C" fn(*mut u8)>, } @@ -31,7 +31,7 @@ const KEY_SENTVAL: usize = libc::PTHREAD_KEYS_MAX + 1; impl LazyKey { pub const fn new(dtor: Option<unsafe extern "C" fn(*mut u8)>) -> LazyKey { - LazyKey { key: atomic::AtomicUsize::new(KEY_SENTVAL), dtor } + LazyKey { key: AtomicUsize::new(KEY_SENTVAL), dtor } } #[inline] diff --git a/library/std/src/sys/thread_local/key/windows.rs b/library/std/src/sys/thread_local/key/windows.rs index f4e0f25a476..c34c7bc204f 100644 --- a/library/std/src/sys/thread_local/key/windows.rs +++ b/library/std/src/sys/thread_local/key/windows.rs @@ -27,7 +27,7 @@ use crate::cell::UnsafeCell; use crate::ptr; use crate::sync::atomic::Ordering::{AcqRel, Acquire, Relaxed, Release}; -use crate::sync::atomic::{AtomicPtr, AtomicU32}; +use crate::sync::atomic::{Atomic, AtomicPtr, AtomicU32}; use crate::sys::c; use crate::sys::thread_local::guard; @@ -38,9 +38,9 @@ pub struct LazyKey { /// The key value shifted up by one. Since TLS_OUT_OF_INDEXES == u32::MAX /// is not a valid key value, this allows us to use zero as sentinel value /// without risking overflow. - key: AtomicU32, + key: Atomic<Key>, dtor: Option<Dtor>, - next: AtomicPtr<LazyKey>, + next: Atomic<*mut LazyKey>, /// Currently, destructors cannot be unregistered, so we cannot use racy /// initialization for keys. Instead, we need synchronize initialization. /// Use the Windows-provided `Once` since it does not require TLS. @@ -142,7 +142,7 @@ pub unsafe fn get(key: Key) -> *mut u8 { unsafe { c::TlsGetValue(key).cast() } } -static DTORS: AtomicPtr<LazyKey> = AtomicPtr::new(ptr::null_mut()); +static DTORS: Atomic<*mut LazyKey> = AtomicPtr::new(ptr::null_mut()); /// Should only be called once per key, otherwise loops or breaks may occur in /// the linked list. diff --git a/library/std/src/sys/thread_local/key/xous.rs b/library/std/src/sys/thread_local/key/xous.rs index 48dfe17ab32..a27cec5ca1a 100644 --- a/library/std/src/sys/thread_local/key/xous.rs +++ b/library/std/src/sys/thread_local/key/xous.rs @@ -42,7 +42,7 @@ use crate::mem::ManuallyDrop; use crate::os::xous::ffi::{MemoryFlags, map_memory, unmap_memory}; use crate::ptr; use crate::sync::atomic::Ordering::{Acquire, Relaxed, Release}; -use crate::sync::atomic::{AtomicPtr, AtomicUsize}; +use crate::sync::atomic::{Atomic, AtomicPtr, AtomicUsize}; pub type Key = usize; pub type Dtor = unsafe extern "C" fn(*mut u8); @@ -52,19 +52,19 @@ const TLS_MEMORY_SIZE: usize = 4096; /// TLS keys start at `1`. Index `0` is unused #[cfg(not(test))] #[unsafe(export_name = "_ZN16__rust_internals3std3sys4xous16thread_local_key13TLS_KEY_INDEXE")] -static TLS_KEY_INDEX: AtomicUsize = AtomicUsize::new(1); +static TLS_KEY_INDEX: Atomic<usize> = AtomicUsize::new(1); #[cfg(not(test))] #[unsafe(export_name = "_ZN16__rust_internals3std3sys4xous16thread_local_key9DTORSE")] -static DTORS: AtomicPtr<Node> = AtomicPtr::new(ptr::null_mut()); +static DTORS: Atomic<*mut Node> = AtomicPtr::new(ptr::null_mut()); #[cfg(test)] unsafe extern "Rust" { #[link_name = "_ZN16__rust_internals3std3sys4xous16thread_local_key13TLS_KEY_INDEXE"] - static TLS_KEY_INDEX: AtomicUsize; + static TLS_KEY_INDEX: Atomic<usize>; #[link_name = "_ZN16__rust_internals3std3sys4xous16thread_local_key9DTORSE"] - static DTORS: AtomicPtr<Node>; + static DTORS: Atomic<*mut Node>; } fn tls_ptr_addr() -> *mut *mut u8 { diff --git a/library/std/src/thread/local.rs b/library/std/src/thread/local.rs index d5a5d10205d..7cd44873313 100644 --- a/library/std/src/thread/local.rs +++ b/library/std/src/thread/local.rs @@ -22,12 +22,16 @@ use crate::fmt; /// /// Initialization is dynamically performed on the first call to a setter (e.g. /// [`with`]) within a thread, and values that implement [`Drop`] get -/// destructed when a thread exits. Some caveats apply, which are explained below. +/// destructed when a thread exits. Some platform-specific caveats apply, which +/// are explained below. +/// Note that, should the destructor panics, the whole process will be [aborted]. /// /// A `LocalKey`'s initializer cannot recursively depend on itself. Using a /// `LocalKey` in this way may cause panics, aborts or infinite recursion on /// the first call to `with`. /// +/// [aborted]: crate::process::abort +/// /// # Single-thread Synchronization /// /// Though there is no potential race with other threads, it is still possible to diff --git a/library/std/src/thread/mod.rs b/library/std/src/thread/mod.rs index 3f3ba02361c..6838f15e174 100644 --- a/library/std/src/thread/mod.rs +++ b/library/std/src/thread/mod.rs @@ -166,7 +166,7 @@ use crate::mem::{self, ManuallyDrop, forget}; use crate::num::NonZero; use crate::pin::Pin; use crate::sync::Arc; -use crate::sync::atomic::{AtomicUsize, Ordering}; +use crate::sync::atomic::{Atomic, AtomicUsize, Ordering}; use crate::sys::sync::Parker; use crate::sys::thread as imp; use crate::sys_common::{AsInner, IntoInner}; @@ -481,7 +481,7 @@ impl Builder { let Builder { name, stack_size, no_hooks } = self; let stack_size = stack_size.unwrap_or_else(|| { - static MIN: AtomicUsize = AtomicUsize::new(0); + static MIN: Atomic<usize> = AtomicUsize::new(0); match MIN.load(Ordering::Relaxed) { 0 => {} @@ -1195,9 +1195,9 @@ impl ThreadId { cfg_if::cfg_if! { if #[cfg(target_has_atomic = "64")] { - use crate::sync::atomic::AtomicU64; + use crate::sync::atomic::{Atomic, AtomicU64}; - static COUNTER: AtomicU64 = AtomicU64::new(0); + static COUNTER: Atomic<u64> = AtomicU64::new(0); let mut last = COUNTER.load(Ordering::Relaxed); loop { @@ -1302,10 +1302,10 @@ pub(crate) mod main_thread { cfg_if::cfg_if! { if #[cfg(target_has_atomic = "64")] { use super::ThreadId; - use crate::sync::atomic::AtomicU64; + use crate::sync::atomic::{Atomic, AtomicU64}; use crate::sync::atomic::Ordering::Relaxed; - static MAIN: AtomicU64 = AtomicU64::new(0); + static MAIN: Atomic<u64> = AtomicU64::new(0); pub(super) fn get() -> Option<ThreadId> { ThreadId::from_u64(MAIN.load(Relaxed)) @@ -1319,10 +1319,10 @@ pub(crate) mod main_thread { } else { use super::ThreadId; use crate::mem::MaybeUninit; - use crate::sync::atomic::AtomicBool; + use crate::sync::atomic::{Atomic, AtomicBool}; use crate::sync::atomic::Ordering::{Acquire, Release}; - static INIT: AtomicBool = AtomicBool::new(false); + static INIT: Atomic<bool> = AtomicBool::new(false); static mut MAIN: MaybeUninit<ThreadId> = MaybeUninit::uninit(); pub(super) fn get() -> Option<ThreadId> { @@ -1676,6 +1676,7 @@ impl fmt::Debug for Thread { /// [`Result`]: crate::result::Result /// [`std::panic::resume_unwind`]: crate::panic::resume_unwind #[stable(feature = "rust1", since = "1.0.0")] +#[cfg_attr(not(bootstrap), doc(search_unbox))] pub type Result<T> = crate::result::Result<T, Box<dyn Any + Send + 'static>>; // This packet is used to communicate the return value between the spawned diff --git a/library/std/src/thread/scoped.rs b/library/std/src/thread/scoped.rs index 0033fc3a732..a4c0ca5417d 100644 --- a/library/std/src/thread/scoped.rs +++ b/library/std/src/thread/scoped.rs @@ -2,7 +2,7 @@ use super::{Builder, JoinInner, Result, Thread, current_or_unnamed}; use crate::marker::PhantomData; use crate::panic::{AssertUnwindSafe, catch_unwind, resume_unwind}; use crate::sync::Arc; -use crate::sync::atomic::{AtomicBool, AtomicUsize, Ordering}; +use crate::sync::atomic::{Atomic, AtomicBool, AtomicUsize, Ordering}; use crate::{fmt, io}; /// A scope to spawn scoped threads in. @@ -35,8 +35,8 @@ pub struct Scope<'scope, 'env: 'scope> { pub struct ScopedJoinHandle<'scope, T>(JoinInner<'scope, T>); pub(super) struct ScopeData { - num_running_threads: AtomicUsize, - a_thread_panicked: AtomicBool, + num_running_threads: Atomic<usize>, + a_thread_panicked: Atomic<bool>, main_thread: Thread, } diff --git a/library/std/src/time.rs b/library/std/src/time.rs index 5ab71413586..03af35e809c 100644 --- a/library/std/src/time.rs +++ b/library/std/src/time.rs @@ -205,8 +205,8 @@ pub struct Instant(time::Instant); /// println!("{}", elapsed.as_secs()); /// } /// Err(e) => { -/// // an error occurred! -/// println!("Error: {e:?}"); +/// // the system clock went backwards! +/// println!("Great Scott! {e:?}"); /// } /// } /// } @@ -245,6 +245,7 @@ pub struct Instant(time::Instant); /// > structure cannot represent the new point in time. /// /// [`add`]: SystemTime::add +/// [`UNIX_EPOCH`]: SystemTime::UNIX_EPOCH #[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)] #[stable(feature = "time2", since = "1.8.0")] pub struct SystemTime(time::SystemTime); |
