diff options
| author | Ben Kimock <kimockb@gmail.com> | 2024-11-09 06:57:05 +0000 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2024-11-09 06:57:05 +0000 |
| commit | c272bb4ec0a09744bef47fbe15ac6cded53d0216 (patch) | |
| tree | 0c85c9634f6ff5ec409a9589eb9636d8a1d435b9 /library/std | |
| parent | d7aceeea71d4d32c7db671d39a448aa051bc90f6 (diff) | |
| parent | 15d883e5b73ce6758926d8e3ef4a307f9ac6092f (diff) | |
| download | rust-c272bb4ec0a09744bef47fbe15ac6cded53d0216.tar.gz rust-c272bb4ec0a09744bef47fbe15ac6cded53d0216.zip | |
Merge pull request #4019 from rust-lang/rustup-2024-11-09
Automatic Rustup
Diffstat (limited to 'library/std')
| -rw-r--r-- | library/std/Cargo.toml | 6 | ||||
| -rw-r--r-- | library/std/build.rs | 19 | ||||
| -rw-r--r-- | library/std/src/collections/hash/map/tests.rs | 26 | ||||
| -rw-r--r-- | library/std/src/f128/tests.rs | 22 | ||||
| -rw-r--r-- | library/std/src/ffi/os_str.rs | 27 | ||||
| -rw-r--r-- | library/std/src/hash/random.rs | 3 | ||||
| -rw-r--r-- | library/std/src/lib.rs | 12 | ||||
| -rw-r--r-- | library/std/src/os/darwin/fs.rs | 17 | ||||
| -rw-r--r-- | library/std/src/os/darwin/mod.rs | 5 | ||||
| -rw-r--r-- | library/std/src/os/ios/mod.rs | 2 | ||||
| -rw-r--r-- | library/std/src/os/macos/mod.rs | 2 | ||||
| -rw-r--r-- | library/std/src/os/mod.rs | 24 | ||||
| -rw-r--r-- | library/std/src/os/unix/mod.rs | 2 | ||||
| -rw-r--r-- | library/std/src/os/unix/process.rs | 2 | ||||
| -rw-r--r-- | library/std/src/path.rs | 28 | ||||
| -rw-r--r-- | library/std/src/sync/lazy_lock.rs | 4 | ||||
| -rw-r--r-- | library/std/src/sync/mpmc/list.rs | 8 | ||||
| -rw-r--r-- | library/std/src/sys/alloc/windows.rs | 69 |
18 files changed, 173 insertions, 105 deletions
diff --git a/library/std/Cargo.toml b/library/std/Cargo.toml index 9b66fc8f921..b732fdf1696 100644 --- a/library/std/Cargo.toml +++ b/library/std/Cargo.toml @@ -17,15 +17,11 @@ cfg-if = { version = "1.0", features = ['rustc-dep-of-std'] } panic_unwind = { path = "../panic_unwind", optional = true } panic_abort = { path = "../panic_abort" } core = { path = "../core", public = true } -compiler_builtins = { version = "0.1.136" } +compiler_builtins = { version = "=0.1.138" } unwind = { path = "../unwind" } hashbrown = { version = "0.15", default-features = false, features = [ 'rustc-dep-of-std', ] } -# FIXME(#127890): `object` depends on `memchr`, but `memchr` > v2.5 causes -# issues with LTO. This dependency is not used directly, but pin it here so -# it resolves to 2.5. To be removed once rust-lang/rust#127890 is fixed. -memchr = { version = "=2.5.0", default-features = false, features = ["rustc-dep-of-std"] } std_detect = { path = "../stdarch/crates/std_detect", default-features = false, features = [ 'rustc-dep-of-std', ] } diff --git a/library/std/build.rs b/library/std/build.rs index 032326556bd..8dc326a3dde 100644 --- a/library/std/build.rs +++ b/library/std/build.rs @@ -122,19 +122,24 @@ fn main() { _ if is_miri => true, // Unsupported <https://github.com/llvm/llvm-project/issues/94434> ("arm64ec", _) => false, - // ABI and precision bugs <https://github.com/rust-lang/rust/issues/125109> - // <https://github.com/rust-lang/rust/issues/125102> - ("powerpc" | "powerpc64", _) => false, + // Selection bug <https://github.com/llvm/llvm-project/issues/96432> + ("mips64" | "mips64r6", _) => false, // Selection bug <https://github.com/llvm/llvm-project/issues/95471> ("nvptx64", _) => false, + // ABI bugs <https://github.com/rust-lang/rust/issues/125109> et al. (full + // list at <https://github.com/rust-lang/rust/issues/116909>) + ("powerpc" | "powerpc64", _) => false, // ABI unsupported <https://github.com/llvm/llvm-project/issues/41838> ("sparc", _) => false, + // Stack alignment bug <https://github.com/llvm/llvm-project/issues/77401>. NB: tests may + // not fail if our compiler-builtins is linked. + ("x86", _) => false, // MinGW ABI bugs <https://gcc.gnu.org/bugzilla/show_bug.cgi?id=115054> ("x86_64", "windows") if target_env == "gnu" && target_abi != "llvm" => false, - // 64-bit Linux is about the only platform to have f128 symbols by default - (_, "linux") if target_pointer_width == 64 => true, - // Almost all OSs are missing symbol. compiler-builtins will have to add them. - _ => false, + // There are no known problems on other platforms, so the only requirement is that symbols + // are available. `compiler-builtins` provides all symbols required for core `f128` + // support, so this should work for everything else. + _ => true, }; // Configure platforms that have reliable basics but may have unreliable math. diff --git a/library/std/src/collections/hash/map/tests.rs b/library/std/src/collections/hash/map/tests.rs index b79ad1c3119..a275488a556 100644 --- a/library/std/src/collections/hash/map/tests.rs +++ b/library/std/src/collections/hash/map/tests.rs @@ -5,7 +5,7 @@ use super::Entry::{Occupied, Vacant}; use super::HashMap; use crate::assert_matches::assert_matches; use crate::cell::RefCell; -use crate::hash::RandomState; +use crate::hash::{BuildHasher, BuildHasherDefault, DefaultHasher, RandomState}; use crate::test_helpers::test_rng; // https://github.com/rust-lang/rust/issues/62301 @@ -1124,6 +1124,26 @@ fn from_array() { #[test] fn const_with_hasher() { - const X: HashMap<(), (), ()> = HashMap::with_hasher(()); - assert_eq!(X.len(), 0); + const X: HashMap<(), (), BuildHasherDefault<DefaultHasher>> = + HashMap::with_hasher(BuildHasherDefault::new()); + let mut x = X; + assert_eq!(x.len(), 0); + x.insert((), ()); + assert_eq!(x.len(), 1); + + // It *is* possible to do this without using the `BuildHasherDefault` type. + struct MyBuildDefaultHasher; + impl BuildHasher for MyBuildDefaultHasher { + type Hasher = DefaultHasher; + + fn build_hasher(&self) -> Self::Hasher { + DefaultHasher::new() + } + } + + const Y: HashMap<(), (), MyBuildDefaultHasher> = HashMap::with_hasher(MyBuildDefaultHasher); + let mut y = Y; + assert_eq!(y.len(), 0); + y.insert((), ()); + assert_eq!(y.len(), 1); } diff --git a/library/std/src/f128/tests.rs b/library/std/src/f128/tests.rs index 7051c051bf7..cbcf9f96239 100644 --- a/library/std/src/f128/tests.rs +++ b/library/std/src/f128/tests.rs @@ -2,7 +2,10 @@ #![cfg(reliable_f128)] use crate::f128::consts; -use crate::num::{FpCategory as Fp, *}; +use crate::num::FpCategory as Fp; +#[cfg(reliable_f128_math)] +use crate::ops::Rem; +use crate::ops::{Add, Div, Mul, Sub}; // Note these tolerances make sense around zero, but not for more extreme exponents. @@ -53,7 +56,22 @@ macro_rules! assert_f128_biteq { #[test] fn test_num_f128() { - test_num(10f128, 2f128); + // FIXME(f16_f128): replace with a `test_num` call once the required `fmodl`/`fmodf128` + // function is available on all platforms. + let ten = 10f128; + let two = 2f128; + assert_eq!(ten.add(two), ten + two); + assert_eq!(ten.sub(two), ten - two); + assert_eq!(ten.mul(two), ten * two); + assert_eq!(ten.div(two), ten / two); +} + +#[test] +#[cfg(reliable_f128_math)] +fn test_num_f128_rem() { + let ten = 10f128; + let two = 2f128; + assert_eq!(ten.rem(two), ten % two); } #[test] diff --git a/library/std/src/ffi/os_str.rs b/library/std/src/ffi/os_str.rs index 2243f100643..b19d482feaa 100644 --- a/library/std/src/ffi/os_str.rs +++ b/library/std/src/ffi/os_str.rs @@ -1225,6 +1225,15 @@ impl From<&OsStr> for Box<OsStr> { } } +#[stable(feature = "box_from_mut_slice", since = "CURRENT_RUSTC_VERSION")] +impl From<&mut OsStr> for Box<OsStr> { + /// Copies the string into a newly allocated <code>[Box]<[OsStr]></code>. + #[inline] + fn from(s: &mut OsStr) -> Box<OsStr> { + Self::from(&*s) + } +} + #[stable(feature = "box_from_cow", since = "1.45.0")] impl From<Cow<'_, OsStr>> for Box<OsStr> { /// Converts a `Cow<'a, OsStr>` into a <code>[Box]<[OsStr]></code>, @@ -1296,6 +1305,15 @@ impl From<&OsStr> for Arc<OsStr> { } } +#[stable(feature = "shared_from_mut_slice", since = "CURRENT_RUSTC_VERSION")] +impl From<&mut OsStr> for Arc<OsStr> { + /// Copies the string into a newly allocated <code>[Arc]<[OsStr]></code>. + #[inline] + fn from(s: &mut OsStr) -> Arc<OsStr> { + Arc::from(&*s) + } +} + #[stable(feature = "shared_from_slice2", since = "1.24.0")] impl From<OsString> for Rc<OsStr> { /// Converts an [`OsString`] into an <code>[Rc]<[OsStr]></code> by moving the [`OsString`] @@ -1317,6 +1335,15 @@ impl From<&OsStr> for Rc<OsStr> { } } +#[stable(feature = "shared_from_mut_slice", since = "CURRENT_RUSTC_VERSION")] +impl From<&mut OsStr> for Rc<OsStr> { + /// Copies the string into a newly allocated <code>[Rc]<[OsStr]></code>. + #[inline] + fn from(s: &mut OsStr) -> Rc<OsStr> { + Rc::from(&*s) + } +} + #[stable(feature = "cow_from_osstr", since = "1.28.0")] impl<'a> From<OsString> for Cow<'a, OsStr> { /// Moves the string into a [`Cow::Owned`]. diff --git a/library/std/src/hash/random.rs b/library/std/src/hash/random.rs index 40f3a90f60c..236803b24a2 100644 --- a/library/std/src/hash/random.rs +++ b/library/std/src/hash/random.rs @@ -105,9 +105,8 @@ impl DefaultHasher { #[stable(feature = "hashmap_default_hasher", since = "1.13.0")] #[inline] #[allow(deprecated)] - #[rustc_const_unstable(feature = "const_hash", issue = "104061")] #[must_use] - pub const fn new() -> DefaultHasher { + pub fn new() -> DefaultHasher { DefaultHasher(SipHasher13::new_with_keys(0, 0)) } } diff --git a/library/std/src/lib.rs b/library/std/src/lib.rs index d0dd991a933..5b94f036248 100644 --- a/library/std/src/lib.rs +++ b/library/std/src/lib.rs @@ -32,14 +32,12 @@ //! //! Once you are familiar with the contents of the standard library you may //! begin to find the verbosity of the prose distracting. At this stage in your -//! development you may want to press the <code> -//! <svg style="width:0.75rem;height:0.75rem" viewBox="0 0 12 12" -//! stroke="currentColor" fill="none"> -//! <path d="M2,2l4,4l4,-4M2,6l4,4l4,-4"/></svg> Summary</code> button near the -//! top of the page to collapse it into a more skimmable view. +//! development you may want to press the +//! "<svg style="width:0.75rem;height:0.75rem" viewBox="0 0 12 12" stroke="currentColor" fill="none"><path d="M2,2l4,4l4,-4M2,6l4,4l4,-4"/></svg> Summary" +//! button near the top of the page to collapse it into a more skimmable view. //! //! While you are looking at the top of the page, also notice the -//! <code>source</code> link. Rust's API documentation comes with the source +//! "Source" link. Rust's API documentation comes with the source //! code and you are encouraged to read it. The standard library source is //! generally high quality and a peek behind the curtains is //! often enlightening. @@ -328,6 +326,7 @@ // Library features (core): // tidy-alphabetical-start #![feature(array_chunks)] +#![feature(build_hasher_default_const_new)] #![feature(c_str_module)] #![feature(char_internals)] #![feature(clone_to_uninit)] @@ -415,7 +414,6 @@ // Only for const-ness: // tidy-alphabetical-start #![feature(const_collections_with_hasher)] -#![feature(const_hash)] #![feature(thread_local_internals)] // tidy-alphabetical-end // diff --git a/library/std/src/os/darwin/fs.rs b/library/std/src/os/darwin/fs.rs index 2d154b214b5..5740c86e621 100644 --- a/library/std/src/os/darwin/fs.rs +++ b/library/std/src/os/darwin/fs.rs @@ -1,7 +1,8 @@ -#![allow(dead_code)] +//! Darwin-specific extension traits to [`fs`]. +//! +//! [`fs`]: crate::fs +#![stable(feature = "metadata_ext", since = "1.1.0")] -#[allow(deprecated)] -use super::raw; use crate::fs::{self, Metadata}; use crate::sealed::Sealed; use crate::sys_common::{AsInner, AsInnerMut, IntoInner}; @@ -25,7 +26,10 @@ pub trait MetadataExt { methods of this trait" )] #[allow(deprecated)] - fn as_raw_stat(&self) -> &raw::stat; + // Only available on macOS and iOS, since they were stably exposed there. + #[cfg(any(doc, target_os = "macos", target_os = "ios"))] + #[doc(cfg(any(target_os = "macos", target_os = "ios")))] + fn as_raw_stat(&self) -> &super::raw::stat; #[stable(feature = "metadata_ext2", since = "1.8.0")] fn st_dev(&self) -> u64; @@ -77,8 +81,9 @@ pub trait MetadataExt { #[stable(feature = "metadata_ext", since = "1.1.0")] impl MetadataExt for Metadata { #[allow(deprecated)] - fn as_raw_stat(&self) -> &raw::stat { - unsafe { &*(self.as_inner().as_inner() as *const libc::stat as *const raw::stat) } + #[cfg(any(doc, target_os = "macos", target_os = "ios"))] + fn as_raw_stat(&self) -> &super::raw::stat { + unsafe { &*(self.as_inner().as_inner() as *const libc::stat as *const super::raw::stat) } } fn st_dev(&self) -> u64 { self.as_inner().as_inner().st_dev as u64 diff --git a/library/std/src/os/darwin/mod.rs b/library/std/src/os/darwin/mod.rs index 03401fe8895..7a057ddb861 100644 --- a/library/std/src/os/darwin/mod.rs +++ b/library/std/src/os/darwin/mod.rs @@ -13,7 +13,10 @@ //! `aarch64-apple-darwin` target names, which are mostly named that way for //! legacy reasons. -pub(crate) mod fs; +#![stable(feature = "os_darwin", since = "CURRENT_RUSTC_VERSION")] +#![doc(cfg(target_vendor = "apple"))] + +pub mod fs; // deprecated, but used for public reexport under `std::os::unix::raw`, as // well as `std::os::macos`/`std::os::ios`, because those modules precede the // decision to remove these. diff --git a/library/std/src/os/ios/mod.rs b/library/std/src/os/ios/mod.rs index 52d592ed95a..bd18fc2fa0c 100644 --- a/library/std/src/os/ios/mod.rs +++ b/library/std/src/os/ios/mod.rs @@ -4,10 +4,8 @@ #[stable(feature = "metadata_ext", since = "1.1.0")] pub mod fs { - #[doc(inline)] #[stable(feature = "file_set_times", since = "1.75.0")] pub use crate::os::darwin::fs::FileTimesExt; - #[doc(inline)] #[stable(feature = "metadata_ext", since = "1.1.0")] pub use crate::os::darwin::fs::MetadataExt; } diff --git a/library/std/src/os/macos/mod.rs b/library/std/src/os/macos/mod.rs index 59fe90834c2..0681c9b7148 100644 --- a/library/std/src/os/macos/mod.rs +++ b/library/std/src/os/macos/mod.rs @@ -4,10 +4,8 @@ #[stable(feature = "metadata_ext", since = "1.1.0")] pub mod fs { - #[doc(inline)] #[stable(feature = "file_set_times", since = "1.75.0")] pub use crate::os::darwin::fs::FileTimesExt; - #[doc(inline)] #[stable(feature = "metadata_ext", since = "1.1.0")] pub use crate::os::darwin::fs::MetadataExt; } diff --git a/library/std/src/os/mod.rs b/library/std/src/os/mod.rs index 6701173d1e0..e28a1c3e6d5 100644 --- a/library/std/src/os/mod.rs +++ b/library/std/src/os/mod.rs @@ -15,7 +15,16 @@ pub mod raw; // documented don't compile (missing things in `libc` which is empty), // so just omit them with an empty module and add the "unstable" attribute. -// unix, linux, wasi and windows are handled a bit differently. +// darwin, unix, linux, wasi and windows are handled a bit differently. +#[cfg(all( + doc, + any( + all(target_arch = "wasm32", not(target_os = "wasi")), + all(target_vendor = "fortanix", target_env = "sgx") + ) +))] +#[unstable(issue = "none", feature = "std_internals")] +pub mod darwin {} #[cfg(all( doc, any( @@ -53,6 +62,17 @@ pub mod wasi {} #[unstable(issue = "none", feature = "std_internals")] pub mod windows {} +// darwin +#[cfg(not(all( + doc, + any( + all(target_arch = "wasm32", not(target_os = "wasi")), + all(target_vendor = "fortanix", target_env = "sgx") + ) +)))] +#[cfg(any(target_vendor = "apple", doc))] +pub mod darwin; + // unix #[cfg(not(all( doc, @@ -105,8 +125,6 @@ pub mod windows; pub mod aix; #[cfg(target_os = "android")] pub mod android; -#[cfg(target_vendor = "apple")] -pub(crate) mod darwin; #[cfg(target_os = "dragonfly")] pub mod dragonfly; #[cfg(target_os = "emscripten")] diff --git a/library/std/src/os/unix/mod.rs b/library/std/src/os/unix/mod.rs index 5c2ec8ef994..2f9dffe8c65 100644 --- a/library/std/src/os/unix/mod.rs +++ b/library/std/src/os/unix/mod.rs @@ -42,7 +42,7 @@ mod platform { #[cfg(target_os = "android")] pub use crate::os::android::*; #[cfg(target_vendor = "apple")] - pub(super) use crate::os::darwin::*; + pub use crate::os::darwin::*; #[cfg(target_os = "dragonfly")] pub use crate::os::dragonfly::*; #[cfg(target_os = "emscripten")] diff --git a/library/std/src/os/unix/process.rs b/library/std/src/os/unix/process.rs index ef5adaf2290..7c3fa7d6507 100644 --- a/library/std/src/os/unix/process.rs +++ b/library/std/src/os/unix/process.rs @@ -143,7 +143,7 @@ pub trait CommandExt: Sealed { /// /// This function, unlike `spawn`, will **not** `fork` the process to create /// a new child. Like spawn, however, the default behavior for the stdio - /// descriptors will be to inherited from the current process. + /// descriptors will be to inherit them from the current process. /// /// # Notes /// diff --git a/library/std/src/path.rs b/library/std/src/path.rs index 62125f885b2..5662a44d832 100644 --- a/library/std/src/path.rs +++ b/library/std/src/path.rs @@ -1762,6 +1762,16 @@ impl From<&Path> for Box<Path> { } } +#[stable(feature = "box_from_mut_slice", since = "CURRENT_RUSTC_VERSION")] +impl From<&mut Path> for Box<Path> { + /// Creates a boxed [`Path`] from a reference. + /// + /// This will allocate and clone `path` to it. + fn from(path: &mut Path) -> Box<Path> { + Self::from(&*path) + } +} + #[stable(feature = "box_from_cow", since = "1.45.0")] impl From<Cow<'_, Path>> for Box<Path> { /// Creates a boxed [`Path`] from a clone-on-write pointer. @@ -1990,6 +2000,15 @@ impl From<&Path> for Arc<Path> { } } +#[stable(feature = "shared_from_mut_slice", since = "CURRENT_RUSTC_VERSION")] +impl From<&mut Path> for Arc<Path> { + /// Converts a [`Path`] into an [`Arc`] by copying the [`Path`] data into a new [`Arc`] buffer. + #[inline] + fn from(s: &mut Path) -> Arc<Path> { + Arc::from(&*s) + } +} + #[stable(feature = "shared_from_slice2", since = "1.24.0")] impl From<PathBuf> for Rc<Path> { /// Converts a [`PathBuf`] into an <code>[Rc]<[Path]></code> by moving the [`PathBuf`] data into @@ -2011,6 +2030,15 @@ impl From<&Path> for Rc<Path> { } } +#[stable(feature = "shared_from_mut_slice", since = "CURRENT_RUSTC_VERSION")] +impl From<&mut Path> for Rc<Path> { + /// Converts a [`Path`] into an [`Rc`] by copying the [`Path`] data into a new [`Rc`] buffer. + #[inline] + fn from(s: &mut Path) -> Rc<Path> { + Rc::from(&*s) + } +} + #[stable(feature = "rust1", since = "1.0.0")] impl ToOwned for Path { type Owned = PathBuf; diff --git a/library/std/src/sync/lazy_lock.rs b/library/std/src/sync/lazy_lock.rs index b05615035d7..40510f56134 100644 --- a/library/std/src/sync/lazy_lock.rs +++ b/library/std/src/sync/lazy_lock.rs @@ -226,7 +226,7 @@ impl<T, F: FnOnce() -> T> LazyLock<T, F> { } impl<T, F> LazyLock<T, F> { - /// Returns a reference to the value if initialized, or `None` if not. + /// Returns a mutable reference to the value if initialized, or `None` if not. /// /// # Examples /// @@ -255,7 +255,7 @@ impl<T, F> LazyLock<T, F> { } } - /// Returns a mutable reference to the value if initialized, or `None` if not. + /// Returns a reference to the value if initialized, or `None` if not. /// /// # Examples /// diff --git a/library/std/src/sync/mpmc/list.rs b/library/std/src/sync/mpmc/list.rs index 88a8c75f7c8..523e6d2f3bb 100644 --- a/library/std/src/sync/mpmc/list.rs +++ b/library/std/src/sync/mpmc/list.rs @@ -63,14 +63,14 @@ struct Block<T> { impl<T> Block<T> { /// Creates an empty block. - fn new() -> Block<T> { + fn new() -> Box<Block<T>> { // SAFETY: This is safe because: // [1] `Block::next` (AtomicPtr) 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. - unsafe { MaybeUninit::zeroed().assume_init() } + unsafe { Box::new_zeroed().assume_init() } } /// Waits until the next pointer is set. @@ -199,13 +199,13 @@ impl<T> Channel<T> { // If we're going to have to install the next block, allocate it in advance in order to // make the wait for other threads as short as possible. if offset + 1 == BLOCK_CAP && next_block.is_none() { - next_block = Some(Box::new(Block::<T>::new())); + next_block = Some(Block::<T>::new()); } // If this is the first message to be sent into the channel, we need to allocate the // first block and install it. if block.is_null() { - let new = Box::into_raw(Box::new(Block::<T>::new())); + let new = Box::into_raw(Block::<T>::new()); if self .tail diff --git a/library/std/src/sys/alloc/windows.rs b/library/std/src/sys/alloc/windows.rs index a77dda6e817..7e2402afab9 100644 --- a/library/std/src/sys/alloc/windows.rs +++ b/library/std/src/sys/alloc/windows.rs @@ -3,7 +3,6 @@ use crate::alloc::{GlobalAlloc, Layout, System}; use crate::ffi::c_void; use crate::mem::MaybeUninit; use crate::ptr; -use crate::sync::atomic::{AtomicPtr, Ordering}; use crate::sys::c; #[cfg(test)] @@ -81,40 +80,18 @@ windows_targets::link!("kernel32.dll" "system" fn HeapReAlloc( // See https://docs.microsoft.com/windows/win32/api/heapapi/nf-heapapi-heapfree windows_targets::link!("kernel32.dll" "system" fn HeapFree(hheap: c::HANDLE, dwflags: u32, lpmem: *const c_void) -> c::BOOL); -// Cached handle to the default heap of the current process. -// Either a non-null handle returned by `GetProcessHeap`, or null when not yet initialized or `GetProcessHeap` failed. -static HEAP: AtomicPtr<c_void> = AtomicPtr::new(ptr::null_mut()); - -// Get a handle to the default heap of the current process, or null if the operation fails. -// If this operation is successful, `HEAP` will be successfully initialized and contain -// a non-null handle returned by `GetProcessHeap`. -#[inline] -fn init_or_get_process_heap() -> c::HANDLE { - // `HEAP` has not yet been successfully initialized - let heap = unsafe { GetProcessHeap() }; - if !heap.is_null() { - // SAFETY: No locking is needed because within the same process, - // successful calls to `GetProcessHeap` will always return the same value, even on different threads. - HEAP.store(heap, Ordering::Release); - - // SAFETY: `HEAP` contains a non-null handle returned by `GetProcessHeap` - heap - } else { - // Could not get the current process heap. - ptr::null_mut() - } +fn get_process_heap() -> *mut c_void { + // SAFETY: GetProcessHeap simply returns a valid handle or NULL so is always safe to call. + unsafe { GetProcessHeap() } } -/// This is outlined from `process_heap_alloc` so that `process_heap_alloc` -/// does not need any stack allocations. #[inline(never)] -#[cold] -extern "C" fn process_heap_init_and_alloc( - _heap: MaybeUninit<c::HANDLE>, // We pass this argument to match the ABI of `HeapAlloc` +fn process_heap_alloc( + _heap: MaybeUninit<c::HANDLE>, // We pass this argument to match the ABI of `HeapAlloc`, flags: u32, bytes: usize, ) -> *mut c_void { - let heap = init_or_get_process_heap(); + let heap = get_process_heap(); if core::intrinsics::unlikely(heap.is_null()) { return ptr::null_mut(); } @@ -122,28 +99,6 @@ extern "C" fn process_heap_init_and_alloc( unsafe { HeapAlloc(heap, flags, bytes) } } -#[inline(never)] -fn process_heap_alloc( - _heap: MaybeUninit<c::HANDLE>, // We pass this argument to match the ABI of `HeapAlloc`, - flags: u32, - bytes: usize, -) -> *mut c_void { - let heap = HEAP.load(Ordering::Relaxed); - if core::intrinsics::likely(!heap.is_null()) { - // SAFETY: `heap` is a non-null handle returned by `GetProcessHeap`. - unsafe { HeapAlloc(heap, flags, bytes) } - } else { - process_heap_init_and_alloc(MaybeUninit::uninit(), flags, bytes) - } -} - -// Get a non-null handle to the default heap of the current process. -// SAFETY: `HEAP` must have been successfully initialized. -#[inline] -unsafe fn get_process_heap() -> c::HANDLE { - HEAP.load(Ordering::Acquire) -} - // Header containing a pointer to the start of an allocated block. // SAFETY: Size and alignment must be <= `MIN_ALIGN`. #[repr(C)] @@ -232,9 +187,9 @@ unsafe impl GlobalAlloc for System { } }; - // SAFETY: because `ptr` has been successfully allocated with this allocator, - // `HEAP` must have been successfully initialized. - let heap = unsafe { get_process_heap() }; + // because `ptr` has been successfully allocated with this allocator, + // there must be a valid process heap. + let heap = get_process_heap(); // SAFETY: `heap` is a non-null handle returned by `GetProcessHeap`, // `block` is a pointer to the start of an allocated block. @@ -244,9 +199,9 @@ unsafe impl GlobalAlloc for System { #[inline] unsafe fn realloc(&self, ptr: *mut u8, layout: Layout, new_size: usize) -> *mut u8 { if layout.align() <= MIN_ALIGN { - // SAFETY: because `ptr` has been successfully allocated with this allocator, - // `HEAP` must have been successfully initialized. - let heap = unsafe { get_process_heap() }; + // because `ptr` has been successfully allocated with this allocator, + // there must be a valid process heap. + let heap = get_process_heap(); // SAFETY: `heap` is a non-null handle returned by `GetProcessHeap`, // `ptr` is a pointer to the start of an allocated block. |
