From fb9e1f73b36ee867b6ff14ab977afa5a57c8c025 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Eduardo=20S=C3=A1nchez=20Mu=C3=B1oz?= Date: Fri, 12 Apr 2024 21:23:20 +0200 Subject: [PATCH 1/4] Stabilize (const_)slice_ptr_len and (const_)slice_ptr_is_empty_nonnull --- library/alloc/src/lib.rs | 1 - library/core/src/lib.rs | 1 - library/core/src/ptr/const_ptr.rs | 14 ++++++-------- library/core/src/ptr/mut_ptr.rs | 11 +++++------ library/core/src/ptr/non_null.rs | 9 +++++---- library/core/tests/lib.rs | 1 - library/std/src/lib.rs | 1 - tests/ui/consts/const_fn_unsize.rs | 1 - 8 files changed, 16 insertions(+), 23 deletions(-) diff --git a/library/alloc/src/lib.rs b/library/alloc/src/lib.rs index f638c5cf8c71c..dec04d7e421e3 100644 --- a/library/alloc/src/lib.rs +++ b/library/alloc/src/lib.rs @@ -151,7 +151,6 @@ #![feature(slice_from_ptr_range)] #![feature(slice_index_methods)] #![feature(slice_ptr_get)] -#![feature(slice_ptr_len)] #![feature(slice_range)] #![feature(std_internals)] #![feature(str_internals)] diff --git a/library/core/src/lib.rs b/library/core/src/lib.rs index 10d2698c5dd1b..85312371cda6e 100644 --- a/library/core/src/lib.rs +++ b/library/core/src/lib.rs @@ -158,7 +158,6 @@ #![feature(const_slice_from_raw_parts_mut)] #![feature(const_slice_from_ref)] #![feature(const_slice_index)] -#![feature(const_slice_ptr_len)] #![feature(const_slice_split_at_mut)] #![feature(const_str_from_utf8_unchecked_mut)] #![feature(const_strict_overflow_ops)] diff --git a/library/core/src/ptr/const_ptr.rs b/library/core/src/ptr/const_ptr.rs index 01db050e666f2..9737fb8816e9c 100644 --- a/library/core/src/ptr/const_ptr.rs +++ b/library/core/src/ptr/const_ptr.rs @@ -1647,16 +1647,15 @@ impl *const [T] { /// # Examples /// /// ```rust - /// #![feature(slice_ptr_len)] - /// /// use std::ptr; /// /// let slice: *const [i8] = ptr::slice_from_raw_parts(ptr::null(), 3); /// assert_eq!(slice.len(), 3); /// ``` #[inline] - #[unstable(feature = "slice_ptr_len", issue = "71146")] - #[rustc_const_unstable(feature = "const_slice_ptr_len", issue = "71146")] + #[stable(feature = "slice_ptr_len", since = "CURRENT_RUSTC_VERSION")] + #[rustc_const_stable(feature = "const_slice_ptr_len", since = "CURRENT_RUSTC_VERSION")] + #[rustc_allow_const_fn_unstable(ptr_metadata)] pub const fn len(self) -> usize { metadata(self) } @@ -1666,15 +1665,14 @@ impl *const [T] { /// # Examples /// /// ``` - /// #![feature(slice_ptr_len)] /// use std::ptr; /// /// let slice: *const [i8] = ptr::slice_from_raw_parts(ptr::null(), 3); /// assert!(!slice.is_empty()); /// ``` #[inline(always)] - #[unstable(feature = "slice_ptr_len", issue = "71146")] - #[rustc_const_unstable(feature = "const_slice_ptr_len", issue = "71146")] + #[stable(feature = "slice_ptr_len", since = "CURRENT_RUSTC_VERSION")] + #[rustc_const_stable(feature = "const_slice_ptr_len", since = "CURRENT_RUSTC_VERSION")] pub const fn is_empty(self) -> bool { self.len() == 0 } @@ -1804,7 +1802,7 @@ impl *const [T; N] { /// # Examples /// /// ``` - /// #![feature(array_ptr_get, slice_ptr_len)] + /// #![feature(array_ptr_get)] /// /// let arr: *const [i32; 3] = &[1, 2, 4] as *const [i32; 3]; /// let slice: *const [i32] = arr.as_slice(); diff --git a/library/core/src/ptr/mut_ptr.rs b/library/core/src/ptr/mut_ptr.rs index 41e5ba6745827..08f03af355da8 100644 --- a/library/core/src/ptr/mut_ptr.rs +++ b/library/core/src/ptr/mut_ptr.rs @@ -1909,15 +1909,15 @@ impl *mut [T] { /// # Examples /// /// ```rust - /// #![feature(slice_ptr_len)] /// use std::ptr; /// /// let slice: *mut [i8] = ptr::slice_from_raw_parts_mut(ptr::null_mut(), 3); /// assert_eq!(slice.len(), 3); /// ``` #[inline(always)] - #[unstable(feature = "slice_ptr_len", issue = "71146")] - #[rustc_const_unstable(feature = "const_slice_ptr_len", issue = "71146")] + #[stable(feature = "slice_ptr_len", since = "CURRENT_RUSTC_VERSION")] + #[rustc_const_stable(feature = "const_slice_ptr_len", since = "CURRENT_RUSTC_VERSION")] + #[rustc_allow_const_fn_unstable(ptr_metadata)] pub const fn len(self) -> usize { metadata(self) } @@ -1927,15 +1927,14 @@ impl *mut [T] { /// # Examples /// /// ``` - /// #![feature(slice_ptr_len)] /// use std::ptr; /// /// let slice: *mut [i8] = ptr::slice_from_raw_parts_mut(ptr::null_mut(), 3); /// assert!(!slice.is_empty()); /// ``` #[inline(always)] - #[unstable(feature = "slice_ptr_len", issue = "71146")] - #[rustc_const_unstable(feature = "const_slice_ptr_len", issue = "71146")] + #[stable(feature = "slice_ptr_len", since = "CURRENT_RUSTC_VERSION")] + #[rustc_const_stable(feature = "const_slice_ptr_len", since = "CURRENT_RUSTC_VERSION")] pub const fn is_empty(self) -> bool { self.len() == 0 } diff --git a/library/core/src/ptr/non_null.rs b/library/core/src/ptr/non_null.rs index f0e4b958bc603..96ce3cd3a3fb5 100644 --- a/library/core/src/ptr/non_null.rs +++ b/library/core/src/ptr/non_null.rs @@ -1562,7 +1562,6 @@ impl NonNull<[T]> { /// ``` #[stable(feature = "slice_ptr_len_nonnull", since = "1.63.0")] #[rustc_const_stable(feature = "const_slice_ptr_len_nonnull", since = "1.63.0")] - #[rustc_allow_const_fn_unstable(const_slice_ptr_len)] #[must_use] #[inline] pub const fn len(self) -> usize { @@ -1574,14 +1573,16 @@ impl NonNull<[T]> { /// # Examples /// /// ```rust - /// #![feature(slice_ptr_is_empty_nonnull)] /// use std::ptr::NonNull; /// /// let slice: NonNull<[i8]> = NonNull::slice_from_raw_parts(NonNull::dangling(), 3); /// assert!(!slice.is_empty()); /// ``` - #[unstable(feature = "slice_ptr_is_empty_nonnull", issue = "71146")] - #[rustc_const_unstable(feature = "const_slice_ptr_is_empty_nonnull", issue = "71146")] + #[stable(feature = "slice_ptr_is_empty_nonnull", since = "CURRENT_RUSTC_VERSION")] + #[rustc_const_stable( + feature = "const_slice_ptr_is_empty_nonnull", + since = "CURRENT_RUSTC_VERSION" + )] #[must_use] #[inline] pub const fn is_empty(self) -> bool { diff --git a/library/core/tests/lib.rs b/library/core/tests/lib.rs index 0c87860096f63..e741149e7ce21 100644 --- a/library/core/tests/lib.rs +++ b/library/core/tests/lib.rs @@ -54,7 +54,6 @@ #![feature(sort_internals)] #![feature(slice_take)] #![feature(slice_from_ptr_range)] -#![feature(slice_ptr_len)] #![feature(slice_split_once)] #![feature(split_as_slice)] #![feature(maybe_uninit_fill)] diff --git a/library/std/src/lib.rs b/library/std/src/lib.rs index ac475b5530a78..445f31ce49172 100644 --- a/library/std/src/lib.rs +++ b/library/std/src/lib.rs @@ -265,7 +265,6 @@ feature(slice_index_methods, coerce_unsized, sgx_platform) )] #![cfg_attr(any(windows, target_os = "uefi"), feature(round_char_boundary))] -#![cfg_attr(target_os = "xous", feature(slice_ptr_len))] #![cfg_attr(target_family = "wasm", feature(stdarch_wasm_atomic_wait))] #![cfg_attr( all(any(target_arch = "x86_64", target_arch = "x86"), target_os = "uefi"), diff --git a/tests/ui/consts/const_fn_unsize.rs b/tests/ui/consts/const_fn_unsize.rs index f96a6088fd312..15d717e7e1213 100644 --- a/tests/ui/consts/const_fn_unsize.rs +++ b/tests/ui/consts/const_fn_unsize.rs @@ -1,5 +1,4 @@ //@ run-pass -#![feature(slice_ptr_len)] use std::ptr::NonNull; From ca0939db046ca73d7512f28cf4a58010c3727838 Mon Sep 17 00:00:00 2001 From: Trevor Gross Date: Fri, 12 Apr 2024 17:36:00 -0400 Subject: [PATCH 2/4] Fix Pietro's entry in the mailmap Mailmap only allows one remapping per line, so @pietroalbini wasn't getting grouped correctly. Fix this. --- .mailmap | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/.mailmap b/.mailmap index f62df9ca5f3cf..6ee765533f839 100644 --- a/.mailmap +++ b/.mailmap @@ -474,7 +474,8 @@ Philipp Matthias Schäfer phosphorus Pierre Krieger pierwill <19642016+pierwill@users.noreply.github.com> -Pietro Albini +Pietro Albini +Pietro Albini Pradyumna Rahul Przemysław Wesołek Przemek Wesołek r00ster From a7201db04bf1e3a424cd0a3a75ccff56401f2401 Mon Sep 17 00:00:00 2001 From: Josh Stone Date: Fri, 12 Apr 2024 14:55:36 -0700 Subject: [PATCH 3/4] Merge cuviper in the mailmap --- .mailmap | 2 ++ 1 file changed, 2 insertions(+) diff --git a/.mailmap b/.mailmap index f62df9ca5f3cf..9e30bd621096e 100644 --- a/.mailmap +++ b/.mailmap @@ -307,6 +307,8 @@ Joseph T. Lyons Josh Cotton Josh Driver Josh Holmer +Josh Stone +Josh Stone Julian Knodt jumbatm <30644300+jumbatm@users.noreply.github.com> Junyoung Cho From f7d54fa6cb8d5a31914de285efbb79f55b60abb2 Mon Sep 17 00:00:00 2001 From: Ben Kimock Date: Thu, 11 Apr 2024 21:13:57 -0400 Subject: [PATCH 4/4] Avoid more NonNull-raw-NonNull roundtrips in Vec --- library/alloc/src/raw_vec.rs | 11 ++++++++ library/alloc/src/vec/in_place_collect.rs | 21 ++++++++------- library/alloc/src/vec/in_place_drop.rs | 7 ++--- library/alloc/src/vec/into_iter.rs | 2 +- library/alloc/src/vec/mod.rs | 27 +++++++++++++++++++ library/alloc/src/vec/spec_from_iter.rs | 2 +- tests/ui/suggestions/deref-path-method.stderr | 2 +- tests/ui/ufcs/bad-builder.stderr | 2 +- 8 files changed, 57 insertions(+), 17 deletions(-) diff --git a/library/alloc/src/raw_vec.rs b/library/alloc/src/raw_vec.rs index 0883080d7357f..1134c7f833e2b 100644 --- a/library/alloc/src/raw_vec.rs +++ b/library/alloc/src/raw_vec.rs @@ -259,6 +259,17 @@ impl RawVec { Self { ptr: unsafe { Unique::new_unchecked(ptr) }, cap, alloc } } + /// A convenience method for hoisting the non-null precondition out of [`RawVec::from_raw_parts_in`]. + /// + /// # Safety + /// + /// See [`RawVec::from_raw_parts_in`]. + #[inline] + pub(crate) unsafe fn from_nonnull_in(ptr: NonNull, capacity: usize, alloc: A) -> Self { + let cap = if T::IS_ZST { Cap::ZERO } else { unsafe { Cap(capacity) } }; + Self { ptr: Unique::from(ptr), cap, alloc } + } + /// Gets a raw pointer to the start of the allocation. Note that this is /// `Unique::dangling()` if `capacity == 0` or `T` is zero-sized. In the former case, you must /// be careful. diff --git a/library/alloc/src/vec/in_place_collect.rs b/library/alloc/src/vec/in_place_collect.rs index 4907a45e881d9..88aa1b1b0e081 100644 --- a/library/alloc/src/vec/in_place_collect.rs +++ b/library/alloc/src/vec/in_place_collect.rs @@ -161,7 +161,7 @@ use core::iter::{InPlaceIterable, SourceIter, TrustedRandomAccessNoCoerce}; use core::marker::PhantomData; use core::mem::{self, ManuallyDrop, SizedTypeProperties}; use core::num::NonZero; -use core::ptr::{self, NonNull}; +use core::ptr; use super::{InPlaceDrop, InPlaceDstDataSrcBufDrop, SpecFromIter, SpecFromIterNested, Vec}; @@ -254,28 +254,30 @@ where let (src_buf, src_ptr, src_cap, mut dst_buf, dst_end, dst_cap) = unsafe { let inner = iterator.as_inner().as_into_iter(); ( - inner.buf.as_ptr(), + inner.buf, inner.ptr, inner.cap, - inner.buf.as_ptr() as *mut T, + inner.buf.cast::(), inner.end as *const T, inner.cap * mem::size_of::() / mem::size_of::(), ) }; // SAFETY: `dst_buf` and `dst_end` are the start and end of the buffer. - let len = unsafe { SpecInPlaceCollect::collect_in_place(&mut iterator, dst_buf, dst_end) }; + let len = unsafe { + SpecInPlaceCollect::collect_in_place(&mut iterator, dst_buf.as_ptr() as *mut T, dst_end) + }; let src = unsafe { iterator.as_inner().as_into_iter() }; // check if SourceIter contract was upheld // caveat: if they weren't we might not even make it to this point - debug_assert_eq!(src_buf, src.buf.as_ptr()); + debug_assert_eq!(src_buf, src.buf); // check InPlaceIterable contract. This is only possible if the iterator advanced the // source pointer at all. If it uses unchecked access via TrustedRandomAccess // then the source pointer will stay in its initial position and we can't use it as reference if src.ptr != src_ptr { debug_assert!( - unsafe { dst_buf.add(len) as *const _ } <= src.ptr.as_ptr(), + unsafe { dst_buf.add(len).cast() } <= src.ptr, "InPlaceIterable contract violation, write pointer advanced beyond read pointer" ); } @@ -315,10 +317,9 @@ where let dst_size = mem::size_of::().unchecked_mul(dst_cap); let new_layout = Layout::from_size_align_unchecked(dst_size, dst_align); - let result = - alloc.shrink(NonNull::new_unchecked(dst_buf as *mut u8), old_layout, new_layout); + let result = alloc.shrink(dst_buf.cast(), old_layout, new_layout); let Ok(reallocated) = result else { handle_alloc_error(new_layout) }; - dst_buf = reallocated.as_ptr() as *mut T; + dst_buf = reallocated.cast::(); } } else { debug_assert_eq!(src_cap * mem::size_of::(), dst_cap * mem::size_of::()); @@ -326,7 +327,7 @@ where mem::forget(dst_guard); - let vec = unsafe { Vec::from_raw_parts(dst_buf, len, dst_cap) }; + let vec = unsafe { Vec::from_nonnull(dst_buf, len, dst_cap) }; vec } diff --git a/library/alloc/src/vec/in_place_drop.rs b/library/alloc/src/vec/in_place_drop.rs index 40a540b57fc22..4050c250130bb 100644 --- a/library/alloc/src/vec/in_place_drop.rs +++ b/library/alloc/src/vec/in_place_drop.rs @@ -1,4 +1,5 @@ use core::marker::PhantomData; +use core::ptr::NonNull; use core::ptr::{self, drop_in_place}; use core::slice::{self}; @@ -31,7 +32,7 @@ impl Drop for InPlaceDrop { // the source allocation - i.e. before the reallocation happened - to avoid leaking them // if some other destructor panics. pub(super) struct InPlaceDstDataSrcBufDrop { - pub(super) ptr: *mut Dest, + pub(super) ptr: NonNull, pub(super) len: usize, pub(super) src_cap: usize, pub(super) src: PhantomData, @@ -42,8 +43,8 @@ impl Drop for InPlaceDstDataSrcBufDrop { fn drop(&mut self) { unsafe { let _drop_allocation = - RawVec::::from_raw_parts_in(self.ptr.cast::(), self.src_cap, Global); - drop_in_place(core::ptr::slice_from_raw_parts_mut::(self.ptr, self.len)); + RawVec::::from_nonnull_in(self.ptr.cast::(), self.src_cap, Global); + drop_in_place(core::ptr::slice_from_raw_parts_mut::(self.ptr.as_ptr(), self.len)); }; } } diff --git a/library/alloc/src/vec/into_iter.rs b/library/alloc/src/vec/into_iter.rs index dfd42ca06193a..b0226c848332c 100644 --- a/library/alloc/src/vec/into_iter.rs +++ b/library/alloc/src/vec/into_iter.rs @@ -433,7 +433,7 @@ unsafe impl<#[may_dangle] T, A: Allocator> Drop for IntoIter { // `IntoIter::alloc` is not used anymore after this and will be dropped by RawVec let alloc = ManuallyDrop::take(&mut self.0.alloc); // RawVec handles deallocation - let _ = RawVec::from_raw_parts_in(self.0.buf.as_ptr(), self.0.cap, alloc); + let _ = RawVec::from_nonnull_in(self.0.buf, self.0.cap, alloc); } } } diff --git a/library/alloc/src/vec/mod.rs b/library/alloc/src/vec/mod.rs index 7e3463bc082a1..465da39f184b1 100644 --- a/library/alloc/src/vec/mod.rs +++ b/library/alloc/src/vec/mod.rs @@ -603,6 +603,17 @@ impl Vec { pub unsafe fn from_raw_parts(ptr: *mut T, length: usize, capacity: usize) -> Self { unsafe { Self::from_raw_parts_in(ptr, length, capacity, Global) } } + + /// A convenience method for hoisting the non-null precondition out of [`Vec::from_raw_parts`]. + /// + /// # Safety + /// + /// See [`Vec::from_raw_parts`]. + #[inline] + #[cfg(not(no_global_oom_handling))] // required by tests/run-make/alloc-no-oom-handling + pub(crate) unsafe fn from_nonnull(ptr: NonNull, length: usize, capacity: usize) -> Self { + unsafe { Self::from_nonnull_in(ptr, length, capacity, Global) } + } } impl Vec { @@ -820,6 +831,22 @@ impl Vec { unsafe { Vec { buf: RawVec::from_raw_parts_in(ptr, capacity, alloc), len: length } } } + /// A convenience method for hoisting the non-null precondition out of [`Vec::from_raw_parts_in`]. + /// + /// # Safety + /// + /// See [`Vec::from_raw_parts_in`]. + #[inline] + #[cfg(not(no_global_oom_handling))] // required by tests/run-make/alloc-no-oom-handling + pub(crate) unsafe fn from_nonnull_in( + ptr: NonNull, + length: usize, + capacity: usize, + alloc: A, + ) -> Self { + unsafe { Vec { buf: RawVec::from_nonnull_in(ptr, capacity, alloc), len: length } } + } + /// Decomposes a `Vec` into its raw components: `(pointer, length, capacity)`. /// /// Returns the raw pointer to the underlying data, the length of diff --git a/library/alloc/src/vec/spec_from_iter.rs b/library/alloc/src/vec/spec_from_iter.rs index 33dd4139bc08b..6646ae7bccb7a 100644 --- a/library/alloc/src/vec/spec_from_iter.rs +++ b/library/alloc/src/vec/spec_from_iter.rs @@ -51,7 +51,7 @@ impl SpecFromIter> for Vec { if has_advanced { ptr::copy(it.ptr.as_ptr(), it.buf.as_ptr(), it.len()); } - return Vec::from_raw_parts(it.buf.as_ptr(), it.len(), it.cap); + return Vec::from_nonnull(it.buf, it.len(), it.cap); } } diff --git a/tests/ui/suggestions/deref-path-method.stderr b/tests/ui/suggestions/deref-path-method.stderr index b27d9aef06614..bfcc2307fd7fb 100644 --- a/tests/ui/suggestions/deref-path-method.stderr +++ b/tests/ui/suggestions/deref-path-method.stderr @@ -9,7 +9,7 @@ note: if you're trying to build a new `Vec<_, _>` consider using one of the foll Vec::::with_capacity Vec::::try_with_capacity Vec::::from_raw_parts - and 4 others + and 6 others --> $SRC_DIR/alloc/src/vec/mod.rs:LL:COL help: the function `contains` is implemented on `[_]` | diff --git a/tests/ui/ufcs/bad-builder.stderr b/tests/ui/ufcs/bad-builder.stderr index 9cfeb7a5d09d6..e466f94d0d842 100644 --- a/tests/ui/ufcs/bad-builder.stderr +++ b/tests/ui/ufcs/bad-builder.stderr @@ -9,7 +9,7 @@ note: if you're trying to build a new `Vec` consider using one of the followi Vec::::with_capacity Vec::::try_with_capacity Vec::::from_raw_parts - and 4 others + and 6 others --> $SRC_DIR/alloc/src/vec/mod.rs:LL:COL help: there is an associated function `new` with a similar name |