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](https://github.com/rust-lang/rust/issues/71146#issuecomment-808735714) 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.
This commit is contained in:
commit
837cd9e26c
1 changed files with 4 additions and 3 deletions
|
@ -499,14 +499,15 @@ impl<T> NonNull<[T]> {
|
|||
/// # Examples
|
||||
///
|
||||
/// ```rust
|
||||
/// #![feature(slice_ptr_len, nonnull_slice_from_raw_parts)]
|
||||
/// #![feature(nonnull_slice_from_raw_parts)]
|
||||
/// use std::ptr::NonNull;
|
||||
///
|
||||
/// let slice: NonNull<[i8]> = NonNull::slice_from_raw_parts(NonNull::dangling(), 3);
|
||||
/// assert_eq!(slice.len(), 3);
|
||||
/// ```
|
||||
#[unstable(feature = "slice_ptr_len", issue = "71146")]
|
||||
#[rustc_const_unstable(feature = "const_slice_ptr_len", issue = "71146")]
|
||||
#[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 {
|
||||
|
|
Loading…
Add table
Reference in a new issue