From 0d4a80eaee3544af8f9f00e4a8d1f0749115633a Mon Sep 17 00:00:00 2001 From: Alex Crichton Date: Thu, 5 Sep 2024 09:31:17 -0700 Subject: [PATCH 01/11] Update compiler-builtins to 0.1.125 This commit updates the compiler-builtins crate from 0.1.123 to 0.1.125. The changes in this update are: * https://github.com/rust-lang/compiler-builtins/pull/682 * https://github.com/rust-lang/compiler-builtins/pull/678 * https://github.com/rust-lang/compiler-builtins/pull/685 --- Cargo.lock | 4 ++-- alloc/Cargo.toml | 2 +- std/Cargo.toml | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 54ad052c52322..ded30dd82f7b4 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -58,9 +58,9 @@ dependencies = [ [[package]] name = "compiler_builtins" -version = "0.1.123" +version = "0.1.125" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b47fcbecb558bdad78c7d3a998523c60a50dd6cd046d5fe74163e309e878fff7" +checksum = "bd02a01d7bc069bed818e956600fe437ee222dd1d6ad92bfb9db87b43b71fd87" dependencies = [ "cc", "rustc-std-workspace-core", diff --git a/alloc/Cargo.toml b/alloc/Cargo.toml index 1bd4434d4f7e9..1da947d196fd6 100644 --- a/alloc/Cargo.toml +++ b/alloc/Cargo.toml @@ -10,7 +10,7 @@ edition = "2021" [dependencies] core = { path = "../core" } -compiler_builtins = { version = "0.1.123", features = ['rustc-dep-of-std'] } +compiler_builtins = { version = "0.1.125", features = ['rustc-dep-of-std'] } [dev-dependencies] rand = { version = "0.8.5", default-features = false, features = ["alloc"] } diff --git a/std/Cargo.toml b/std/Cargo.toml index e20fe9feff114..9a31fd21dc71a 100644 --- a/std/Cargo.toml +++ b/std/Cargo.toml @@ -17,7 +17,7 @@ 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.123" } +compiler_builtins = { version = "0.1.125" } profiler_builtins = { path = "../profiler_builtins", optional = true } unwind = { path = "../unwind" } hashbrown = { version = "0.14", default-features = false, features = [ From e954412fd46d8ee1f51ebd694719b7efb1b7bab8 Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Sun, 8 Sep 2024 08:45:41 +0200 Subject: [PATCH 02/11] remove pointless rustc_const_unstable on trait impls --- core/src/ptr/alignment.rs | 2 -- 1 file changed, 2 deletions(-) diff --git a/core/src/ptr/alignment.rs b/core/src/ptr/alignment.rs index 19fe03d57cc0a..834cec9dcfc26 100644 --- a/core/src/ptr/alignment.rs +++ b/core/src/ptr/alignment.rs @@ -199,7 +199,6 @@ impl From for usize { } } -#[rustc_const_unstable(feature = "const_alloc_layout", issue = "67521")] #[unstable(feature = "ptr_alignment_type", issue = "102070")] impl cmp::Ord for Alignment { #[inline] @@ -208,7 +207,6 @@ impl cmp::Ord for Alignment { } } -#[rustc_const_unstable(feature = "const_alloc_layout", issue = "67521")] #[unstable(feature = "ptr_alignment_type", issue = "102070")] impl cmp::PartialOrd for Alignment { #[inline] From 9849587e9b4a54990081fac4c891228b45ef61b5 Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Sun, 8 Sep 2024 16:35:34 +0200 Subject: [PATCH 03/11] add FIXME(const-hack) --- alloc/src/collections/vec_deque/mod.rs | 4 ++-- alloc/src/raw_vec.rs | 15 +-------------- alloc/src/vec/in_place_collect.rs | 2 +- alloc/src/vec/into_iter.rs | 2 +- alloc/src/vec/mod.rs | 2 +- core/src/char/convert.rs | 2 +- core/src/char/methods.rs | 2 +- core/src/num/mod.rs | 2 +- core/src/option.rs | 24 +++++++----------------- core/src/slice/index.rs | 9 ++++++--- core/src/slice/mod.rs | 6 +++--- core/src/str/converts.rs | 4 ++-- core/src/str/error.rs | 2 +- core/src/time.rs | 2 ++ core/src/unicode/unicode_data.rs | 6 ++---- core/tests/hash/mod.rs | 7 ++----- std/src/sys/pal/windows/args.rs | 2 +- 17 files changed, 35 insertions(+), 58 deletions(-) diff --git a/alloc/src/collections/vec_deque/mod.rs b/alloc/src/collections/vec_deque/mod.rs index dc725ec0f56e4..8c9db063105ce 100644 --- a/alloc/src/collections/vec_deque/mod.rs +++ b/alloc/src/collections/vec_deque/mod.rs @@ -554,8 +554,8 @@ impl VecDeque { #[rustc_const_stable(feature = "const_vec_deque_new", since = "1.68.0")] #[must_use] pub const fn new() -> VecDeque { - // FIXME: This should just be `VecDeque::new_in(Global)` once that hits stable. - VecDeque { head: 0, len: 0, buf: RawVec::NEW } + // FIXME(const-hack): This should just be `VecDeque::new_in(Global)` once that hits stable. + VecDeque { head: 0, len: 0, buf: RawVec::new() } } /// Creates an empty deque with space for at least `capacity` elements. diff --git a/alloc/src/raw_vec.rs b/alloc/src/raw_vec.rs index a651ba067e47c..436e0596e3d5e 100644 --- a/alloc/src/raw_vec.rs +++ b/alloc/src/raw_vec.rs @@ -96,13 +96,6 @@ struct RawVecInner { } impl RawVec { - /// HACK(Centril): This exists because stable `const fn` can only call stable `const fn`, so - /// they cannot call `Self::new()`. - /// - /// If you change `RawVec::new` or dependencies, please take care to not introduce anything - /// that would truly const-call something unstable. - pub const NEW: Self = Self::new(); - /// Creates the biggest possible `RawVec` (on the system heap) /// without allocating. If `T` has positive size, then this makes a /// `RawVec` with capacity `0`. If `T` is zero-sized, then it makes a @@ -111,7 +104,7 @@ impl RawVec { #[must_use] #[rustc_const_stable(feature = "raw_vec_internals_const", since = "1.81")] pub const fn new() -> Self { - Self { inner: RawVecInner::new::(), _marker: PhantomData } + Self::new_in(Global) } /// Creates a `RawVec` (on the system heap) with exactly the @@ -149,12 +142,6 @@ impl RawVec { } impl RawVecInner { - #[must_use] - #[rustc_const_stable(feature = "raw_vec_internals_const", since = "1.81")] - const fn new() -> Self { - Self::new_in(Global, core::mem::align_of::()) - } - #[cfg(not(any(no_global_oom_handling, test)))] #[must_use] #[inline] diff --git a/alloc/src/vec/in_place_collect.rs b/alloc/src/vec/in_place_collect.rs index d119e6ca397c5..2604843994506 100644 --- a/alloc/src/vec/in_place_collect.rs +++ b/alloc/src/vec/in_place_collect.rs @@ -191,7 +191,7 @@ const fn in_place_collectible( const fn needs_realloc(src_cap: usize, dst_cap: usize) -> bool { if const { mem::align_of::() != mem::align_of::() } { - // FIXME: use unreachable! once that works in const + // FIXME(const-hack): use unreachable! once that works in const panic!("in_place_collectible() prevents this"); } diff --git a/alloc/src/vec/into_iter.rs b/alloc/src/vec/into_iter.rs index fad8abad49353..487d5cc7224bc 100644 --- a/alloc/src/vec/into_iter.rs +++ b/alloc/src/vec/into_iter.rs @@ -142,7 +142,7 @@ impl IntoIter { // struct and then overwriting &mut self. // this creates less assembly self.cap = 0; - self.buf = RawVec::NEW.non_null(); + self.buf = RawVec::new().non_null(); self.ptr = self.buf; self.end = self.buf.as_ptr(); diff --git a/alloc/src/vec/mod.rs b/alloc/src/vec/mod.rs index 162791ba59d03..ff084edba8dc8 100644 --- a/alloc/src/vec/mod.rs +++ b/alloc/src/vec/mod.rs @@ -419,7 +419,7 @@ impl Vec { #[stable(feature = "rust1", since = "1.0.0")] #[must_use] pub const fn new() -> Self { - Vec { buf: RawVec::NEW, len: 0 } + Vec { buf: RawVec::new(), len: 0 } } /// Constructs a new, empty `Vec` with at least the specified capacity. diff --git a/core/src/char/convert.rs b/core/src/char/convert.rs index f0c2636307fcf..73ab4f1e52ade 100644 --- a/core/src/char/convert.rs +++ b/core/src/char/convert.rs @@ -11,7 +11,7 @@ use crate::ub_checks::assert_unsafe_precondition; #[must_use] #[inline] pub(super) const fn from_u32(i: u32) -> Option { - // FIXME: once Result::ok is const fn, use it here + // FIXME(const-hack): once Result::ok is const fn, use it here match char_try_from_u32(i) { Ok(c) => Some(c), Err(_) => None, diff --git a/core/src/char/methods.rs b/core/src/char/methods.rs index 41a19665779b6..6e7494af12f8e 100644 --- a/core/src/char/methods.rs +++ b/core/src/char/methods.rs @@ -386,7 +386,7 @@ impl char { // Force the 6th bit to be set to ensure ascii is lower case. digit = (self as u32 | 0b10_0000).wrapping_sub('a' as u32).saturating_add(10); } - // FIXME: once then_some is const fn, use it here + // FIXME(const-hack): once then_some is const fn, use it here if digit < radix { Some(digit) } else { None } } diff --git a/core/src/num/mod.rs b/core/src/num/mod.rs index 37c9db7f474b5..dca644ebef4ad 100644 --- a/core/src/num/mod.rs +++ b/core/src/num/mod.rs @@ -6,7 +6,7 @@ use crate::str::FromStr; use crate::ub_checks::assert_unsafe_precondition; use crate::{ascii, intrinsics, mem}; -// Used because the `?` operator is not allowed in a const context. +// FIXME(const-hack): Used because the `?` operator is not allowed in a const context. macro_rules! try_opt { ($e:expr) => { match $e { diff --git a/core/src/option.rs b/core/src/option.rs index 212e4f0215463..18604a8ae3532 100644 --- a/core/src/option.rs +++ b/core/src/option.rs @@ -739,6 +739,7 @@ impl Option { #[stable(feature = "pin", since = "1.33.0")] #[rustc_const_unstable(feature = "const_option_ext", issue = "91930")] pub const fn as_pin_ref(self: Pin<&Self>) -> Option> { + // FIXME(const-hack): use `map` once that is possible match Pin::get_ref(self).as_ref() { // SAFETY: `x` is guaranteed to be pinned because it comes from `self` // which is pinned. @@ -758,6 +759,7 @@ impl Option { // SAFETY: `get_unchecked_mut` is never used to move the `Option` inside `self`. // `x` is guaranteed to be pinned because it comes from `self` which is pinned. unsafe { + // FIXME(const-hack): use `map` once that is possible match Pin::get_unchecked_mut(self).as_mut() { Some(x) => Some(Pin::new_unchecked(x)), None => None, @@ -1290,10 +1292,7 @@ impl Option { where T: Deref, { - match self.as_ref() { - Some(t) => Some(t.deref()), - None => None, - } + self.as_ref().map(|t| t.deref()) } /// Converts from `Option` (or `&mut Option`) to `Option<&mut T::Target>`. @@ -1316,10 +1315,7 @@ impl Option { where T: DerefMut, { - match self.as_mut() { - Some(t) => Some(t.deref_mut()), - None => None, - } + self.as_mut().map(|t| t.deref_mut()) } ///////////////////////////////////////////////////////////////////////// @@ -1633,13 +1629,7 @@ impl Option { #[inline] #[stable(feature = "option_entry", since = "1.20.0")] pub fn get_or_insert(&mut self, value: T) -> &mut T { - if let None = *self { - *self = Some(value); - } - - // SAFETY: a `None` variant for `self` would have been replaced by a `Some` - // variant in the code above. - unsafe { self.as_mut().unwrap_unchecked() } + self.get_or_insert_with(|| value) } /// Inserts the default value into the option if it is [`None`], then @@ -1725,7 +1715,7 @@ impl Option { #[stable(feature = "rust1", since = "1.0.0")] #[rustc_const_unstable(feature = "const_option", issue = "67441")] pub const fn take(&mut self) -> Option { - // FIXME replace `mem::replace` by `mem::take` when the latter is const ready + // FIXME(const-hack) replace `mem::replace` by `mem::take` when the latter is const ready mem::replace(self, None) } @@ -1894,7 +1884,7 @@ impl Option<&T> { where T: Copy, { - // FIXME: this implementation, which sidesteps using `Option::map` since it's not const + // FIXME(const-hack): this implementation, which sidesteps using `Option::map` since it's not const // ready yet, should be reverted when possible to avoid code repetition match self { Some(&v) => Some(v), diff --git a/core/src/slice/index.rs b/core/src/slice/index.rs index de1492e82ce7d..7adcee1ed6b64 100644 --- a/core/src/slice/index.rs +++ b/core/src/slice/index.rs @@ -33,10 +33,11 @@ where #[track_caller] #[rustc_const_unstable(feature = "const_slice_index", issue = "none")] const fn slice_start_index_len_fail(index: usize, len: usize) -> ! { + // FIXME(const-hack): once integer formatting in panics is possible, we + // should use the same implementation at compiletime and runtime. const_eval_select((index, len), slice_start_index_len_fail_ct, slice_start_index_len_fail_rt) } -// FIXME const-hack #[inline] #[track_caller] fn slice_start_index_len_fail_rt(index: usize, len: usize) -> ! { @@ -54,10 +55,11 @@ const fn slice_start_index_len_fail_ct(_: usize, _: usize) -> ! { #[track_caller] #[rustc_const_unstable(feature = "const_slice_index", issue = "none")] const fn slice_end_index_len_fail(index: usize, len: usize) -> ! { + // FIXME(const-hack): once integer formatting in panics is possible, we + // should use the same implementation at compiletime and runtime. const_eval_select((index, len), slice_end_index_len_fail_ct, slice_end_index_len_fail_rt) } -// FIXME const-hack #[inline] #[track_caller] fn slice_end_index_len_fail_rt(index: usize, len: usize) -> ! { @@ -75,10 +77,11 @@ const fn slice_end_index_len_fail_ct(_: usize, _: usize) -> ! { #[track_caller] #[rustc_const_unstable(feature = "const_slice_index", issue = "none")] const fn slice_index_order_fail(index: usize, end: usize) -> ! { + // FIXME(const-hack): once integer formatting in panics is possible, we + // should use the same implementation at compiletime and runtime. const_eval_select((index, end), slice_index_order_fail_ct, slice_index_order_fail_rt) } -// FIXME const-hack #[inline] #[track_caller] fn slice_index_order_fail_rt(index: usize, end: usize) -> ! { diff --git a/core/src/slice/mod.rs b/core/src/slice/mod.rs index 166189f4b6cf3..3a02966a168a7 100644 --- a/core/src/slice/mod.rs +++ b/core/src/slice/mod.rs @@ -529,7 +529,7 @@ impl [T] { None } else { // SAFETY: We manually verified the bounds of the slice. - // FIXME: Without const traits, we need this instead of `get_unchecked`. + // FIXME(const-hack): Without const traits, we need this instead of `get_unchecked`. let last = unsafe { self.split_at_unchecked(self.len() - N).1 }; // SAFETY: We explicitly check for the correct number of elements, @@ -563,7 +563,7 @@ impl [T] { None } else { // SAFETY: We manually verified the bounds of the slice. - // FIXME: Without const traits, we need this instead of `get_unchecked`. + // FIXME(const-hack): Without const traits, we need this instead of `get_unchecked`. let last = unsafe { self.split_at_mut_unchecked(self.len() - N).1 }; // SAFETY: We explicitly check for the correct number of elements, @@ -1952,7 +1952,7 @@ impl [T] { #[inline] #[must_use] pub const unsafe fn split_at_unchecked(&self, mid: usize) -> (&[T], &[T]) { - // HACK: the const function `from_raw_parts` is used to make this + // FIXME(const-hack): the const function `from_raw_parts` is used to make this // function const; previously the implementation used // `(self.get_unchecked(..mid), self.get_unchecked(mid..))` diff --git a/core/src/str/converts.rs b/core/src/str/converts.rs index 1956a04829d1d..dcddc40ba4b99 100644 --- a/core/src/str/converts.rs +++ b/core/src/str/converts.rs @@ -85,7 +85,7 @@ use crate::{mem, ptr}; #[rustc_allow_const_fn_unstable(str_internals)] #[rustc_diagnostic_item = "str_from_utf8"] pub const fn from_utf8(v: &[u8]) -> Result<&str, Utf8Error> { - // FIXME: This should use `?` again, once it's `const` + // FIXME(const-hack): This should use `?` again, once it's `const` match run_utf8_validation(v) { Ok(_) => { // SAFETY: validation succeeded. @@ -129,7 +129,7 @@ pub const fn from_utf8(v: &[u8]) -> Result<&str, Utf8Error> { #[rustc_const_unstable(feature = "const_str_from_utf8", issue = "91006")] #[rustc_diagnostic_item = "str_from_utf8_mut"] pub const fn from_utf8_mut(v: &mut [u8]) -> Result<&mut str, Utf8Error> { - // This should use `?` again, once it's `const` + // FIXME(const-hack): This should use `?` again, once it's `const` match run_utf8_validation(v) { Ok(_) => { // SAFETY: validation succeeded. diff --git a/core/src/str/error.rs b/core/src/str/error.rs index a11b5add42ebf..4c8231a2286e1 100644 --- a/core/src/str/error.rs +++ b/core/src/str/error.rs @@ -100,7 +100,7 @@ impl Utf8Error { #[must_use] #[inline] pub const fn error_len(&self) -> Option { - // FIXME: This should become `map` again, once it's `const` + // FIXME(const-hack): This should become `map` again, once it's `const` match self.error_len { Some(len) => Some(len as usize), None => None, diff --git a/core/src/time.rs b/core/src/time.rs index c19eeedb35426..65560dfcf9d2d 100644 --- a/core/src/time.rs +++ b/core/src/time.rs @@ -213,6 +213,7 @@ impl Duration { // SAFETY: nanos < NANOS_PER_SEC, therefore nanos is within the valid range Duration { secs, nanos: unsafe { Nanoseconds(nanos) } } } else { + // FIXME(const-hack): use `.expect` once that is possible. let secs = match secs.checked_add((nanos / NANOS_PER_SEC) as u64) { Some(secs) => secs, None => panic!("overflow in Duration::new"), @@ -768,6 +769,7 @@ impl Duration { let total_nanos = self.nanos.0 as u64 * rhs as u64; let extra_secs = total_nanos / (NANOS_PER_SEC as u64); let nanos = (total_nanos % (NANOS_PER_SEC as u64)) as u32; + // FIXME(const-hack): use `and_then` once that is possible. if let Some(s) = self.secs.checked_mul(rhs as u64) { if let Some(secs) = s.checked_add(extra_secs) { debug_assert!(nanos < NANOS_PER_SEC); diff --git a/core/src/unicode/unicode_data.rs b/core/src/unicode/unicode_data.rs index 1b3d6729663b5..9783e81608403 100644 --- a/core/src/unicode/unicode_data.rs +++ b/core/src/unicode/unicode_data.rs @@ -18,16 +18,14 @@ const fn bitset_search< let bucket_idx = (needle / 64) as usize; let chunk_map_idx = bucket_idx / CHUNK_SIZE; let chunk_piece = bucket_idx % CHUNK_SIZE; - // FIXME: const-hack: Revert to `slice::get` after `const_slice_index` - // feature stabilizes. + // FIXME(const-hack): Revert to `slice::get` when slice indexing becomes possible in const. let chunk_idx = if chunk_map_idx < chunk_idx_map.len() { chunk_idx_map[chunk_map_idx] } else { return false; }; let idx = bitset_chunk_idx[chunk_idx as usize][chunk_piece] as usize; - // FIXME: const-hack: Revert to `slice::get` after `const_slice_index` - // feature stabilizes. + // FIXME(const-hack): Revert to `slice::get` when slice indexing becomes possible in const. let word = if idx < bitset_canonical.len() { bitset_canonical[idx] } else { diff --git a/core/tests/hash/mod.rs b/core/tests/hash/mod.rs index bdd1c2579ded8..03826fc4c92cd 100644 --- a/core/tests/hash/mod.rs +++ b/core/tests/hash/mod.rs @@ -16,11 +16,8 @@ impl Default for MyHasher { impl Hasher for MyHasher { fn write(&mut self, buf: &[u8]) { - // FIXME(const_trait_impl): change to for loop - let mut i = 0; - while i < buf.len() { - self.hash += buf[i] as u64; - i += 1; + for byte in buf { + self.hash += *byte as u64; } } fn write_str(&mut self, s: &str) { diff --git a/std/src/sys/pal/windows/args.rs b/std/src/sys/pal/windows/args.rs index 66e75a8357149..77d82678f1dcc 100644 --- a/std/src/sys/pal/windows/args.rs +++ b/std/src/sys/pal/windows/args.rs @@ -20,7 +20,7 @@ use crate::{fmt, io, iter, vec}; /// This is the const equivalent to `NonZero::new(n).unwrap()` /// -/// FIXME: This can be removed once `Option::unwrap` is stably const. +/// FIXME(const-hack): This can be removed once `Option::unwrap` is stably const. /// See the `const_option` feature (#67441). const fn non_zero_u16(n: u16) -> NonZero { match NonZero::new(n) { From 1b763fc24283120a244fdaef7a8242ea2d4734f3 Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Sun, 8 Sep 2024 08:54:01 +0200 Subject: [PATCH 04/11] remove const_slice_index annotations, it never had a feature gate anyway --- core/src/lib.rs | 1 - core/src/slice/index.rs | 10 ---------- core/src/slice/memchr.rs | 1 - core/src/str/traits.rs | 6 ------ 4 files changed, 18 deletions(-) diff --git a/core/src/lib.rs b/core/src/lib.rs index bda3825436273..5b5d5d1a9610e 100644 --- a/core/src/lib.rs +++ b/core/src/lib.rs @@ -149,7 +149,6 @@ #![feature(const_size_of_val_raw)] #![feature(const_slice_from_raw_parts_mut)] #![feature(const_slice_from_ref)] -#![feature(const_slice_index)] #![feature(const_slice_split_at_mut)] #![feature(const_str_from_utf8_unchecked_mut)] #![feature(const_strict_overflow_ops)] diff --git a/core/src/slice/index.rs b/core/src/slice/index.rs index 7adcee1ed6b64..bc8571c8503e9 100644 --- a/core/src/slice/index.rs +++ b/core/src/slice/index.rs @@ -31,7 +31,6 @@ where #[cfg_attr(not(feature = "panic_immediate_abort"), inline(never), cold)] #[cfg_attr(feature = "panic_immediate_abort", inline)] #[track_caller] -#[rustc_const_unstable(feature = "const_slice_index", issue = "none")] const fn slice_start_index_len_fail(index: usize, len: usize) -> ! { // FIXME(const-hack): once integer formatting in panics is possible, we // should use the same implementation at compiletime and runtime. @@ -53,7 +52,6 @@ const fn slice_start_index_len_fail_ct(_: usize, _: usize) -> ! { #[cfg_attr(not(feature = "panic_immediate_abort"), inline(never), cold)] #[cfg_attr(feature = "panic_immediate_abort", inline)] #[track_caller] -#[rustc_const_unstable(feature = "const_slice_index", issue = "none")] const fn slice_end_index_len_fail(index: usize, len: usize) -> ! { // FIXME(const-hack): once integer formatting in panics is possible, we // should use the same implementation at compiletime and runtime. @@ -75,7 +73,6 @@ const fn slice_end_index_len_fail_ct(_: usize, _: usize) -> ! { #[cfg_attr(not(feature = "panic_immediate_abort"), inline(never), cold)] #[cfg_attr(feature = "panic_immediate_abort", inline)] #[track_caller] -#[rustc_const_unstable(feature = "const_slice_index", issue = "none")] const fn slice_index_order_fail(index: usize, end: usize) -> ! { // FIXME(const-hack): once integer formatting in panics is possible, we // should use the same implementation at compiletime and runtime. @@ -249,7 +246,6 @@ pub unsafe trait SliceIndex: private_slice_index::Sealed { /// The methods `index` and `index_mut` panic if the index is out of bounds. #[stable(feature = "slice_get_slice_impls", since = "1.15.0")] -#[rustc_const_unstable(feature = "const_slice_index", issue = "none")] unsafe impl SliceIndex<[T]> for usize { type Output = T; @@ -389,7 +385,6 @@ unsafe impl SliceIndex<[T]> for ops::IndexRange { /// - the start of the range is greater than the end of the range or /// - the end of the range is out of bounds. #[stable(feature = "slice_get_slice_impls", since = "1.15.0")] -#[rustc_const_unstable(feature = "const_slice_index", issue = "none")] unsafe impl SliceIndex<[T]> for ops::Range { type Output = [T]; @@ -525,7 +520,6 @@ unsafe impl SliceIndex<[T]> for range::Range { /// The methods `index` and `index_mut` panic if the end of the range is out of bounds. #[stable(feature = "slice_get_slice_impls", since = "1.15.0")] -#[rustc_const_unstable(feature = "const_slice_index", issue = "none")] unsafe impl SliceIndex<[T]> for ops::RangeTo { type Output = [T]; @@ -564,7 +558,6 @@ unsafe impl SliceIndex<[T]> for ops::RangeTo { /// The methods `index` and `index_mut` panic if the start of the range is out of bounds. #[stable(feature = "slice_get_slice_impls", since = "1.15.0")] -#[rustc_const_unstable(feature = "const_slice_index", issue = "none")] unsafe impl SliceIndex<[T]> for ops::RangeFrom { type Output = [T]; @@ -647,7 +640,6 @@ unsafe impl SliceIndex<[T]> for range::RangeFrom { } #[stable(feature = "slice_get_slice_impls", since = "1.15.0")] -#[rustc_const_unstable(feature = "const_slice_index", issue = "none")] unsafe impl SliceIndex<[T]> for ops::RangeFull { type Output = [T]; @@ -687,7 +679,6 @@ unsafe impl SliceIndex<[T]> for ops::RangeFull { /// - the start of the range is greater than the end of the range or /// - the end of the range is out of bounds. #[stable(feature = "inclusive_range", since = "1.26.0")] -#[rustc_const_unstable(feature = "const_slice_index", issue = "none")] unsafe impl SliceIndex<[T]> for ops::RangeInclusive { type Output = [T]; @@ -769,7 +760,6 @@ unsafe impl SliceIndex<[T]> for range::RangeInclusive { /// The methods `index` and `index_mut` panic if the end of the range is out of bounds. #[stable(feature = "inclusive_range", since = "1.26.0")] -#[rustc_const_unstable(feature = "const_slice_index", issue = "none")] unsafe impl SliceIndex<[T]> for ops::RangeToInclusive { type Output = [T]; diff --git a/core/src/slice/memchr.rs b/core/src/slice/memchr.rs index da7ceb2dd0a0d..be19c3d3bc153 100644 --- a/core/src/slice/memchr.rs +++ b/core/src/slice/memchr.rs @@ -51,7 +51,6 @@ const fn memchr_naive(x: u8, text: &[u8]) -> Option { } #[rustc_allow_const_fn_unstable(const_cmp)] -#[rustc_allow_const_fn_unstable(const_slice_index)] #[rustc_allow_const_fn_unstable(const_align_offset)] #[rustc_const_stable(feature = "const_memchr", since = "1.65.0")] const fn memchr_aligned(x: u8, text: &[u8]) -> Option { diff --git a/core/src/str/traits.rs b/core/src/str/traits.rs index b69c476ae5e53..77c70b978fd15 100644 --- a/core/src/str/traits.rs +++ b/core/src/str/traits.rs @@ -92,7 +92,6 @@ const fn str_index_overflow_fail() -> ! { /// /// Equivalent to `&self[0 .. len]` or `&mut self[0 .. len]`. #[stable(feature = "str_checked_slicing", since = "1.20.0")] -#[rustc_const_unstable(feature = "const_slice_index", issue = "none")] unsafe impl SliceIndex for ops::RangeFull { type Output = str; #[inline] @@ -157,7 +156,6 @@ unsafe impl SliceIndex for ops::RangeFull { /// // &s[3 .. 100]; /// ``` #[stable(feature = "str_checked_slicing", since = "1.20.0")] -#[rustc_const_unstable(feature = "const_slice_index", issue = "none")] unsafe impl SliceIndex for ops::Range { type Output = str; #[inline] @@ -429,7 +427,6 @@ unsafe impl SliceIndex for (ops::Bound, ops::Bound) { /// Panics if `end` does not point to the starting byte offset of a /// character (as defined by `is_char_boundary`), or if `end > len`. #[stable(feature = "str_checked_slicing", since = "1.20.0")] -#[rustc_const_unstable(feature = "const_slice_index", issue = "none")] unsafe impl SliceIndex for ops::RangeTo { type Output = str; #[inline] @@ -498,7 +495,6 @@ unsafe impl SliceIndex for ops::RangeTo { /// Panics if `begin` does not point to the starting byte offset of /// a character (as defined by `is_char_boundary`), or if `begin > len`. #[stable(feature = "str_checked_slicing", since = "1.20.0")] -#[rustc_const_unstable(feature = "const_slice_index", issue = "none")] unsafe impl SliceIndex for ops::RangeFrom { type Output = str; #[inline] @@ -625,7 +621,6 @@ unsafe impl SliceIndex for range::RangeFrom { /// to the ending byte offset of a character (`end + 1` is either a starting /// byte offset or equal to `len`), if `begin > end`, or if `end >= len`. #[stable(feature = "inclusive_range", since = "1.26.0")] -#[rustc_const_unstable(feature = "const_slice_index", issue = "none")] unsafe impl SliceIndex for ops::RangeInclusive { type Output = str; #[inline] @@ -714,7 +709,6 @@ unsafe impl SliceIndex for range::RangeInclusive { /// (`end + 1` is either a starting byte offset as defined by /// `is_char_boundary`, or equal to `len`), or if `end >= len`. #[stable(feature = "inclusive_range", since = "1.26.0")] -#[rustc_const_unstable(feature = "const_slice_index", issue = "none")] unsafe impl SliceIndex for ops::RangeToInclusive { type Output = str; #[inline] From 4b1440a98efe03729873388ff0aa052df3827f1e Mon Sep 17 00:00:00 2001 From: "James C. Wise" Date: Mon, 9 Sep 2024 13:13:45 -0400 Subject: [PATCH 05/11] Fix slice::first_mut docs pointer -> reference --- core/src/slice/mod.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/core/src/slice/mod.rs b/core/src/slice/mod.rs index 166189f4b6cf3..fb732f82989c0 100644 --- a/core/src/slice/mod.rs +++ b/core/src/slice/mod.rs @@ -156,7 +156,7 @@ impl [T] { if let [first, ..] = self { Some(first) } else { None } } - /// Returns a mutable pointer to the first element of the slice, or `None` if it is empty. + /// Returns a mutable reference to the first element of the slice, or `None` if it is empty. /// /// # Examples /// From dbf585c158ec7df39f9ddc57d8e308eced720243 Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Wed, 11 Sep 2024 22:17:03 +0200 Subject: [PATCH 06/11] make basic allocation functions track_caller in Miri for nicer backtraces --- alloc/src/alloc.rs | 13 +++++++++++++ alloc/src/boxed.rs | 1 + 2 files changed, 14 insertions(+) diff --git a/alloc/src/alloc.rs b/alloc/src/alloc.rs index cddf4f6f39963..de58b06545b07 100644 --- a/alloc/src/alloc.rs +++ b/alloc/src/alloc.rs @@ -89,6 +89,7 @@ pub use std::alloc::Global; #[stable(feature = "global_alloc", since = "1.28.0")] #[must_use = "losing the pointer will leak memory"] #[inline] +#[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces pub unsafe fn alloc(layout: Layout) -> *mut u8 { unsafe { // Make sure we don't accidentally allow omitting the allocator shim in @@ -113,6 +114,7 @@ pub unsafe fn alloc(layout: Layout) -> *mut u8 { /// See [`GlobalAlloc::dealloc`]. #[stable(feature = "global_alloc", since = "1.28.0")] #[inline] +#[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces pub unsafe fn dealloc(ptr: *mut u8, layout: Layout) { unsafe { __rust_dealloc(ptr, layout.size(), layout.align()) } } @@ -132,6 +134,7 @@ pub unsafe fn dealloc(ptr: *mut u8, layout: Layout) { #[stable(feature = "global_alloc", since = "1.28.0")] #[must_use = "losing the pointer will leak memory"] #[inline] +#[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces pub unsafe fn realloc(ptr: *mut u8, layout: Layout, new_size: usize) -> *mut u8 { unsafe { __rust_realloc(ptr, layout.size(), layout.align(), new_size) } } @@ -166,6 +169,7 @@ pub unsafe fn realloc(ptr: *mut u8, layout: Layout, new_size: usize) -> *mut u8 #[stable(feature = "global_alloc", since = "1.28.0")] #[must_use = "losing the pointer will leak memory"] #[inline] +#[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces pub unsafe fn alloc_zeroed(layout: Layout) -> *mut u8 { unsafe { __rust_alloc_zeroed(layout.size(), layout.align()) } } @@ -173,6 +177,7 @@ pub unsafe fn alloc_zeroed(layout: Layout) -> *mut u8 { #[cfg(not(test))] impl Global { #[inline] + #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces fn alloc_impl(&self, layout: Layout, zeroed: bool) -> Result, AllocError> { match layout.size() { 0 => Ok(NonNull::slice_from_raw_parts(layout.dangling(), 0)), @@ -187,6 +192,7 @@ impl Global { // SAFETY: Same as `Allocator::grow` #[inline] + #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces unsafe fn grow_impl( &self, ptr: NonNull, @@ -237,16 +243,19 @@ impl Global { #[cfg(not(test))] unsafe impl Allocator for Global { #[inline] + #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces fn allocate(&self, layout: Layout) -> Result, AllocError> { self.alloc_impl(layout, false) } #[inline] + #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces fn allocate_zeroed(&self, layout: Layout) -> Result, AllocError> { self.alloc_impl(layout, true) } #[inline] + #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces unsafe fn deallocate(&self, ptr: NonNull, layout: Layout) { if layout.size() != 0 { // SAFETY: `layout` is non-zero in size, @@ -256,6 +265,7 @@ unsafe impl Allocator for Global { } #[inline] + #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces unsafe fn grow( &self, ptr: NonNull, @@ -267,6 +277,7 @@ unsafe impl Allocator for Global { } #[inline] + #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces unsafe fn grow_zeroed( &self, ptr: NonNull, @@ -278,6 +289,7 @@ unsafe impl Allocator for Global { } #[inline] + #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces unsafe fn shrink( &self, ptr: NonNull, @@ -325,6 +337,7 @@ unsafe impl Allocator for Global { #[cfg(all(not(no_global_oom_handling), not(test)))] #[lang = "exchange_malloc"] #[inline] +#[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces unsafe fn exchange_malloc(size: usize, align: usize) -> *mut u8 { let layout = unsafe { Layout::from_size_align_unchecked(size, align) }; match Global.allocate(layout) { diff --git a/alloc/src/boxed.rs b/alloc/src/boxed.rs index 6dc75478700ce..4b1d493113c68 100644 --- a/alloc/src/boxed.rs +++ b/alloc/src/boxed.rs @@ -250,6 +250,7 @@ impl Box { #[stable(feature = "rust1", since = "1.0.0")] #[must_use] #[rustc_diagnostic_item = "box_new"] + #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces pub fn new(x: T) -> Self { #[rustc_box] Box::new(x) From 22ffa3d384f6de1906d6e17de40db84487d9126a Mon Sep 17 00:00:00 2001 From: Chris Jefferson Date: Mon, 13 May 2024 13:35:54 +0800 Subject: [PATCH 07/11] Expand PathBuf documentation Mention that some methods do not sanitize their input fully --- std/src/path.rs | 24 ++++++++++++++++++++++++ 1 file changed, 24 insertions(+) diff --git a/std/src/path.rs b/std/src/path.rs index 506ad445b6bed..e7fd2e4ddee22 100644 --- a/std/src/path.rs +++ b/std/src/path.rs @@ -1153,6 +1153,21 @@ impl FusedIterator for Ancestors<'_> {} /// ``` /// /// Which method works best depends on what kind of situation you're in. +/// +/// Note that `PathBuf`` does not always sanitize arguments, for example +/// [`push`] allows paths built from strings which include separators: +/// +/// use std::path::PathBuf; +/// +/// let mut path = PathBuf::new(); +/// +/// path.push(r"C:\"); +/// path.push("windows"); +/// path.push(r"..\otherdir"); +/// path.push("system32"); +/// +/// The behaviour of `PathBuf` may be changed to a panic on such inputs +/// in the future. The [`extend`] method should be used to add multi-part paths. #[cfg_attr(not(test), rustc_diagnostic_item = "PathBuf")] #[stable(feature = "rust1", since = "1.0.0")] pub struct PathBuf { @@ -1391,6 +1406,9 @@ impl PathBuf { /// `file_name`. The new path will be a sibling of the original path. /// (That is, it will have the same parent.) /// + /// The argument is not sanitized, so can include separators. This + /// behaviour may be changed to a panic in the future. + /// /// [`self.file_name`]: Path::file_name /// [`pop`]: PathBuf::pop /// @@ -1411,6 +1429,12 @@ impl PathBuf { /// /// buf.set_file_name("baz"); /// assert!(buf == PathBuf::from("/baz")); + /// + /// buf.set_file_name("../b/c.txt"); + /// assert!(buf == PathBuf::from("/../b/c.txt")); + /// + /// buf.set_file_name("baz"); + /// assert!(buf == PathBuf::from("/../b/baz")); /// ``` #[stable(feature = "rust1", since = "1.0.0")] pub fn set_file_name>(&mut self, file_name: S) { From 34e4b6d8f7e97a3419b8aa252981439c26ab1641 Mon Sep 17 00:00:00 2001 From: Jubilee Young Date: Wed, 11 Sep 2024 22:46:06 -0700 Subject: [PATCH 08/11] Fixup docs for PathBuf --- std/src/path.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/std/src/path.rs b/std/src/path.rs index e7fd2e4ddee22..c94df9b5366be 100644 --- a/std/src/path.rs +++ b/std/src/path.rs @@ -1154,7 +1154,7 @@ impl FusedIterator for Ancestors<'_> {} /// /// Which method works best depends on what kind of situation you're in. /// -/// Note that `PathBuf`` does not always sanitize arguments, for example +/// Note that `PathBuf` does not always sanitize arguments, for example /// [`push`] allows paths built from strings which include separators: /// /// use std::path::PathBuf; @@ -1167,7 +1167,7 @@ impl FusedIterator for Ancestors<'_> {} /// path.push("system32"); /// /// The behaviour of `PathBuf` may be changed to a panic on such inputs -/// in the future. The [`extend`] method should be used to add multi-part paths. +/// in the future. [`Extend::extend`] should be used to add multi-part paths. #[cfg_attr(not(test), rustc_diagnostic_item = "PathBuf")] #[stable(feature = "rust1", since = "1.0.0")] pub struct PathBuf { From 91ebe065a2b11380aa43afb328441a5541118715 Mon Sep 17 00:00:00 2001 From: Christopher Durham Date: Sat, 14 Sep 2024 01:34:05 -0400 Subject: [PATCH 09/11] add core::panic::abort_unwind --- core/src/panic.rs | 30 ++++++++++++++++++++++++++++++ 1 file changed, 30 insertions(+) diff --git a/core/src/panic.rs b/core/src/panic.rs index 6c5236ed99ce8..3919bbd79586f 100644 --- a/core/src/panic.rs +++ b/core/src/panic.rs @@ -140,6 +140,36 @@ pub macro unreachable_2021 { ), } +/// Invokes a closure, aborting if the closure unwinds. +/// +/// When compiled with aborting panics, this function is effectively a no-op. +/// With unwinding panics, an unwind results in another call into the panic +/// hook followed by a process abort. +/// +/// # Notes +/// +/// Instead of using this function, code should attempt to support unwinding. +/// Implementing [`Drop`] allows you to restore invariants uniformly in both +/// return and unwind paths. +/// +/// If an unwind can lead to logical issues but not soundness issues, you +/// should allow the unwind. Opting out of [`UnwindSafe`] indicates to your +/// consumers that they need to consider correctness in the face of unwinds. +/// +/// If an unwind would be unsound, then this function should be used in order +/// to prevent unwinds. However, note that `extern "C" fn` will automatically +/// convert unwinds to aborts, so using this function isn't necessary for FFI. +#[unstable(feature = "abort_unwind", issue = "130338")] +pub fn abort_unwind R, R>(f: F) -> R { + // This attribute adds the "unwinding out of nounwind function" guard. + #[rustc_nounwind] + fn abort_unwind_inner R, R>(f: F) -> R { + f() + } + + abort_unwind_inner(f) +} + /// An internal trait used by std to pass data from std to `panic_unwind` and /// other panic runtimes. Not intended to be stabilized any time soon, do not /// use. From 9c71d4ed0a3be4e9e9555aba11fada484b36d065 Mon Sep 17 00:00:00 2001 From: Christopher Durham Date: Sat, 14 Sep 2024 01:41:00 -0400 Subject: [PATCH 10/11] add std::panic::abort_unwind --- std/src/panic.rs | 3 +++ 1 file changed, 3 insertions(+) diff --git a/std/src/panic.rs b/std/src/panic.rs index 6f0952c41ede5..541cf42ab47e6 100644 --- a/std/src/panic.rs +++ b/std/src/panic.rs @@ -283,6 +283,9 @@ where { } +#[unstable(feature = "abort_unwind", issue = "130338")] +pub use core::panic::abort_unwind; + /// Invokes a closure, capturing the cause of an unwinding panic if one occurs. /// /// This function will return `Ok` with the closure's result if the closure From f39684936844ed02b7730d3c7179bb61951d3a63 Mon Sep 17 00:00:00 2001 From: Christopher Durham Date: Sun, 15 Sep 2024 14:27:24 -0400 Subject: [PATCH 11/11] simplify abort_unwind Co-authored-by: David Tolnay --- core/src/panic.rs | 9 ++------- 1 file changed, 2 insertions(+), 7 deletions(-) diff --git a/core/src/panic.rs b/core/src/panic.rs index 3919bbd79586f..c95a000561c35 100644 --- a/core/src/panic.rs +++ b/core/src/panic.rs @@ -160,14 +160,9 @@ pub macro unreachable_2021 { /// to prevent unwinds. However, note that `extern "C" fn` will automatically /// convert unwinds to aborts, so using this function isn't necessary for FFI. #[unstable(feature = "abort_unwind", issue = "130338")] +#[rustc_nounwind] pub fn abort_unwind R, R>(f: F) -> R { - // This attribute adds the "unwinding out of nounwind function" guard. - #[rustc_nounwind] - fn abort_unwind_inner R, R>(f: F) -> R { - f() - } - - abort_unwind_inner(f) + f() } /// An internal trait used by std to pass data from std to `panic_unwind` and