From dbd03d4517e20940d29daaf198fb6ec8c99b1480 Mon Sep 17 00:00:00 2001 From: Slanterns Date: Tue, 16 Apr 2024 20:58:45 +0800 Subject: [PATCH 01/10] Stabilize `BinaryHeap::as_slice` --- alloc/src/collections/binary_heap/mod.rs | 3 +-- alloc/tests/lib.rs | 1 - 2 files changed, 1 insertion(+), 3 deletions(-) diff --git a/alloc/src/collections/binary_heap/mod.rs b/alloc/src/collections/binary_heap/mod.rs index 83b2678f7f52d..3c024649d3f5d 100644 --- a/alloc/src/collections/binary_heap/mod.rs +++ b/alloc/src/collections/binary_heap/mod.rs @@ -1207,7 +1207,6 @@ impl BinaryHeap { /// Basic usage: /// /// ``` - /// #![feature(binary_heap_as_slice)] /// use std::collections::BinaryHeap; /// use std::io::{self, Write}; /// @@ -1216,7 +1215,7 @@ impl BinaryHeap { /// io::sink().write(heap.as_slice()).unwrap(); /// ``` #[must_use] - #[unstable(feature = "binary_heap_as_slice", issue = "83659")] + #[stable(feature = "binary_heap_as_slice", since = "CURRENT_RUSTC_VERSION")] pub fn as_slice(&self) -> &[T] { self.data.as_slice() } diff --git a/alloc/tests/lib.rs b/alloc/tests/lib.rs index a34bce66496d8..37a02828901d1 100644 --- a/alloc/tests/lib.rs +++ b/alloc/tests/lib.rs @@ -26,7 +26,6 @@ #![feature(binary_heap_into_iter_sorted)] #![feature(binary_heap_drain_sorted)] #![feature(slice_ptr_get)] -#![feature(binary_heap_as_slice)] #![feature(inplace_iteration)] #![feature(iter_advance_by)] #![feature(iter_next_chunk)] From 1e8098b6dd497291aa08487c6ce9b3c9d1e6b7c5 Mon Sep 17 00:00:00 2001 From: Dion Dokter Date: Mon, 27 May 2024 11:08:21 +0200 Subject: [PATCH 02/10] Size optimize int formatting --- core/src/fmt/num.rs | 33 +++++++++++++++++++++++++++++++++ 1 file changed, 33 insertions(+) diff --git a/core/src/fmt/num.rs b/core/src/fmt/num.rs index ab2158394bf1e..3a5a5af8bf5d3 100644 --- a/core/src/fmt/num.rs +++ b/core/src/fmt/num.rs @@ -212,6 +212,7 @@ static DEC_DIGITS_LUT: &[u8; 200] = b"0001020304050607080910111213141516171819\ macro_rules! impl_Display { ($($t:ident),* as $u:ident via $conv_fn:ident named $name:ident) => { + #[cfg(not(feature = "optimize_for_size"))] fn $name(mut n: $u, is_nonnegative: bool, f: &mut fmt::Formatter<'_>) -> fmt::Result { // 2^128 is about 3*10^38, so 39 gives an extra byte of space let mut buf = [MaybeUninit::::uninit(); 39]; @@ -277,6 +278,38 @@ macro_rules! impl_Display { f.pad_integral(is_nonnegative, "", buf_slice) } + #[cfg(feature = "optimize_for_size")] + fn $name(mut n: $u, is_nonnegative: bool, f: &mut fmt::Formatter<'_>) -> fmt::Result { + // 2^128 is about 3*10^38, so 39 gives an extra byte of space + let mut buf = [MaybeUninit::::uninit(); 39]; + let mut curr = buf.len(); + let buf_ptr = MaybeUninit::slice_as_mut_ptr(&mut buf); + + // SAFETY: To show that it's OK to copy into `buf_ptr`, notice that at the beginning + // `curr == buf.len() == 39 > log(n)` since `n < 2^128 < 10^39`, and at + // each step this is kept the same as `n` is divided. Since `n` is always + // non-negative, this means that `curr > 0` so `buf_ptr[curr..curr + 1]` + // is safe to access. + unsafe { + loop { + curr -= 1; + buf_ptr.add(curr).write((n % 10) as u8 + b'0'); + n /= 10; + + if n == 0 { + break; + } + } + } + + // SAFETY: `curr` > 0 (since we made `buf` large enough), and all the chars are valid UTF-8 + let buf_slice = unsafe { + str::from_utf8_unchecked( + slice::from_raw_parts(buf_ptr.add(curr), buf.len() - curr)) + }; + f.pad_integral(is_nonnegative, "", buf_slice) + } + $(#[stable(feature = "rust1", since = "1.0.0")] impl fmt::Display for $t { #[allow(unused_comparisons)] From 85aa4b6ae530eb2be24a714b0dde882b80f50cf6 Mon Sep 17 00:00:00 2001 From: schvv31n Date: Tue, 4 Jun 2024 11:53:59 +0100 Subject: [PATCH 03/10] impl OsString::leak & PathBuf::leak --- std/src/ffi/os_str.rs | 19 +++++++++++++++++++ std/src/ffi/os_str/tests.rs | 7 +++++++ std/src/path.rs | 19 +++++++++++++++++++ std/src/path/tests.rs | 7 +++++++ std/src/sys/os_str/bytes.rs | 5 +++++ std/src/sys/os_str/wtf8.rs | 5 +++++ std/src/sys_common/wtf8.rs | 5 +++++ 7 files changed, 67 insertions(+) diff --git a/std/src/ffi/os_str.rs b/std/src/ffi/os_str.rs index 9dd3d7d3fa16a..f6b9de26c1c4d 100644 --- a/std/src/ffi/os_str.rs +++ b/std/src/ffi/os_str.rs @@ -533,6 +533,25 @@ impl OsString { unsafe { Box::from_raw(rw) } } + /// Consumes and leaks the `OsString`, returning a mutable reference to the contents, + /// `&'a mut OsStr`. + /// + /// The caller has free choice over the returned lifetime, including 'static. + /// Indeed, this function is ideally used for data that lives for the remainder of + /// the program’s life, as dropping the returned reference will cause a memory leak. + /// + /// It does not reallocate or shrink the `OsString`, so the leaked allocation may include + /// unused capacity that is not part of the returned slice. If you want to discard excess + /// capacity, call [`into_boxed_os_str`], and then [`Box::leak`] instead. + /// However, keep in mind that trimming the capacity may result in a reallocation and copy. + /// + /// [`into_boxed_os_str`]: Self::into_boxed_os_str + #[unstable(feature = "os_string_pathbuf_leak", issue = "125965")] + #[inline] + pub fn leak<'a>(self) -> &'a mut OsStr { + OsStr::from_inner_mut(self.inner.leak()) + } + /// Part of a hack to make PathBuf::push/pop more efficient. #[inline] pub(crate) fn as_mut_vec_for_path_buf(&mut self) -> &mut Vec { diff --git a/std/src/ffi/os_str/tests.rs b/std/src/ffi/os_str/tests.rs index b020e05eaab20..2379f0ba489e3 100644 --- a/std/src/ffi/os_str/tests.rs +++ b/std/src/ffi/os_str/tests.rs @@ -23,6 +23,13 @@ fn test_os_string_clear() { assert_eq!(0, os_string.inner.as_inner().len()); } +#[test] +fn test_os_string_leak() { + let os_string = OsString::from("have a cake"); + let leaked = os_string.leak(); + assert_eq!(leaked.as_encoded_bytes(), b"have a cake"); +} + #[test] fn test_os_string_capacity() { let os_string = OsString::with_capacity(0); diff --git a/std/src/path.rs b/std/src/path.rs index f4e1e2a38c106..adbcdcd2e67e3 100644 --- a/std/src/path.rs +++ b/std/src/path.rs @@ -1226,6 +1226,25 @@ impl PathBuf { self } + /// Consumes and leaks the `PathBuf`, returning a mutable reference to the contents, + /// `&'a mut Path`. + /// + /// The caller has free choice over the returned lifetime, including 'static. + /// Indeed, this function is ideally used for data that lives for the remainder of + /// the program’s life, as dropping the returned reference will cause a memory leak. + /// + /// It does not reallocate or shrink the `PathBuf`, so the leaked allocation may include + /// unused capacity that is not part of the returned slice. If you want to discard excess + /// capacity, call [`into_boxed_path`], and then [`Box::leak`] instead. + /// However, keep in mind that trimming the capacity may result in a reallocation and copy. + /// + /// [`into_boxed_path`]: Self::into_boxed_path + #[unstable(feature = "os_string_pathbuf_leak", issue = "125965")] + #[inline] + pub fn leak<'a>(self) -> &'a mut Path { + Path::from_inner_mut(self.inner.leak()) + } + /// Extends `self` with `path`. /// /// If `path` is absolute, it replaces the current path. diff --git a/std/src/path/tests.rs b/std/src/path/tests.rs index 2d8e50d1f88e9..d29f895ba38ff 100644 --- a/std/src/path/tests.rs +++ b/std/src/path/tests.rs @@ -126,6 +126,13 @@ fn into() { assert_eq!(static_cow_path, owned_cow_path); } +#[test] +fn test_pathbuf_leak() { + let buf = PathBuf::from("/have/a/cake".to_owned()); + let leaked = buf.leak(); + assert_eq!(leaked.as_os_str().as_encoded_bytes(), b"/have/a/cake"); +} + #[test] #[cfg(unix)] pub fn test_decompositions_unix() { diff --git a/std/src/sys/os_str/bytes.rs b/std/src/sys/os_str/bytes.rs index 18b969bca85a6..f7c6b0877aa62 100644 --- a/std/src/sys/os_str/bytes.rs +++ b/std/src/sys/os_str/bytes.rs @@ -176,6 +176,11 @@ impl Buf { self.inner.extend_from_slice(&s.inner) } + #[inline] + pub fn leak<'a>(self) -> &'a mut Slice { + unsafe { mem::transmute(self.inner.leak()) } + } + #[inline] pub fn into_box(self) -> Box { unsafe { mem::transmute(self.inner.into_boxed_slice()) } diff --git a/std/src/sys/os_str/wtf8.rs b/std/src/sys/os_str/wtf8.rs index b3ceb55802dc5..dfff4dd4fb023 100644 --- a/std/src/sys/os_str/wtf8.rs +++ b/std/src/sys/os_str/wtf8.rs @@ -138,6 +138,11 @@ impl Buf { self.inner.shrink_to(min_capacity) } + #[inline] + pub fn leak<'a>(self) -> &'a mut Slice { + unsafe { mem::transmute(self.inner.leak()) } + } + #[inline] pub fn into_box(self) -> Box { unsafe { mem::transmute(self.inner.into_box()) } diff --git a/std/src/sys_common/wtf8.rs b/std/src/sys_common/wtf8.rs index 38e15f9f54960..bb1e505285bf1 100644 --- a/std/src/sys_common/wtf8.rs +++ b/std/src/sys_common/wtf8.rs @@ -325,6 +325,11 @@ impl Wtf8Buf { self.bytes.shrink_to(min_capacity) } + #[inline] + pub fn leak<'a>(self) -> &'a mut Wtf8 { + unsafe { Wtf8::from_mut_bytes_unchecked(self.bytes.leak()) } + } + /// Returns the number of bytes that this string buffer can hold without reallocating. #[inline] pub fn capacity(&self) -> usize { From 91c8b2316644c6f9dc111937c6269fd69277cdac Mon Sep 17 00:00:00 2001 From: Chris Denton Date: Wed, 5 Jun 2024 13:53:46 +0000 Subject: [PATCH 04/10] Update `./x fmt` command --- std/src/sys/pal/windows/c/README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/std/src/sys/pal/windows/c/README.md b/std/src/sys/pal/windows/c/README.md index d458e55efbcdd..efefc5faba7a4 100644 --- a/std/src/sys/pal/windows/c/README.md +++ b/std/src/sys/pal/windows/c/README.md @@ -3,7 +3,7 @@ be edited manually. To add bindings, edit `bindings.txt` then regenerate using the following command: - ./x run generate-windows-sys && ./x fmt library/std + ./x run generate-windows-sys && ./x fmt If you need to override generated functions or types then add them to `library/std/src/sys/pal/windows/c.rs`. From dfddd7e5a864be2075c6ceb6e0887a2ddc31ca04 Mon Sep 17 00:00:00 2001 From: Daniel Sedlak Date: Thu, 6 Jun 2024 20:01:59 +0200 Subject: [PATCH 05/10] Stabilize Option::take_if --- core/src/option.rs | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/core/src/option.rs b/core/src/option.rs index 9a527073602e6..e253cfd2822be 100644 --- a/core/src/option.rs +++ b/core/src/option.rs @@ -1708,8 +1708,6 @@ impl Option { /// # Examples /// /// ``` - /// #![feature(option_take_if)] - /// /// let mut x = Some(42); /// /// let prev = x.take_if(|v| if *v == 42 { @@ -1726,7 +1724,7 @@ impl Option { /// assert_eq!(prev, Some(43)); /// ``` #[inline] - #[unstable(feature = "option_take_if", issue = "98934")] + #[stable(feature = "option_take_if", since = "CURRENT_RUSTC_VERSION")] pub fn take_if

(&mut self, predicate: P) -> Option where P: FnOnce(&mut T) -> bool, From 20f15f4d41a9f99cf6ee6371c2f2194003bb35b7 Mon Sep 17 00:00:00 2001 From: schvv31n Date: Thu, 6 Jun 2024 23:16:39 +0100 Subject: [PATCH 06/10] fixed memory leaks in PathBuf::leak & OsString::leak tests --- std/src/ffi/os_str/tests.rs | 2 ++ std/src/path/tests.rs | 5 ++++- 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/std/src/ffi/os_str/tests.rs b/std/src/ffi/os_str/tests.rs index 2379f0ba489e3..5b39b9e34d8c7 100644 --- a/std/src/ffi/os_str/tests.rs +++ b/std/src/ffi/os_str/tests.rs @@ -26,8 +26,10 @@ fn test_os_string_clear() { #[test] fn test_os_string_leak() { let os_string = OsString::from("have a cake"); + let (len, cap) = (os_string.len(), os_string.capacity()); let leaked = os_string.leak(); assert_eq!(leaked.as_encoded_bytes(), b"have a cake"); + unsafe { drop(String::from_raw_parts(leaked as *mut OsStr as _, len, cap)) } } #[test] diff --git a/std/src/path/tests.rs b/std/src/path/tests.rs index d29f895ba38ff..92702b395dfe1 100644 --- a/std/src/path/tests.rs +++ b/std/src/path/tests.rs @@ -128,9 +128,12 @@ fn into() { #[test] fn test_pathbuf_leak() { - let buf = PathBuf::from("/have/a/cake".to_owned()); + let string = "/have/a/cake".to_owned(); + let (len, cap) = (string.len(), string.capacity()); + let buf = PathBuf::from(string); let leaked = buf.leak(); assert_eq!(leaked.as_os_str().as_encoded_bytes(), b"/have/a/cake"); + unsafe { drop(String::from_raw_parts(leaked.as_mut_os_str() as *mut OsStr as _, len, cap)) } } #[test] From 3f4816887c7752b5c2fb33ece1fd37298f06577f Mon Sep 17 00:00:00 2001 From: Slanterns Date: Tue, 4 Jun 2024 05:26:55 +0800 Subject: [PATCH 07/10] Stabilize `error_in_core` --- alloc/src/lib.rs | 1 - core/src/error.rs | 12 +----------- core/tests/lib.rs | 1 - std/src/lib.rs | 1 - 4 files changed, 1 insertion(+), 14 deletions(-) diff --git a/alloc/src/lib.rs b/alloc/src/lib.rs index 4ac0c9b15be7a..4749b8880fbc4 100644 --- a/alloc/src/lib.rs +++ b/alloc/src/lib.rs @@ -121,7 +121,6 @@ #![feature(deref_pure_trait)] #![feature(dispatch_from_dyn)] #![feature(error_generic_member_access)] -#![feature(error_in_core)] #![feature(exact_size_is_empty)] #![feature(extend_one)] #![feature(fmt_internals)] diff --git a/core/src/error.rs b/core/src/error.rs index a3f2b767054e1..99f10e6d9d104 100644 --- a/core/src/error.rs +++ b/core/src/error.rs @@ -1,5 +1,5 @@ #![doc = include_str!("error.md")] -#![unstable(feature = "error_in_core", issue = "103765")] +#![stable(feature = "error_in_core", since = "CURRENT_RUSTC_VERSION")] #[cfg(test)] mod tests; @@ -130,7 +130,6 @@ pub trait Error: Debug + Display { /// /// ```rust /// #![feature(error_generic_member_access)] - /// #![feature(error_in_core)] /// use core::fmt; /// use core::error::{request_ref, Request}; /// @@ -362,7 +361,6 @@ impl dyn Error { /// /// ```rust /// # #![feature(error_generic_member_access)] -/// # #![feature(error_in_core)] /// use std::error::Error; /// use core::error::request_value; /// @@ -386,7 +384,6 @@ where /// /// ```rust /// # #![feature(error_generic_member_access)] -/// # #![feature(error_in_core)] /// use core::error::Error; /// use core::error::request_ref; /// @@ -458,7 +455,6 @@ where /// /// ``` /// #![feature(error_generic_member_access)] -/// #![feature(error_in_core)] /// use core::fmt; /// use core::error::Request; /// use core::error::request_ref; @@ -529,7 +525,6 @@ impl<'a> Request<'a> { /// /// ```rust /// #![feature(error_generic_member_access)] - /// #![feature(error_in_core)] /// /// use core::error::Request; /// @@ -564,7 +559,6 @@ impl<'a> Request<'a> { /// /// ```rust /// #![feature(error_generic_member_access)] - /// #![feature(error_in_core)] /// /// use core::error::Request; /// @@ -600,7 +594,6 @@ impl<'a> Request<'a> { /// /// ```rust /// #![feature(error_generic_member_access)] - /// #![feature(error_in_core)] /// /// use core::error::Request; /// @@ -633,7 +626,6 @@ impl<'a> Request<'a> { /// /// ```rust /// #![feature(error_generic_member_access)] - /// #![feature(error_in_core)] /// /// use core::error::Request; /// @@ -700,7 +692,6 @@ impl<'a> Request<'a> { /// /// ```rust /// #![feature(error_generic_member_access)] - /// #![feature(error_in_core)] /// /// use core::error::Request; /// use core::error::request_value; @@ -788,7 +779,6 @@ impl<'a> Request<'a> { /// /// ```rust /// #![feature(error_generic_member_access)] - /// #![feature(error_in_core)] /// /// use core::error::Request; /// use core::error::request_ref; diff --git a/core/tests/lib.rs b/core/tests/lib.rs index 20ff6fd7687fe..f632883b563d3 100644 --- a/core/tests/lib.rs +++ b/core/tests/lib.rs @@ -112,7 +112,6 @@ #![feature(const_slice_from_ref)] #![feature(waker_getters)] #![feature(error_generic_member_access)] -#![feature(error_in_core)] #![feature(trait_upcasting)] #![feature(is_ascii_octdigit)] #![feature(get_many_mut)] diff --git a/std/src/lib.rs b/std/src/lib.rs index 9d6576fa84117..1c226f9f08f10 100644 --- a/std/src/lib.rs +++ b/std/src/lib.rs @@ -324,7 +324,6 @@ #![feature(core_io_borrowed_buf)] #![feature(duration_constants)] #![feature(error_generic_member_access)] -#![feature(error_in_core)] #![feature(error_iter)] #![feature(exact_size_is_empty)] #![feature(exclusive_wrapper)] From 7014731c32e05cc36afb8caa76d1fba5859b7b00 Mon Sep 17 00:00:00 2001 From: Slanterns Date: Tue, 4 Jun 2024 05:33:03 +0800 Subject: [PATCH 08/10] fix doc comments about `error_generic_member_access` --- core/src/error.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/core/src/error.rs b/core/src/error.rs index 99f10e6d9d104..da18fdc6e1d1f 100644 --- a/core/src/error.rs +++ b/core/src/error.rs @@ -360,7 +360,7 @@ impl dyn Error { /// Get a string value from an error. /// /// ```rust -/// # #![feature(error_generic_member_access)] +/// #![feature(error_generic_member_access)] /// use std::error::Error; /// use core::error::request_value; /// @@ -383,7 +383,7 @@ where /// Get a string reference from an error. /// /// ```rust -/// # #![feature(error_generic_member_access)] +/// #![feature(error_generic_member_access)] /// use core::error::Error; /// use core::error::request_ref; /// From cd73cbea88a8455819da3fa18cfaf42e3a4c1385 Mon Sep 17 00:00:00 2001 From: Jubilee Young Date: Thu, 6 Jun 2024 22:50:28 -0700 Subject: [PATCH 09/10] Update backtrace to 0.3.73 --- backtrace | 2 +- std/Cargo.toml | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/backtrace b/backtrace index 5e05efa87905f..72265bea21089 160000 --- a/backtrace +++ b/backtrace @@ -1 +1 @@ -Subproject commit 5e05efa87905fb5b351a2bc5644d60c57d6d9327 +Subproject commit 72265bea210891ae47bbe6d4f17b493ef0606619 diff --git a/std/Cargo.toml b/std/Cargo.toml index 79a504c5a5e2c..68bba5c2be112 100644 --- a/std/Cargo.toml +++ b/std/Cargo.toml @@ -34,10 +34,10 @@ addr2line = { version = "0.22.0", optional = true, default-features = false } libc = { version = "0.2.153", default-features = false, features = ['rustc-dep-of-std'], public = true } [target.'cfg(all(not(target_os = "aix"), not(all(windows, target_env = "msvc", not(target_vendor = "uwp")))))'.dependencies] -object = { version = "0.32.0", default-features = false, optional = true, features = ['read_core', 'elf', 'macho', 'pe', 'unaligned', 'archive'] } +object = { version = "0.36.0", default-features = false, optional = true, features = ['read_core', 'elf', 'macho', 'pe', 'unaligned', 'archive'] } [target.'cfg(target_os = "aix")'.dependencies] -object = { version = "0.32.0", default-features = false, optional = true, features = ['read_core', 'xcoff', 'unaligned', 'archive'] } +object = { version = "0.36.0", default-features = false, optional = true, features = ['read_core', 'xcoff', 'unaligned', 'archive'] } [dev-dependencies] rand = { version = "0.8.5", default-features = false, features = ["alloc"] } From 4655eca9735182b70565ae0a5be0bf443534ba07 Mon Sep 17 00:00:00 2001 From: Walter Kalata Date: Fri, 7 Jun 2024 12:18:43 -0700 Subject: [PATCH 10/10] Fix typo in docs for std::pin --- core/src/pin.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/core/src/pin.rs b/core/src/pin.rs index d8fc3b7177f38..0d2aa3070a19f 100644 --- a/core/src/pin.rs +++ b/core/src/pin.rs @@ -184,7 +184,7 @@ //! requires at least a level of pointer indirection each time a new object is added to the mix //! (and, practically, a heap allocation). //! -//! Although there were other reason as well, this issue of expensive composition is the key thing +//! Although there were other reasons as well, this issue of expensive composition is the key thing //! that drove Rust towards adopting a different model. It is particularly a problem //! when one considers, for example, the implications of composing together the [`Future`]s which //! will eventually make up an asynchronous task (including address-sensitive `async fn` state