未验证 提交 837cd9e2 编写于 作者: D Dylan DPC 提交者: GitHub

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.
......@@ -499,14 +499,15 @@ pub const fn slice_from_raw_parts(data: NonNull<T>, len: usize) -> Self {
/// # 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 {
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册