Skip to content

Commit 837cd9e

Browse files
authored
Rollup merge of #94640 - Pointerbender:issue-71146-partial-stabilization, r=yaahc
Partially stabilize `(const_)slice_ptr_len` feature by stabilizing `NonNull::len` This PR partially stabilizes features `const_slice_ptr_len` and `slice_ptr_len` by only stabilizing `NonNull::len`. This partial stabilization is tracked under features `slice_ptr_len_nonnull` and `const_slice_ptr_len_nonnull`, for which this PR can serve as the tracking issue. To summarize the discussion from #71146 leading up to this partial stabilization request: It's currently a bit footgunny to obtain the length of a raw slice pointer, stabilization of `NonNull:len` will help with removing these footguns. Some example footguns are: ```rust /// # Safety /// The caller must ensure that `ptr`: /// 1. does not point to memory that was previously allocated but is now deallocated; /// 2. is within the bounds of a single allocated object; /// 3. does not to point to a slice for which the length exceeds `isize::MAX` bytes; /// 4. points to a properly aligned address; /// 5. does not point to uninitialized memory; /// 6. does not point to a mutably borrowed memory location. pub unsafe fn ptr_len<T>(ptr: core::ptr::NonNull<[T]>) -> usize { (&*ptr.as_ptr()).len() } ``` A slightly less complicated version (but still more complicated than it needs to be): ```rust /// # Safety /// The caller must ensure that the start of `ptr`: /// 1. does not point to memory that was previously allocated but is now deallocated; /// 2. must be within the bounds of a single allocated object. pub unsafe fn ptr_len<T>(ptr: NonNull<[T]>) -> usize { (&*(ptr.as_ptr() as *const [()])).len() } ``` This PR does not stabilize `<*const [T]>::len` and `<*mut [T]>::len` because the tracking issue #71146 list a potential blocker for these methods, but this blocker [does not apply](#71146 (comment)) to `NonNull::len`. We should probably also ping the [Constant Evaluation WG](https://github.com/rust-lang/const-eval) since this PR includes a `#[rustc_allow_const_fn_unstable(const_slice_ptr_len)]`. My instinct here is that this will probably be okay because the pointer is not actually dereferenced and `len()` does not touch the address component of the pointer, but would be best to double check :) One potential down-side was raised that stabilizing `NonNull::len` could lead to encouragement of coding patterns like: ``` pub fn ptr_len<T>(ptr: *mut [T]) -> usize { NonNull::new(ptr).unwrap().len() } ``` which unnecessarily assert non-nullness. However, these are much less of a footgun than the above examples and this should be resolved when `slice_ptr_len` fully stabilizes eventually.
2 parents ed76b77 + 021a7e4 commit 837cd9e

File tree

1 file changed

+4
-3
lines changed

1 file changed

+4
-3
lines changed

library/core/src/ptr/non_null.rs

+4-3
Original file line numberDiff line numberDiff line change
@@ -499,14 +499,15 @@ impl<T> NonNull<[T]> {
499499
/// # Examples
500500
///
501501
/// ```rust
502-
/// #![feature(slice_ptr_len, nonnull_slice_from_raw_parts)]
502+
/// #![feature(nonnull_slice_from_raw_parts)]
503503
/// use std::ptr::NonNull;
504504
///
505505
/// let slice: NonNull<[i8]> = NonNull::slice_from_raw_parts(NonNull::dangling(), 3);
506506
/// assert_eq!(slice.len(), 3);
507507
/// ```
508-
#[unstable(feature = "slice_ptr_len", issue = "71146")]
509-
#[rustc_const_unstable(feature = "const_slice_ptr_len", issue = "71146")]
508+
#[stable(feature = "slice_ptr_len_nonnull", since = "1.63.0")]
509+
#[rustc_const_stable(feature = "const_slice_ptr_len_nonnull", since = "1.63.0")]
510+
#[rustc_allow_const_fn_unstable(const_slice_ptr_len)]
510511
#[must_use]
511512
#[inline]
512513
pub const fn len(self) -> usize {

0 commit comments

Comments
 (0)