diff options
Diffstat (limited to 'library/std/src')
26 files changed, 394 insertions, 727 deletions
diff --git a/library/std/src/collections/hash/map.rs b/library/std/src/collections/hash/map.rs index 4d109285d16..39e94902cfe 100644 --- a/library/std/src/collections/hash/map.rs +++ b/library/std/src/collections/hash/map.rs @@ -6,16 +6,13 @@ use self::Entry::*; use hashbrown::hash_map as base; use crate::borrow::Borrow; -use crate::cell::Cell; use crate::collections::TryReserveError; use crate::collections::TryReserveErrorKind; use crate::error::Error; use crate::fmt::{self, Debug}; -#[allow(deprecated)] -use crate::hash::{BuildHasher, Hash, Hasher, SipHasher13}; +use crate::hash::{BuildHasher, Hash, RandomState}; use crate::iter::FusedIterator; use crate::ops::Index; -use crate::sys; /// A [hash map] implemented with quadratic probing and SIMD lookup. /// @@ -274,7 +271,7 @@ impl<K, V, S> HashMap<K, V, S> { /// /// ``` /// use std::collections::HashMap; - /// use std::collections::hash_map::RandomState; + /// use std::hash::RandomState; /// /// let s = RandomState::new(); /// let mut map = HashMap::with_hasher(s); @@ -306,7 +303,7 @@ impl<K, V, S> HashMap<K, V, S> { /// /// ``` /// use std::collections::HashMap; - /// use std::collections::hash_map::RandomState; + /// use std::hash::RandomState; /// /// let s = RandomState::new(); /// let mut map = HashMap::with_capacity_and_hasher(10, s); @@ -717,7 +714,7 @@ impl<K, V, S> HashMap<K, V, S> { /// /// ``` /// use std::collections::HashMap; - /// use std::collections::hash_map::RandomState; + /// use std::hash::RandomState; /// /// let hasher = RandomState::new(); /// let map: HashMap<i32, i32> = HashMap::with_hasher(hasher); @@ -3072,152 +3069,6 @@ where } } -/// `RandomState` is the default state for [`HashMap`] types. -/// -/// A particular instance `RandomState` will create the same instances of -/// [`Hasher`], but the hashers created by two different `RandomState` -/// instances are unlikely to produce the same result for the same values. -/// -/// # Examples -/// -/// ``` -/// use std::collections::HashMap; -/// use std::collections::hash_map::RandomState; -/// -/// let s = RandomState::new(); -/// let mut map = HashMap::with_hasher(s); -/// map.insert(1, 2); -/// ``` -#[derive(Clone)] -#[stable(feature = "hashmap_build_hasher", since = "1.7.0")] -pub struct RandomState { - k0: u64, - k1: u64, -} - -impl RandomState { - /// Constructs a new `RandomState` that is initialized with random keys. - /// - /// # Examples - /// - /// ``` - /// use std::collections::hash_map::RandomState; - /// - /// let s = RandomState::new(); - /// ``` - #[inline] - #[allow(deprecated)] - // rand - #[must_use] - #[stable(feature = "hashmap_build_hasher", since = "1.7.0")] - pub fn new() -> RandomState { - // Historically this function did not cache keys from the OS and instead - // simply always called `rand::thread_rng().gen()` twice. In #31356 it - // was discovered, however, that because we re-seed the thread-local RNG - // from the OS periodically that this can cause excessive slowdown when - // many hash maps are created on a thread. To solve this performance - // trap we cache the first set of randomly generated keys per-thread. - // - // Later in #36481 it was discovered that exposing a deterministic - // iteration order allows a form of DOS attack. To counter that we - // increment one of the seeds on every RandomState creation, giving - // every corresponding HashMap a different iteration order. - thread_local!(static KEYS: Cell<(u64, u64)> = { - Cell::new(sys::hashmap_random_keys()) - }); - - KEYS.with(|keys| { - let (k0, k1) = keys.get(); - keys.set((k0.wrapping_add(1), k1)); - RandomState { k0, k1 } - }) - } -} - -#[stable(feature = "hashmap_build_hasher", since = "1.7.0")] -impl BuildHasher for RandomState { - type Hasher = DefaultHasher; - #[inline] - #[allow(deprecated)] - fn build_hasher(&self) -> DefaultHasher { - DefaultHasher(SipHasher13::new_with_keys(self.k0, self.k1)) - } -} - -/// The default [`Hasher`] used by [`RandomState`]. -/// -/// The internal algorithm is not specified, and so it and its hashes should -/// not be relied upon over releases. -#[stable(feature = "hashmap_default_hasher", since = "1.13.0")] -#[allow(deprecated)] -#[derive(Clone, Debug)] -pub struct DefaultHasher(SipHasher13); - -impl DefaultHasher { - /// Creates a new `DefaultHasher`. - /// - /// This hasher is not guaranteed to be the same as all other - /// `DefaultHasher` instances, but is the same as all other `DefaultHasher` - /// instances created through `new` or `default`. - #[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 { - DefaultHasher(SipHasher13::new_with_keys(0, 0)) - } -} - -#[stable(feature = "hashmap_default_hasher", since = "1.13.0")] -impl Default for DefaultHasher { - /// Creates a new `DefaultHasher` using [`new`]. - /// See its documentation for more. - /// - /// [`new`]: DefaultHasher::new - #[inline] - fn default() -> DefaultHasher { - DefaultHasher::new() - } -} - -#[stable(feature = "hashmap_default_hasher", since = "1.13.0")] -impl Hasher for DefaultHasher { - // The underlying `SipHasher13` doesn't override the other - // `write_*` methods, so it's ok not to forward them here. - - #[inline] - fn write(&mut self, msg: &[u8]) { - self.0.write(msg) - } - - #[inline] - fn write_str(&mut self, s: &str) { - self.0.write_str(s); - } - - #[inline] - fn finish(&self) -> u64 { - self.0.finish() - } -} - -#[stable(feature = "hashmap_build_hasher", since = "1.7.0")] -impl Default for RandomState { - /// Constructs a new `RandomState`. - #[inline] - fn default() -> RandomState { - RandomState::new() - } -} - -#[stable(feature = "std_debug", since = "1.16.0")] -impl fmt::Debug for RandomState { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - f.debug_struct("RandomState").finish_non_exhaustive() - } -} - #[inline] fn map_entry<'a, K: 'a, V: 'a>(raw: base::RustcEntry<'a, K, V>) -> Entry<'a, K, V> { match raw { diff --git a/library/std/src/collections/hash/map/tests.rs b/library/std/src/collections/hash/map/tests.rs index 91a3776e7be..8585376abc1 100644 --- a/library/std/src/collections/hash/map/tests.rs +++ b/library/std/src/collections/hash/map/tests.rs @@ -1,8 +1,8 @@ use super::Entry::{Occupied, Vacant}; use super::HashMap; -use super::RandomState; use crate::assert_matches::assert_matches; use crate::cell::RefCell; +use crate::hash::RandomState; use crate::test_helpers::test_rng; use rand::Rng; use realstd::collections::TryReserveErrorKind::*; diff --git a/library/std/src/collections/hash/set.rs b/library/std/src/collections/hash/set.rs index 6a87f6e5f2d..8bc59608290 100644 --- a/library/std/src/collections/hash/set.rs +++ b/library/std/src/collections/hash/set.rs @@ -6,11 +6,11 @@ use hashbrown::hash_set as base; use crate::borrow::Borrow; use crate::collections::TryReserveError; use crate::fmt; -use crate::hash::{BuildHasher, Hash}; +use crate::hash::{BuildHasher, Hash, RandomState}; use crate::iter::{Chain, FusedIterator}; use crate::ops::{BitAnd, BitOr, BitXor, Sub}; -use super::map::{map_try_reserve_error, RandomState}; +use super::map::map_try_reserve_error; /// A [hash set] implemented as a `HashMap` where the value is `()`. /// @@ -361,7 +361,7 @@ impl<T, S> HashSet<T, S> { /// /// ``` /// use std::collections::HashSet; - /// use std::collections::hash_map::RandomState; + /// use std::hash::RandomState; /// /// let s = RandomState::new(); /// let mut set = HashSet::with_hasher(s); @@ -393,7 +393,7 @@ impl<T, S> HashSet<T, S> { /// /// ``` /// use std::collections::HashSet; - /// use std::collections::hash_map::RandomState; + /// use std::hash::RandomState; /// /// let s = RandomState::new(); /// let mut set = HashSet::with_capacity_and_hasher(10, s); @@ -411,7 +411,7 @@ impl<T, S> HashSet<T, S> { /// /// ``` /// use std::collections::HashSet; - /// use std::collections::hash_map::RandomState; + /// use std::hash::RandomState; /// /// let hasher = RandomState::new(); /// let set: HashSet<i32> = HashSet::with_hasher(hasher); diff --git a/library/std/src/collections/hash/set/tests.rs b/library/std/src/collections/hash/set/tests.rs index e0cd80b44f8..208f61e755c 100644 --- a/library/std/src/collections/hash/set/tests.rs +++ b/library/std/src/collections/hash/set/tests.rs @@ -1,6 +1,6 @@ -use super::super::map::RandomState; use super::HashSet; +use crate::hash::RandomState; use crate::panic::{catch_unwind, AssertUnwindSafe}; use crate::sync::atomic::{AtomicU32, Ordering}; use crate::sync::Arc; diff --git a/library/std/src/collections/mod.rs b/library/std/src/collections/mod.rs index 42f738acb9f..1389d24a8c5 100644 --- a/library/std/src/collections/mod.rs +++ b/library/std/src/collections/mod.rs @@ -439,6 +439,11 @@ pub mod hash_map { //! A hash map implemented with quadratic probing and SIMD lookup. #[stable(feature = "rust1", since = "1.0.0")] pub use super::hash::map::*; + + #[stable(feature = "hashmap_build_hasher", since = "1.7.0")] + pub use crate::hash::random::DefaultHasher; + #[stable(feature = "hashmap_build_hasher", since = "1.7.0")] + pub use crate::hash::random::RandomState; } #[stable(feature = "rust1", since = "1.0.0")] diff --git a/library/std/src/fs.rs b/library/std/src/fs.rs index 61c39133617..4310e108303 100644 --- a/library/std/src/fs.rs +++ b/library/std/src/fs.rs @@ -189,7 +189,7 @@ pub struct OpenOptions(fs_imp::OpenOptions); /// Representation of the various timestamps on a file. #[derive(Copy, Clone, Debug, Default)] -#[stable(feature = "file_set_times", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "file_set_times", since = "1.75.0")] pub struct FileTimes(fs_imp::FileTimes); /// Representation of the various permissions on a file. @@ -688,7 +688,7 @@ impl File { /// Ok(()) /// } /// ``` - #[stable(feature = "file_set_times", since = "CURRENT_RUSTC_VERSION")] + #[stable(feature = "file_set_times", since = "1.75.0")] #[doc(alias = "futimens")] #[doc(alias = "futimes")] #[doc(alias = "SetFileTime")] @@ -699,7 +699,7 @@ impl File { /// Changes the modification time of the underlying file. /// /// This is an alias for `set_times(FileTimes::new().set_modified(time))`. - #[stable(feature = "file_set_times", since = "CURRENT_RUSTC_VERSION")] + #[stable(feature = "file_set_times", since = "1.75.0")] #[inline] pub fn set_modified(&self, time: SystemTime) -> io::Result<()> { self.set_times(FileTimes::new().set_modified(time)) @@ -1413,20 +1413,20 @@ impl FileTimes { /// Create a new `FileTimes` with no times set. /// /// Using the resulting `FileTimes` in [`File::set_times`] will not modify any timestamps. - #[stable(feature = "file_set_times", since = "CURRENT_RUSTC_VERSION")] + #[stable(feature = "file_set_times", since = "1.75.0")] pub fn new() -> Self { Self::default() } /// Set the last access time of a file. - #[stable(feature = "file_set_times", since = "CURRENT_RUSTC_VERSION")] + #[stable(feature = "file_set_times", since = "1.75.0")] pub fn set_accessed(mut self, t: SystemTime) -> Self { self.0.set_accessed(t.into_inner()); self } /// Set the last modified time of a file. - #[stable(feature = "file_set_times", since = "CURRENT_RUSTC_VERSION")] + #[stable(feature = "file_set_times", since = "1.75.0")] pub fn set_modified(mut self, t: SystemTime) -> Self { self.0.set_modified(t.into_inner()); self @@ -1440,7 +1440,7 @@ impl AsInnerMut<fs_imp::FileTimes> for FileTimes { } // For implementing OS extension traits in `std::os` -#[stable(feature = "file_set_times", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "file_set_times", since = "1.75.0")] impl Sealed for FileTimes {} impl Permissions { diff --git a/library/std/src/hash/mod.rs b/library/std/src/hash/mod.rs new file mode 100644 index 00000000000..bd9bbf29875 --- /dev/null +++ b/library/std/src/hash/mod.rs @@ -0,0 +1,91 @@ +//! Generic hashing support. +//! +//! This module provides a generic way to compute the [hash] of a value. +//! Hashes are most commonly used with [`HashMap`] and [`HashSet`]. +//! +//! [hash]: https://en.wikipedia.org/wiki/Hash_function +//! [`HashMap`]: ../../std/collections/struct.HashMap.html +//! [`HashSet`]: ../../std/collections/struct.HashSet.html +//! +//! The simplest way to make a type hashable is to use `#[derive(Hash)]`: +//! +//! # Examples +//! +//! ```rust +//! use std::hash::{DefaultHasher, Hash, Hasher}; +//! +//! #[derive(Hash)] +//! struct Person { +//! id: u32, +//! name: String, +//! phone: u64, +//! } +//! +//! let person1 = Person { +//! id: 5, +//! name: "Janet".to_string(), +//! phone: 555_666_7777, +//! }; +//! let person2 = Person { +//! id: 5, +//! name: "Bob".to_string(), +//! phone: 555_666_7777, +//! }; +//! +//! assert!(calculate_hash(&person1) != calculate_hash(&person2)); +//! +//! fn calculate_hash<T: Hash>(t: &T) -> u64 { +//! let mut s = DefaultHasher::new(); +//! t.hash(&mut s); +//! s.finish() +//! } +//! ``` +//! +//! If you need more control over how a value is hashed, you need to implement +//! the [`Hash`] trait: +//! +//! ```rust +//! use std::hash::{DefaultHasher, Hash, Hasher}; +//! +//! struct Person { +//! id: u32, +//! # #[allow(dead_code)] +//! name: String, +//! phone: u64, +//! } +//! +//! impl Hash for Person { +//! fn hash<H: Hasher>(&self, state: &mut H) { +//! self.id.hash(state); +//! self.phone.hash(state); +//! } +//! } +//! +//! let person1 = Person { +//! id: 5, +//! name: "Janet".to_string(), +//! phone: 555_666_7777, +//! }; +//! let person2 = Person { +//! id: 5, +//! name: "Bob".to_string(), +//! phone: 555_666_7777, +//! }; +//! +//! assert_eq!(calculate_hash(&person1), calculate_hash(&person2)); +//! +//! fn calculate_hash<T: Hash>(t: &T) -> u64 { +//! let mut s = DefaultHasher::new(); +//! t.hash(&mut s); +//! s.finish() +//! } +//! ``` +#![stable(feature = "rust1", since = "1.0.0")] + +pub(crate) mod random; + +#[stable(feature = "rust1", since = "1.0.0")] +pub use core::hash::*; + +#[stable(feature = "std_hash_exports", since = "CURRENT_RUSTC_VERSION")] +pub use self::random::{DefaultHasher, RandomState}; diff --git a/library/std/src/hash/random.rs b/library/std/src/hash/random.rs new file mode 100644 index 00000000000..a1ccbb25369 --- /dev/null +++ b/library/std/src/hash/random.rs @@ -0,0 +1,161 @@ +//! This module exists to isolate [`RandomState`] and [`DefaultHasher`] outside of the +//! [`collections`] module without actually publicly exporting them, so that parts of that +//! implementation can more easily be moved to the [`alloc`] crate. +//! +//! Although its items are public and contain stability attributes, they can't actually be accessed +//! outside this crate. +//! +//! [`collections`]: crate::collections +#[allow(deprecated)] +use super::{BuildHasher, Hasher, SipHasher13}; +use crate::cell::Cell; +use crate::fmt; +use crate::sys; + +/// `RandomState` is the default state for [`HashMap`] types. +/// +/// A particular instance `RandomState` will create the same instances of +/// [`Hasher`], but the hashers created by two different `RandomState` +/// instances are unlikely to produce the same result for the same values. +/// +/// [`HashMap`]: crate::collections::HashMap +/// +/// # Examples +/// +/// ``` +/// use std::collections::HashMap; +/// use std::hash::RandomState; +/// +/// let s = RandomState::new(); +/// let mut map = HashMap::with_hasher(s); +/// map.insert(1, 2); +/// ``` +#[stable(feature = "hashmap_build_hasher", since = "1.7.0")] +#[derive(Clone)] +pub struct RandomState { + k0: u64, + k1: u64, +} + +impl RandomState { + /// Constructs a new `RandomState` that is initialized with random keys. + /// + /// # Examples + /// + /// ``` + /// use std::hash::RandomState; + /// + /// let s = RandomState::new(); + /// ``` + #[inline] + #[allow(deprecated)] + // rand + #[must_use] + #[stable(feature = "hashmap_build_hasher", since = "1.7.0")] + pub fn new() -> RandomState { + // Historically this function did not cache keys from the OS and instead + // simply always called `rand::thread_rng().gen()` twice. In #31356 it + // was discovered, however, that because we re-seed the thread-local RNG + // from the OS periodically that this can cause excessive slowdown when + // many hash maps are created on a thread. To solve this performance + // trap we cache the first set of randomly generated keys per-thread. + // + // Later in #36481 it was discovered that exposing a deterministic + // iteration order allows a form of DOS attack. To counter that we + // increment one of the seeds on every RandomState creation, giving + // every corresponding HashMap a different iteration order. + thread_local!(static KEYS: Cell<(u64, u64)> = { + Cell::new(sys::hashmap_random_keys()) + }); + + KEYS.with(|keys| { + let (k0, k1) = keys.get(); + keys.set((k0.wrapping_add(1), k1)); + RandomState { k0, k1 } + }) + } +} + +#[stable(feature = "hashmap_build_hasher", since = "1.7.0")] +impl BuildHasher for RandomState { + type Hasher = DefaultHasher; + #[inline] + #[allow(deprecated)] + fn build_hasher(&self) -> DefaultHasher { + DefaultHasher(SipHasher13::new_with_keys(self.k0, self.k1)) + } +} + +/// The default [`Hasher`] used by [`RandomState`]. +/// +/// The internal algorithm is not specified, and so it and its hashes should +/// not be relied upon over releases. +#[allow(deprecated)] +#[derive(Clone, Debug)] +#[stable(feature = "hashmap_build_hasher", since = "1.7.0")] +pub struct DefaultHasher(SipHasher13); + +impl DefaultHasher { + /// Creates a new `DefaultHasher`. + /// + /// This hasher is not guaranteed to be the same as all other + /// `DefaultHasher` instances, but is the same as all other `DefaultHasher` + /// instances created through `new` or `default`. + #[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 { + DefaultHasher(SipHasher13::new_with_keys(0, 0)) + } +} + +#[stable(feature = "hashmap_default_hasher", since = "1.13.0")] +impl Default for DefaultHasher { + /// Creates a new `DefaultHasher` using [`new`]. + /// See its documentation for more. + /// + /// [`new`]: DefaultHasher::new + #[inline] + fn default() -> DefaultHasher { + DefaultHasher::new() + } +} + +#[stable(feature = "hashmap_default_hasher", since = "1.13.0")] +impl Hasher for DefaultHasher { + // The underlying `SipHasher13` doesn't override the other + // `write_*` methods, so it's ok not to forward them here. + + #[inline] + fn write(&mut self, msg: &[u8]) { + self.0.write(msg) + } + + #[inline] + fn write_str(&mut self, s: &str) { + self.0.write_str(s); + } + + #[inline] + fn finish(&self) -> u64 { + self.0.finish() + } +} + +#[stable(feature = "hashmap_build_hasher", since = "1.7.0")] +impl Default for RandomState { + /// Constructs a new `RandomState`. + #[inline] + fn default() -> RandomState { + RandomState::new() + } +} + +#[stable(feature = "std_debug", since = "1.16.0")] +impl fmt::Debug for RandomState { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + f.debug_struct("RandomState").finish_non_exhaustive() + } +} diff --git a/library/std/src/io/copy.rs b/library/std/src/io/copy.rs index 57d226a3771..4d51a719f6c 100644 --- a/library/std/src/io/copy.rs +++ b/library/std/src/io/copy.rs @@ -1,6 +1,7 @@ use super::{BorrowedBuf, BufReader, BufWriter, Read, Result, Write, DEFAULT_BUF_SIZE}; use crate::alloc::Allocator; use crate::cmp; +use crate::cmp::min; use crate::collections::VecDeque; use crate::io::IoSlice; use crate::mem::MaybeUninit; @@ -263,36 +264,67 @@ impl<A: Allocator> BufferedWriterSpec for Vec<u8, A> { fn copy_from<R: Read + ?Sized>(&mut self, reader: &mut R) -> Result<u64> { let mut bytes = 0; - // avoid allocating before we have determined that there's anything to read - if self.capacity() == 0 { - bytes = stack_buffer_copy(&mut reader.take(DEFAULT_BUF_SIZE as u64), self)?; - if bytes == 0 { - return Ok(0); + // avoid inflating empty/small vecs before we have determined that there's anything to read + if self.capacity() < DEFAULT_BUF_SIZE { + let stack_read_limit = DEFAULT_BUF_SIZE as u64; + bytes = stack_buffer_copy(&mut reader.take(stack_read_limit), self)?; + // fewer bytes than requested -> EOF reached + if bytes < stack_read_limit { + return Ok(bytes); } } + // don't immediately offer the vec's whole spare capacity, otherwise + // we might have to fully initialize it if the reader doesn't have a custom read_buf() impl + let mut max_read_size = DEFAULT_BUF_SIZE; + loop { self.reserve(DEFAULT_BUF_SIZE); - let mut buf: BorrowedBuf<'_> = self.spare_capacity_mut().into(); - match reader.read_buf(buf.unfilled()) { - Ok(()) => {} - Err(e) if e.is_interrupted() => continue, - Err(e) => return Err(e), - }; + let mut initialized_spare_capacity = 0; - let read = buf.filled().len(); - if read == 0 { - break; - } + loop { + let buf = self.spare_capacity_mut(); + let read_size = min(max_read_size, buf.len()); + let mut buf = BorrowedBuf::from(&mut buf[..read_size]); + // SAFETY: init is either 0 or the init_len from the previous iteration. + unsafe { + buf.set_init(initialized_spare_capacity); + } + match reader.read_buf(buf.unfilled()) { + Ok(()) => { + let bytes_read = buf.len(); - // SAFETY: BorrowedBuf guarantees all of its filled bytes are init - // and the number of read bytes can't exceed the spare capacity since - // that's what the buffer is borrowing from. - unsafe { self.set_len(self.len() + read) }; - bytes += read as u64; - } + // EOF + if bytes_read == 0 { + return Ok(bytes); + } - Ok(bytes) + // the reader is returning short reads but it doesn't call ensure_init() + if buf.init_len() < buf.capacity() { + max_read_size = usize::MAX; + } + // the reader hasn't returned short reads so far + if bytes_read == buf.capacity() { + max_read_size *= 2; + } + + initialized_spare_capacity = buf.init_len() - bytes_read; + bytes += bytes_read as u64; + // SAFETY: BorrowedBuf guarantees all of its filled bytes are init + // and the number of read bytes can't exceed the spare capacity since + // that's what the buffer is borrowing from. + unsafe { self.set_len(self.len() + bytes_read) }; + + // spare capacity full, reserve more + if self.len() == self.capacity() { + break; + } + } + Err(e) if e.is_interrupted() => continue, + Err(e) => return Err(e), + } + } + } } } diff --git a/library/std/src/io/impls.rs b/library/std/src/io/impls.rs index f438325560f..d8c8d933eb4 100644 --- a/library/std/src/io/impls.rs +++ b/library/std/src/io/impls.rs @@ -476,7 +476,7 @@ impl<A: Allocator> Read for VecDeque<u8, A> { } /// BufRead is implemented for `VecDeque<u8>` by reading bytes from the front of the `VecDeque`. -#[stable(feature = "vecdeque_buf_read", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "vecdeque_buf_read", since = "1.75.0")] impl<A: Allocator> BufRead for VecDeque<u8, A> { /// Returns the contents of the "front" slice as returned by /// [`as_slices`][`VecDeque::as_slices`]. If the contained byte slices of the `VecDeque` are @@ -528,3 +528,17 @@ impl<A: Allocator> Write for VecDeque<u8, A> { Ok(()) } } + +#[unstable(feature = "read_buf", issue = "78485")] +impl<'a> io::Write for core::io::BorrowedCursor<'a> { + fn write(&mut self, buf: &[u8]) -> io::Result<usize> { + let amt = cmp::min(buf.len(), self.capacity()); + self.append(&buf[..amt]); + Ok(amt) + } + + #[inline] + fn flush(&mut self) -> io::Result<()> { + Ok(()) + } +} diff --git a/library/std/src/io/mod.rs b/library/std/src/io/mod.rs index aa9a2482d2d..7d70a0bac24 100644 --- a/library/std/src/io/mod.rs +++ b/library/std/src/io/mod.rs @@ -330,7 +330,7 @@ pub use self::{ }; #[unstable(feature = "read_buf", issue = "78485")] -pub use self::readbuf::{BorrowedBuf, BorrowedCursor}; +pub use core::io::{BorrowedBuf, BorrowedCursor}; pub(crate) use error::const_io_error; mod buffered; @@ -339,7 +339,6 @@ mod cursor; mod error; mod impls; pub mod prelude; -mod readbuf; mod stdio; mod util; diff --git a/library/std/src/io/readbuf.rs b/library/std/src/io/readbuf.rs deleted file mode 100644 index 034ddd8df9a..00000000000 --- a/library/std/src/io/readbuf.rs +++ /dev/null @@ -1,317 +0,0 @@ -#![unstable(feature = "read_buf", issue = "78485")] - -#[cfg(test)] -mod tests; - -use crate::fmt::{self, Debug, Formatter}; -use crate::io::{Result, Write}; -use crate::mem::{self, MaybeUninit}; -use crate::{cmp, ptr}; - -/// A borrowed byte buffer which is incrementally filled and initialized. -/// -/// This type is a sort of "double cursor". It tracks three regions in the buffer: a region at the beginning of the -/// buffer that has been logically filled with data, a region that has been initialized at some point but not yet -/// logically filled, and a region at the end that is fully uninitialized. The filled region is guaranteed to be a -/// subset of the initialized region. -/// -/// In summary, the contents of the buffer can be visualized as: -/// ```not_rust -/// [ capacity ] -/// [ filled | unfilled ] -/// [ initialized | uninitialized ] -/// ``` -/// -/// A `BorrowedBuf` is created around some existing data (or capacity for data) via a unique reference -/// (`&mut`). The `BorrowedBuf` can be configured (e.g., using `clear` or `set_init`), but cannot be -/// directly written. To write into the buffer, use `unfilled` to create a `BorrowedCursor`. The cursor -/// has write-only access to the unfilled portion of the buffer (you can think of it as a -/// write-only iterator). -/// -/// The lifetime `'data` is a bound on the lifetime of the underlying data. -pub struct BorrowedBuf<'data> { - /// The buffer's underlying data. - buf: &'data mut [MaybeUninit<u8>], - /// The length of `self.buf` which is known to be filled. - filled: usize, - /// The length of `self.buf` which is known to be initialized. - init: usize, -} - -impl Debug for BorrowedBuf<'_> { - fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result { - f.debug_struct("BorrowedBuf") - .field("init", &self.init) - .field("filled", &self.filled) - .field("capacity", &self.capacity()) - .finish() - } -} - -/// Create a new `BorrowedBuf` from a fully initialized slice. -impl<'data> From<&'data mut [u8]> for BorrowedBuf<'data> { - #[inline] - fn from(slice: &'data mut [u8]) -> BorrowedBuf<'data> { - let len = slice.len(); - - BorrowedBuf { - // SAFETY: initialized data never becoming uninitialized is an invariant of BorrowedBuf - buf: unsafe { (slice as *mut [u8]).as_uninit_slice_mut().unwrap() }, - filled: 0, - init: len, - } - } -} - -/// Create a new `BorrowedBuf` from an uninitialized buffer. -/// -/// Use `set_init` if part of the buffer is known to be already initialized. -impl<'data> From<&'data mut [MaybeUninit<u8>]> for BorrowedBuf<'data> { - #[inline] - fn from(buf: &'data mut [MaybeUninit<u8>]) -> BorrowedBuf<'data> { - BorrowedBuf { buf, filled: 0, init: 0 } - } -} - -impl<'data> BorrowedBuf<'data> { - /// Returns the total capacity of the buffer. - #[inline] - pub fn capacity(&self) -> usize { - self.buf.len() - } - - /// Returns the length of the filled part of the buffer. - #[inline] - pub fn len(&self) -> usize { - self.filled - } - - /// Returns the length of the initialized part of the buffer. - #[inline] - pub fn init_len(&self) -> usize { - self.init - } - - /// Returns a shared reference to the filled portion of the buffer. - #[inline] - pub fn filled(&self) -> &[u8] { - // SAFETY: We only slice the filled part of the buffer, which is always valid - unsafe { MaybeUninit::slice_assume_init_ref(&self.buf[0..self.filled]) } - } - - /// Returns a mutable reference to the filled portion of the buffer. - #[inline] - pub fn filled_mut(&mut self) -> &mut [u8] { - // SAFETY: We only slice the filled part of the buffer, which is always valid - unsafe { MaybeUninit::slice_assume_init_mut(&mut self.buf[0..self.filled]) } - } - - /// Returns a cursor over the unfilled part of the buffer. - #[inline] - pub fn unfilled<'this>(&'this mut self) -> BorrowedCursor<'this> { - BorrowedCursor { - start: self.filled, - // SAFETY: we never assign into `BorrowedCursor::buf`, so treating its - // lifetime covariantly is safe. - buf: unsafe { - mem::transmute::<&'this mut BorrowedBuf<'data>, &'this mut BorrowedBuf<'this>>(self) - }, - } - } - - /// Clears the buffer, resetting the filled region to empty. - /// - /// The number of initialized bytes is not changed, and the contents of the buffer are not modified. - #[inline] - pub fn clear(&mut self) -> &mut Self { - self.filled = 0; - self - } - - /// Asserts that the first `n` bytes of the buffer are initialized. - /// - /// `BorrowedBuf` assumes that bytes are never de-initialized, so this method does nothing when called with fewer - /// bytes than are already known to be initialized. - /// - /// # Safety - /// - /// The caller must ensure that the first `n` unfilled bytes of the buffer have already been initialized. - #[inline] - pub unsafe fn set_init(&mut self, n: usize) -> &mut Self { - self.init = cmp::max(self.init, n); - self - } -} - -/// A writeable view of the unfilled portion of a [`BorrowedBuf`](BorrowedBuf). -/// -/// Provides access to the initialized and uninitialized parts of the underlying `BorrowedBuf`. -/// Data can be written directly to the cursor by using [`append`](BorrowedCursor::append) or -/// indirectly by getting a slice of part or all of the cursor and writing into the slice. In the -/// indirect case, the caller must call [`advance`](BorrowedCursor::advance) after writing to inform -/// the cursor how many bytes have been written. -/// -/// Once data is written to the cursor, it becomes part of the filled portion of the underlying -/// `BorrowedBuf` and can no longer be accessed or re-written by the cursor. I.e., the cursor tracks -/// the unfilled part of the underlying `BorrowedBuf`. -/// -/// The lifetime `'a` is a bound on the lifetime of the underlying buffer (which means it is a bound -/// on the data in that buffer by transitivity). -#[derive(Debug)] -pub struct BorrowedCursor<'a> { - /// The underlying buffer. - // Safety invariant: we treat the type of buf as covariant in the lifetime of `BorrowedBuf` when - // we create a `BorrowedCursor`. This is only safe if we never replace `buf` by assigning into - // it, so don't do that! - buf: &'a mut BorrowedBuf<'a>, - /// The length of the filled portion of the underlying buffer at the time of the cursor's - /// creation. - start: usize, -} - -impl<'a> BorrowedCursor<'a> { - /// Reborrow this cursor by cloning it with a smaller lifetime. - /// - /// Since a cursor maintains unique access to its underlying buffer, the borrowed cursor is - /// not accessible while the new cursor exists. - #[inline] - pub fn reborrow<'this>(&'this mut self) -> BorrowedCursor<'this> { - BorrowedCursor { - // SAFETY: we never assign into `BorrowedCursor::buf`, so treating its - // lifetime covariantly is safe. - buf: unsafe { - mem::transmute::<&'this mut BorrowedBuf<'a>, &'this mut BorrowedBuf<'this>>( - self.buf, - ) - }, - start: self.start, - } - } - - /// Returns the available space in the cursor. - #[inline] - pub fn capacity(&self) -> usize { - self.buf.capacity() - self.buf.filled - } - - /// Returns the number of bytes written to this cursor since it was created from a `BorrowedBuf`. - /// - /// Note that if this cursor is a reborrowed clone of another, then the count returned is the - /// count written via either cursor, not the count since the cursor was reborrowed. - #[inline] - pub fn written(&self) -> usize { - self.buf.filled - self.start - } - - /// Returns a shared reference to the initialized portion of the cursor. - #[inline] - pub fn init_ref(&self) -> &[u8] { - // SAFETY: We only slice the initialized part of the buffer, which is always valid - unsafe { MaybeUninit::slice_assume_init_ref(&self.buf.buf[self.buf.filled..self.buf.init]) } - } - - /// Returns a mutable reference to the initialized portion of the cursor. - #[inline] - pub fn init_mut(&mut self) -> &mut [u8] { - // SAFETY: We only slice the initialized part of the buffer, which is always valid - unsafe { - MaybeUninit::slice_assume_init_mut(&mut self.buf.buf[self.buf.filled..self.buf.init]) - } - } - - /// Returns a mutable reference to the uninitialized part of the cursor. - /// - /// It is safe to uninitialize any of these bytes. - #[inline] - pub fn uninit_mut(&mut self) -> &mut [MaybeUninit<u8>] { - &mut self.buf.buf[self.buf.init..] - } - - /// Returns a mutable reference to the whole cursor. - /// - /// # Safety - /// - /// The caller must not uninitialize any bytes in the initialized portion of the cursor. - #[inline] - pub unsafe fn as_mut(&mut self) -> &mut [MaybeUninit<u8>] { - &mut self.buf.buf[self.buf.filled..] - } - - /// Advance the cursor by asserting that `n` bytes have been filled. - /// - /// After advancing, the `n` bytes are no longer accessible via the cursor and can only be - /// accessed via the underlying buffer. I.e., the buffer's filled portion grows by `n` elements - /// and its unfilled portion (and the capacity of this cursor) shrinks by `n` elements. - /// - /// # Safety - /// - /// The caller must ensure that the first `n` bytes of the cursor have been properly - /// initialised. - #[inline] - pub unsafe fn advance(&mut self, n: usize) -> &mut Self { - self.buf.filled += n; - self.buf.init = cmp::max(self.buf.init, self.buf.filled); - self - } - - /// Initializes all bytes in the cursor. - #[inline] - pub fn ensure_init(&mut self) -> &mut Self { - let uninit = self.uninit_mut(); - // SAFETY: 0 is a valid value for MaybeUninit<u8> and the length matches the allocation - // since it is comes from a slice reference. - unsafe { - ptr::write_bytes(uninit.as_mut_ptr(), 0, uninit.len()); - } - self.buf.init = self.buf.capacity(); - - self - } - - /// Asserts that the first `n` unfilled bytes of the cursor are initialized. - /// - /// `BorrowedBuf` assumes that bytes are never de-initialized, so this method does nothing when - /// called with fewer bytes than are already known to be initialized. - /// - /// # Safety - /// - /// The caller must ensure that the first `n` bytes of the buffer have already been initialized. - #[inline] - pub unsafe fn set_init(&mut self, n: usize) -> &mut Self { - self.buf.init = cmp::max(self.buf.init, self.buf.filled + n); - self - } - - /// Appends data to the cursor, advancing position within its buffer. - /// - /// # Panics - /// - /// Panics if `self.capacity()` is less than `buf.len()`. - #[inline] - pub fn append(&mut self, buf: &[u8]) { - assert!(self.capacity() >= buf.len()); - - // SAFETY: we do not de-initialize any of the elements of the slice - unsafe { - MaybeUninit::write_slice(&mut self.as_mut()[..buf.len()], buf); - } - - // SAFETY: We just added the entire contents of buf to the filled section. - unsafe { - self.set_init(buf.len()); - } - self.buf.filled += buf.len(); - } -} - -impl<'a> Write for BorrowedCursor<'a> { - fn write(&mut self, buf: &[u8]) -> Result<usize> { - self.append(buf); - Ok(buf.len()) - } - - #[inline] - fn flush(&mut self) -> Result<()> { - Ok(()) - } -} diff --git a/library/std/src/io/readbuf/tests.rs b/library/std/src/io/readbuf/tests.rs deleted file mode 100644 index 89a2f6b2271..00000000000 --- a/library/std/src/io/readbuf/tests.rs +++ /dev/null @@ -1,175 +0,0 @@ -use super::BorrowedBuf; -use crate::mem::MaybeUninit; - -/// Test that BorrowedBuf has the correct numbers when created with new -#[test] -fn new() { - let buf: &mut [_] = &mut [0; 16]; - let mut rbuf: BorrowedBuf<'_> = buf.into(); - - assert_eq!(rbuf.filled().len(), 0); - assert_eq!(rbuf.init_len(), 16); - assert_eq!(rbuf.capacity(), 16); - assert_eq!(rbuf.unfilled().capacity(), 16); -} - -/// Test that BorrowedBuf has the correct numbers when created with uninit -#[test] -fn uninit() { - let buf: &mut [_] = &mut [MaybeUninit::uninit(); 16]; - let mut rbuf: BorrowedBuf<'_> = buf.into(); - - assert_eq!(rbuf.filled().len(), 0); - assert_eq!(rbuf.init_len(), 0); - assert_eq!(rbuf.capacity(), 16); - assert_eq!(rbuf.unfilled().capacity(), 16); -} - -#[test] -fn initialize_unfilled() { - let buf: &mut [_] = &mut [MaybeUninit::uninit(); 16]; - let mut rbuf: BorrowedBuf<'_> = buf.into(); - - rbuf.unfilled().ensure_init(); - - assert_eq!(rbuf.init_len(), 16); -} - -#[test] -fn advance_filled() { - let buf: &mut [_] = &mut [0; 16]; - let mut rbuf: BorrowedBuf<'_> = buf.into(); - - unsafe { - rbuf.unfilled().advance(1); - } - - assert_eq!(rbuf.filled().len(), 1); - assert_eq!(rbuf.unfilled().capacity(), 15); -} - -#[test] -fn clear() { - let buf: &mut [_] = &mut [255; 16]; - let mut rbuf: BorrowedBuf<'_> = buf.into(); - - unsafe { - rbuf.unfilled().advance(16); - } - - assert_eq!(rbuf.filled().len(), 16); - assert_eq!(rbuf.unfilled().capacity(), 0); - - rbuf.clear(); - - assert_eq!(rbuf.filled().len(), 0); - assert_eq!(rbuf.unfilled().capacity(), 16); - - assert_eq!(rbuf.unfilled().init_ref(), [255; 16]); -} - -#[test] -fn set_init() { - let buf: &mut [_] = &mut [MaybeUninit::uninit(); 16]; - let mut rbuf: BorrowedBuf<'_> = buf.into(); - - unsafe { - rbuf.set_init(8); - } - - assert_eq!(rbuf.init_len(), 8); - - unsafe { - rbuf.unfilled().advance(4); - } - - unsafe { - rbuf.set_init(2); - } - - assert_eq!(rbuf.init_len(), 8); - - unsafe { - rbuf.set_init(8); - } - - assert_eq!(rbuf.init_len(), 8); -} - -#[test] -fn append() { - let buf: &mut [_] = &mut [MaybeUninit::new(255); 16]; - let mut rbuf: BorrowedBuf<'_> = buf.into(); - - rbuf.unfilled().append(&[0; 8]); - - assert_eq!(rbuf.init_len(), 8); - assert_eq!(rbuf.filled().len(), 8); - assert_eq!(rbuf.filled(), [0; 8]); - - rbuf.clear(); - - rbuf.unfilled().append(&[1; 16]); - - assert_eq!(rbuf.init_len(), 16); - assert_eq!(rbuf.filled().len(), 16); - assert_eq!(rbuf.filled(), [1; 16]); -} - -#[test] -fn reborrow_written() { - let buf: &mut [_] = &mut [MaybeUninit::new(0); 32]; - let mut buf: BorrowedBuf<'_> = buf.into(); - - let mut cursor = buf.unfilled(); - cursor.append(&[1; 16]); - - let mut cursor2 = cursor.reborrow(); - cursor2.append(&[2; 16]); - - assert_eq!(cursor2.written(), 32); - assert_eq!(cursor.written(), 32); - - assert_eq!(buf.unfilled().written(), 0); - assert_eq!(buf.init_len(), 32); - assert_eq!(buf.filled().len(), 32); - let filled = buf.filled(); - assert_eq!(&filled[..16], [1; 16]); - assert_eq!(&filled[16..], [2; 16]); -} - -#[test] -fn cursor_set_init() { - let buf: &mut [_] = &mut [MaybeUninit::uninit(); 16]; - let mut rbuf: BorrowedBuf<'_> = buf.into(); - - unsafe { - rbuf.unfilled().set_init(8); - } - - assert_eq!(rbuf.init_len(), 8); - assert_eq!(rbuf.unfilled().init_ref().len(), 8); - assert_eq!(rbuf.unfilled().init_mut().len(), 8); - assert_eq!(rbuf.unfilled().uninit_mut().len(), 8); - assert_eq!(unsafe { rbuf.unfilled().as_mut() }.len(), 16); - - unsafe { - rbuf.unfilled().advance(4); - } - - unsafe { - rbuf.unfilled().set_init(2); - } - - assert_eq!(rbuf.init_len(), 8); - - unsafe { - rbuf.unfilled().set_init(8); - } - - assert_eq!(rbuf.init_len(), 12); - assert_eq!(rbuf.unfilled().init_ref().len(), 8); - assert_eq!(rbuf.unfilled().init_mut().len(), 8); - assert_eq!(rbuf.unfilled().uninit_mut().len(), 4); - assert_eq!(unsafe { rbuf.unfilled().as_mut() }.len(), 12); -} diff --git a/library/std/src/lib.rs b/library/std/src/lib.rs index f57c8d4e7e2..d06012c14dc 100644 --- a/library/std/src/lib.rs +++ b/library/std/src/lib.rs @@ -227,7 +227,7 @@ test(no_crate_inject, attr(deny(warnings))), test(attr(allow(dead_code, deprecated, unused_variables, unused_mut))) )] -#![cfg_attr(not(bootstrap), doc(rust_logo))] +#![doc(rust_logo)] #![doc(cfg_hide( not(test), not(any(test, bootstrap)), @@ -310,6 +310,7 @@ // tidy-alphabetical-start #![feature(char_internals)] #![feature(core_intrinsics)] +#![feature(core_io_borrowed_buf)] #![feature(duration_constants)] #![feature(error_generic_member_access)] #![feature(error_in_core)] @@ -493,8 +494,6 @@ pub use core::convert; pub use core::default; #[stable(feature = "futures_api", since = "1.36.0")] pub use core::future; -#[stable(feature = "rust1", since = "1.0.0")] -pub use core::hash; #[stable(feature = "core_hint", since = "1.27.0")] pub use core::hint; #[stable(feature = "i128", since = "1.26.0")] @@ -564,6 +563,7 @@ pub mod env; pub mod error; pub mod ffi; pub mod fs; +pub mod hash; pub mod io; pub mod net; pub mod num; @@ -715,7 +715,7 @@ pub(crate) mod test_helpers { #[track_caller] pub(crate) fn test_rng() -> rand_xorshift::XorShiftRng { use core::hash::{BuildHasher, Hash, Hasher}; - let mut hasher = crate::collections::hash_map::RandomState::new().build_hasher(); + let mut hasher = crate::hash::RandomState::new().build_hasher(); core::panic::Location::caller().hash(&mut hasher); let hc64 = hasher.finish(); let seed_vec = hc64.to_le_bytes().into_iter().chain(0u8..8).collect::<Vec<u8>>(); diff --git a/library/std/src/os/ios/fs.rs b/library/std/src/os/ios/fs.rs index 0d2a7189032..e5df4de0b7f 100644 --- a/library/std/src/os/ios/fs.rs +++ b/library/std/src/os/ios/fs.rs @@ -144,14 +144,14 @@ impl MetadataExt for Metadata { } /// OS-specific extensions to [`fs::FileTimes`]. -#[stable(feature = "file_set_times", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "file_set_times", since = "1.75.0")] pub trait FileTimesExt: Sealed { /// Set the creation time of a file. - #[stable(feature = "file_set_times", since = "CURRENT_RUSTC_VERSION")] + #[stable(feature = "file_set_times", since = "1.75.0")] fn set_created(self, t: SystemTime) -> Self; } -#[stable(feature = "file_set_times", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "file_set_times", since = "1.75.0")] impl FileTimesExt for fs::FileTimes { fn set_created(mut self, t: SystemTime) -> Self { self.as_inner_mut().set_created(t.into_inner()); diff --git a/library/std/src/os/macos/fs.rs b/library/std/src/os/macos/fs.rs index 098b0733723..573426d1a86 100644 --- a/library/std/src/os/macos/fs.rs +++ b/library/std/src/os/macos/fs.rs @@ -150,14 +150,14 @@ impl MetadataExt for Metadata { } /// OS-specific extensions to [`fs::FileTimes`]. -#[stable(feature = "file_set_times", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "file_set_times", since = "1.75.0")] pub trait FileTimesExt: Sealed { /// Set the creation time of a file. - #[stable(feature = "file_set_times", since = "CURRENT_RUSTC_VERSION")] + #[stable(feature = "file_set_times", since = "1.75.0")] fn set_created(self, t: SystemTime) -> Self; } -#[stable(feature = "file_set_times", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "file_set_times", since = "1.75.0")] impl FileTimesExt for fs::FileTimes { fn set_created(mut self, t: SystemTime) -> Self { self.as_inner_mut().set_created(t.into_inner()); diff --git a/library/std/src/os/watchos/fs.rs b/library/std/src/os/watchos/fs.rs index 2838501817c..ee215dd5984 100644 --- a/library/std/src/os/watchos/fs.rs +++ b/library/std/src/os/watchos/fs.rs @@ -144,14 +144,14 @@ impl MetadataExt for Metadata { } /// OS-specific extensions to [`fs::FileTimes`]. -#[stable(feature = "file_set_times", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "file_set_times", since = "1.75.0")] pub trait FileTimesExt: Sealed { /// Set the creation time of a file. - #[stable(feature = "file_set_times", since = "CURRENT_RUSTC_VERSION")] + #[stable(feature = "file_set_times", since = "1.75.0")] fn set_created(self, t: SystemTime) -> Self; } -#[stable(feature = "file_set_times", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "file_set_times", since = "1.75.0")] impl FileTimesExt for fs::FileTimes { fn set_created(mut self, t: SystemTime) -> Self { self.as_inner_mut().set_created(t.into_inner()); diff --git a/library/std/src/os/windows/fs.rs b/library/std/src/os/windows/fs.rs index 3b591a35dd7..1b013d1c154 100644 --- a/library/std/src/os/windows/fs.rs +++ b/library/std/src/os/windows/fs.rs @@ -528,14 +528,14 @@ impl FileTypeExt for fs::FileType { } /// Windows-specific extensions to [`fs::FileTimes`]. -#[stable(feature = "file_set_times", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "file_set_times", since = "1.75.0")] pub trait FileTimesExt: Sealed { /// Set the creation time of a file. - #[stable(feature = "file_set_times", since = "CURRENT_RUSTC_VERSION")] + #[stable(feature = "file_set_times", since = "1.75.0")] fn set_created(self, t: SystemTime) -> Self; } -#[stable(feature = "file_set_times", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "file_set_times", since = "1.75.0")] impl FileTimesExt for fs::FileTimes { fn set_created(mut self, t: SystemTime) -> Self { self.as_inner_mut().set_created(t.into_inner()); diff --git a/library/std/src/path/tests.rs b/library/std/src/path/tests.rs index f12ffbf2e01..dbc0f7d9df3 100644 --- a/library/std/src/path/tests.rs +++ b/library/std/src/path/tests.rs @@ -1,8 +1,7 @@ use super::*; -use crate::collections::hash_map::DefaultHasher; use crate::collections::{BTreeSet, HashSet}; -use crate::hash::Hasher; +use crate::hash::{DefaultHasher, Hasher}; use crate::rc::Rc; use crate::sync::Arc; use core::hint::black_box; @@ -1461,8 +1460,7 @@ fn test_eq_receivers() { #[test] pub fn test_compare() { - use crate::collections::hash_map::DefaultHasher; - use crate::hash::{Hash, Hasher}; + use crate::hash::{DefaultHasher, Hash, Hasher}; fn hash<T: Hash>(t: T) -> u64 { let mut s = DefaultHasher::new(); diff --git a/library/std/src/process.rs b/library/std/src/process.rs index ad29eeb6a0b..af6bef1a76e 100644 --- a/library/std/src/process.rs +++ b/library/std/src/process.rs @@ -1961,7 +1961,7 @@ impl ExitCode { } /// The default value is [`ExitCode::SUCCESS`] -#[stable(feature = "process_exitcode_default", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "process_exitcode_default", since = "1.75.0")] impl Default for ExitCode { fn default() -> Self { ExitCode::SUCCESS diff --git a/library/std/src/sys/unix/fs.rs b/library/std/src/sys/unix/fs.rs index 40eb910fdc3..e3455cfef33 100644 --- a/library/std/src/sys/unix/fs.rs +++ b/library/std/src/sys/unix/fs.rs @@ -1300,13 +1300,17 @@ impl File { pub fn set_times(&self, times: FileTimes) -> io::Result<()> { #[cfg(not(any(target_os = "redox", target_os = "espidf", target_os = "horizon")))] - let to_timespec = |time: Option<SystemTime>| { - match time { - Some(time) if let Some(ts) = time.t.to_timespec() => Ok(ts), - Some(time) if time > crate::sys::time::UNIX_EPOCH => Err(io::const_io_error!(io::ErrorKind::InvalidInput, "timestamp is too large to set as a file time")), - Some(_) => Err(io::const_io_error!(io::ErrorKind::InvalidInput, "timestamp is too small to set as a file time")), - None => Ok(libc::timespec { tv_sec: 0, tv_nsec: libc::UTIME_OMIT as _ }), - } + let to_timespec = |time: Option<SystemTime>| match time { + Some(time) if let Some(ts) = time.t.to_timespec() => Ok(ts), + Some(time) if time > crate::sys::time::UNIX_EPOCH => Err(io::const_io_error!( + io::ErrorKind::InvalidInput, + "timestamp is too large to set as a file time" + )), + Some(_) => Err(io::const_io_error!( + io::ErrorKind::InvalidInput, + "timestamp is too small to set as a file time" + )), + None => Ok(libc::timespec { tv_sec: 0, tv_nsec: libc::UTIME_OMIT as _ }), }; cfg_if::cfg_if! { if #[cfg(any(target_os = "redox", target_os = "espidf", target_os = "horizon"))] { diff --git a/library/std/src/sys/unix/os.rs b/library/std/src/sys/unix/os.rs index dc3c037c0cb..077698a462c 100644 --- a/library/std/src/sys/unix/os.rs +++ b/library/std/src/sys/unix/os.rs @@ -274,15 +274,19 @@ pub fn current_exe() -> io::Result<PathBuf> { return path.canonicalize(); } // Search PWD to infer current_exe. - if let Some(pstr) = path.to_str() && pstr.contains("/") { + if let Some(pstr) = path.to_str() + && pstr.contains("/") + { return getcwd().map(|cwd| cwd.join(path))?.canonicalize(); } // Search PATH to infer current_exe. if let Some(p) = getenv(OsStr::from_bytes("PATH".as_bytes())) { for search_path in split_paths(&p) { let pb = search_path.join(&path); - if pb.is_file() && let Ok(metadata) = crate::fs::metadata(&pb) && - metadata.permissions().mode() & 0o111 != 0 { + if pb.is_file() + && let Ok(metadata) = crate::fs::metadata(&pb) + && metadata.permissions().mode() & 0o111 != 0 + { return pb.canonicalize(); } } diff --git a/library/std/src/sys/wasi/fs.rs b/library/std/src/sys/wasi/fs.rs index 437aae3ae7f..e8238665452 100644 --- a/library/std/src/sys/wasi/fs.rs +++ b/library/std/src/sys/wasi/fs.rs @@ -477,12 +477,13 @@ impl File { } pub fn set_times(&self, times: FileTimes) -> io::Result<()> { - let to_timestamp = |time: Option<SystemTime>| { - match time { - Some(time) if let Some(ts) = time.to_wasi_timestamp() => Ok(ts), - Some(_) => Err(io::const_io_error!(io::ErrorKind::InvalidInput, "timestamp is too large to set as a file time")), - None => Ok(0), - } + let to_timestamp = |time: Option<SystemTime>| match time { + Some(time) if let Some(ts) = time.to_wasi_timestamp() => Ok(ts), + Some(_) => Err(io::const_io_error!( + io::ErrorKind::InvalidInput, + "timestamp is too large to set as a file time" + )), + None => Ok(0), }; self.fd.filestat_set_times( to_timestamp(times.accessed)?, diff --git a/library/std/src/sys/windows/path.rs b/library/std/src/sys/windows/path.rs index 8c0e07b3566..f7f9f96ba5d 100644 --- a/library/std/src/sys/windows/path.rs +++ b/library/std/src/sys/windows/path.rs @@ -104,7 +104,9 @@ pub fn parse_prefix(path: &OsStr) -> Option<Prefix<'_>> { // The meaning of verbatim paths can change when they use a different // separator. - if let Some(parser) = parser.strip_prefix(r"?\") && !parser.prefix_bytes().iter().any(|&x| x == b'/') { + if let Some(parser) = parser.strip_prefix(r"?\") + && !parser.prefix_bytes().iter().any(|&x| x == b'/') + { // \\?\ if let Some(parser) = parser.strip_prefix(r"UNC\") { // \\?\UNC\server\share diff --git a/library/std/src/sys_common/once/futex.rs b/library/std/src/sys_common/once/futex.rs index 42db5fad4b4..609085dcd47 100644 --- a/library/std/src/sys_common/once/futex.rs +++ b/library/std/src/sys_common/once/futex.rs @@ -128,7 +128,8 @@ impl Once { RUNNING | QUEUED => { // Set the state to QUEUED if it is not already. if state == RUNNING - && let Err(new) = self.state.compare_exchange_weak(RUNNING, QUEUED, Relaxed, Acquire) + && let Err(new) = + self.state.compare_exchange_weak(RUNNING, QUEUED, Relaxed, Acquire) { state = new; continue; diff --git a/library/std/src/thread/mod.rs b/library/std/src/thread/mod.rs index 4097eb5549e..4b9ddd5aba1 100644 --- a/library/std/src/thread/mod.rs +++ b/library/std/src/thread/mod.rs @@ -548,10 +548,6 @@ impl Builder { let main = Box::new(main); // SAFETY: dynamic size and alignment of the Box remain the same. See below for why the // lifetime change is justified. - #[cfg(bootstrap)] - let main = - unsafe { mem::transmute::<Box<dyn FnOnce() + 'a>, Box<dyn FnOnce() + 'static>>(main) }; - #[cfg(not(bootstrap))] let main = unsafe { Box::from_raw(Box::into_raw(main) as *mut (dyn FnOnce() + 'static)) }; Ok(JoinInner { |
