Partially stabilize (const_)slice_ptr_len
feature by stabilizing NonNull::len
by Pointerbender · Pull Request #94640 · rust-lang/rust (original) (raw)
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:
/// # 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(ptr: core::ptr::NonNull<[T]>) -> usize {
(&*ptr.as_ptr()).len()
}
A slightly less complicated version (but still more complicated than it needs to be):
/// # 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(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 to NonNull::len
.
We should probably also ping the Constant Evaluation WG 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.