Update safety comments, make split_at_mut unsafe

`&mut [T]` implies validity which automatically makes `ptr::add` ok within its bounds.
But `*mut [T]` does not. Since we still want the benefits of in-bounds pointer arithmetic
`split_at_must` must require the caller to pass valid pointers and therefore it is `unsafe`.
This commit is contained in:
The 8472 2022-04-03 13:32:34 +02:00
parent a671fa1b15
commit b0ca46e90d

View File

@ -1366,6 +1366,22 @@ impl<T> *mut [T] {
/// ///
/// Panics if `mid > len`. /// Panics if `mid > len`.
/// ///
/// # Safety
///
/// `mid` must be [in-bounds] of the underlying [allocated object].
/// Which means `self` must be dereferenceable and span a single allocation
/// that is at least `mid * size_of::<T>()` bytes long. Not upholding these
/// requirements is *[undefined behavior]* even if the resulting pointers are not used.
///
/// Since `len` being in-bounds it is not a safety invariant of `*mut [T]` the
/// safety requirements of this method are the same as for [`split_at_mut_unchecked`].
/// The explicit bounds check is only as useful as `len` is correct.
///
/// [`split_at_mut_unchecked`]: #method.split_at_mut_unchecked
/// [in-bounds]: #method.add
/// [allocated object]: crate::ptr#allocated-object
/// [undefined behavior]: https://doc.rust-lang.org/reference/behavior-considered-undefined.html
///
/// # Examples /// # Examples
/// ///
/// ``` /// ```
@ -1374,8 +1390,8 @@ impl<T> *mut [T] {
/// ///
/// let mut v = [1, 0, 3, 0, 5, 6]; /// let mut v = [1, 0, 3, 0, 5, 6];
/// let ptr = &mut v as *mut [_]; /// let ptr = &mut v as *mut [_];
/// let (left, right) = ptr.split_at_mut(2);
/// unsafe { /// unsafe {
/// let (left, right) = ptr.split_at_mut(2);
/// assert_eq!(&*left, [1, 0]); /// assert_eq!(&*left, [1, 0]);
/// assert_eq!(&*right, [3, 0, 5, 6]); /// assert_eq!(&*right, [3, 0, 5, 6]);
/// } /// }
@ -1383,10 +1399,10 @@ impl<T> *mut [T] {
#[inline(always)] #[inline(always)]
#[track_caller] #[track_caller]
#[unstable(feature = "raw_slice_split", issue = "95595")] #[unstable(feature = "raw_slice_split", issue = "95595")]
pub fn split_at_mut(self, mid: usize) -> (*mut [T], *mut [T]) { pub unsafe fn split_at_mut(self, mid: usize) -> (*mut [T], *mut [T]) {
assert!(mid <= self.len()); assert!(mid <= self.len());
// SAFETY: `[ptr; mid]` and `[mid; len]` are inside `self`, which // SAFETY: The assert above is only a safety-net as long as `self.len()` is correct
// fulfills the requirements of `from_raw_parts_mut`. // The actual safety requirements of this function are the same as for `split_at_mut_unchecked`
unsafe { self.split_at_mut_unchecked(mid) } unsafe { self.split_at_mut_unchecked(mid) }
} }
@ -1396,16 +1412,15 @@ impl<T> *mut [T] {
/// the index `mid` itself) and the second will contain all /// the index `mid` itself) and the second will contain all
/// indices from `[mid, len)` (excluding the index `len` itself). /// indices from `[mid, len)` (excluding the index `len` itself).
/// ///
/// For a safe alternative see [`split_at_mut`].
///
/// [`split_at_mut`]: #method.split_at_mut
///
/// # Safety /// # Safety
/// ///
/// Calling this method with an out-of-bounds index is *[undefined behavior]* /// `mid` must be [in-bounds] of the underlying [allocated object].
/// even if the resulting reference is not used. The caller has to ensure that /// Which means `self` must be dereferenceable and span a single allocation
/// `0 <= mid <= self.len()`. /// that is at least `mid * size_of::<T>()` bytes long. Not upholding these
/// requirements is *[undefined behavior]* even if the resulting pointers are not used.
/// ///
/// [in-bounds]: #method.add
/// [out-of-bounds index]: #method.add
/// [undefined behavior]: https://doc.rust-lang.org/reference/behavior-considered-undefined.html /// [undefined behavior]: https://doc.rust-lang.org/reference/behavior-considered-undefined.html
/// ///
/// # Examples /// # Examples
@ -1431,16 +1446,12 @@ impl<T> *mut [T] {
let len = self.len(); let len = self.len();
let ptr = self.as_mut_ptr(); let ptr = self.as_mut_ptr();
// SAFETY: Caller has to check that `0 <= mid <= self.len()`. // SAFETY: Caller must pass a valid pointer and an index that is in-bounds.
// let tail = unsafe { ptr.add(mid) };
// `[ptr; mid]` and `[mid; len]` are not overlapping, so returning a mutable reference (
// is fine. crate::ptr::slice_from_raw_parts_mut(ptr, mid),
unsafe { crate::ptr::slice_from_raw_parts_mut(tail, len - mid),
( )
crate::ptr::slice_from_raw_parts_mut(ptr, mid),
crate::ptr::slice_from_raw_parts_mut(ptr.add(mid), len - mid),
)
}
} }
/// Returns a raw pointer to the slice's buffer. /// Returns a raw pointer to the slice's buffer.
@ -1466,9 +1477,10 @@ impl<T> *mut [T] {
/// Returns a raw pointer to an element or subslice, without doing bounds /// Returns a raw pointer to an element or subslice, without doing bounds
/// checking. /// checking.
/// ///
/// Calling this method with an out-of-bounds index or when `self` is not dereferenceable /// Calling this method with an [out-of-bounds index] or when `self` is not dereferenceable
/// is *[undefined behavior]* even if the resulting pointer is not used. /// is *[undefined behavior]* even if the resulting pointer is not used.
/// ///
/// [out-of-bounds index]: #method.add
/// [undefined behavior]: https://doc.rust-lang.org/reference/behavior-considered-undefined.html /// [undefined behavior]: https://doc.rust-lang.org/reference/behavior-considered-undefined.html
/// ///
/// # Examples /// # Examples