Skip to content

Commit a64b928

Browse files
committed
Remove remaining unsafe from slice_first_last_chunk functions
1 parent 7d82b83 commit a64b928

File tree

1 file changed

+46
-48
lines changed

1 file changed

+46
-48
lines changed

library/core/src/slice/mod.rs

Lines changed: 46 additions & 48 deletions
Original file line numberDiff line numberDiff line change
@@ -323,13 +323,7 @@ impl<T> [T] {
323323
#[stable(feature = "slice_first_last_chunk", since = "1.77.0")]
324324
#[rustc_const_stable(feature = "slice_first_last_chunk", since = "1.77.0")]
325325
pub const fn first_chunk<const N: usize>(&self) -> Option<&[T; N]> {
326-
if self.len() < N {
327-
None
328-
} else {
329-
// SAFETY: We explicitly check for the correct number of elements,
330-
// and do not let the reference outlive the slice.
331-
Some(unsafe { &*(self.as_ptr().cast::<[T; N]>()) })
332-
}
326+
if let Some((first, _)) = self.split_at_checked(N) { first.as_array() } else { None }
333327
}
334328

335329
/// Returns a mutable array reference to the first `N` items in the slice.
@@ -353,13 +347,10 @@ impl<T> [T] {
353347
#[stable(feature = "slice_first_last_chunk", since = "1.77.0")]
354348
#[rustc_const_stable(feature = "const_slice_first_last_chunk", since = "1.83.0")]
355349
pub const fn first_chunk_mut<const N: usize>(&mut self) -> Option<&mut [T; N]> {
356-
if self.len() < N {
357-
None
350+
if let Some((first, _)) = self.split_at_mut_checked(N) {
351+
first.as_mut_array()
358352
} else {
359-
// SAFETY: We explicitly check for the correct number of elements,
360-
// do not let the reference outlive the slice,
361-
// and require exclusive access to the entire slice to mutate the chunk.
362-
Some(unsafe { &mut *(self.as_mut_ptr().cast::<[T; N]>()) })
353+
None
363354
}
364355
}
365356

@@ -383,11 +374,13 @@ impl<T> [T] {
383374
#[stable(feature = "slice_first_last_chunk", since = "1.77.0")]
384375
#[rustc_const_stable(feature = "slice_first_last_chunk", since = "1.77.0")]
385376
pub const fn split_first_chunk<const N: usize>(&self) -> Option<(&[T; N], &[T])> {
386-
let Some((first, tail)) = self.split_at_checked(N) else { return None };
387-
388-
// SAFETY: We explicitly check for the correct number of elements,
389-
// and do not let the references outlive the slice.
390-
Some((unsafe { &*(first.as_ptr().cast::<[T; N]>()) }, tail))
377+
if let Some((first, tail)) = self.split_at_checked(N)
378+
&& let Some(first) = first.as_array()
379+
{
380+
Some((first, tail))
381+
} else {
382+
None
383+
}
391384
}
392385

393386
/// Returns a mutable array reference to the first `N` items in the slice and the remaining
@@ -415,12 +408,13 @@ impl<T> [T] {
415408
pub const fn split_first_chunk_mut<const N: usize>(
416409
&mut self,
417410
) -> Option<(&mut [T; N], &mut [T])> {
418-
let Some((first, tail)) = self.split_at_mut_checked(N) else { return None };
419-
420-
// SAFETY: We explicitly check for the correct number of elements,
421-
// do not let the reference outlive the slice,
422-
// and enforce exclusive mutability of the chunk by the split.
423-
Some((unsafe { &mut *(first.as_mut_ptr().cast::<[T; N]>()) }, tail))
411+
if let Some((first, tail)) = self.split_at_mut_checked(N)
412+
&& let Some(first) = first.as_mut_array()
413+
{
414+
Some((first, tail))
415+
} else {
416+
None
417+
}
424418
}
425419

426420
/// Returns an array reference to the last `N` items in the slice and the remaining slice.
@@ -443,12 +437,14 @@ impl<T> [T] {
443437
#[stable(feature = "slice_first_last_chunk", since = "1.77.0")]
444438
#[rustc_const_stable(feature = "slice_first_last_chunk", since = "1.77.0")]
445439
pub const fn split_last_chunk<const N: usize>(&self) -> Option<(&[T], &[T; N])> {
446-
let Some(index) = self.len().checked_sub(N) else { return None };
447-
let (init, last) = self.split_at(index);
448-
449-
// SAFETY: We explicitly check for the correct number of elements,
450-
// and do not let the references outlive the slice.
451-
Some((init, unsafe { &*(last.as_ptr().cast::<[T; N]>()) }))
440+
if let Some(index) = self.len().checked_sub(N)
441+
&& let (init, last) = self.split_at(index)
442+
&& let Some(last) = last.as_array()
443+
{
444+
Some((init, last))
445+
} else {
446+
None
447+
}
452448
}
453449

454450
/// Returns a mutable array reference to the last `N` items in the slice and the remaining
@@ -476,13 +472,14 @@ impl<T> [T] {
476472
pub const fn split_last_chunk_mut<const N: usize>(
477473
&mut self,
478474
) -> Option<(&mut [T], &mut [T; N])> {
479-
let Some(index) = self.len().checked_sub(N) else { return None };
480-
let (init, last) = self.split_at_mut(index);
481-
482-
// SAFETY: We explicitly check for the correct number of elements,
483-
// do not let the reference outlive the slice,
484-
// and enforce exclusive mutability of the chunk by the split.
485-
Some((init, unsafe { &mut *(last.as_mut_ptr().cast::<[T; N]>()) }))
475+
if let Some(index) = self.len().checked_sub(N)
476+
&& let (init, last) = self.split_at_mut(index)
477+
&& let Some(last) = last.as_mut_array()
478+
{
479+
Some((init, last))
480+
} else {
481+
None
482+
}
486483
}
487484

488485
/// Returns an array reference to the last `N` items in the slice.
@@ -506,12 +503,13 @@ impl<T> [T] {
506503
#[rustc_const_stable(feature = "const_slice_last_chunk", since = "1.80.0")]
507504
pub const fn last_chunk<const N: usize>(&self) -> Option<&[T; N]> {
508505
// FIXME(const-hack): Without const traits, we need this instead of `get`.
509-
let Some(index) = self.len().checked_sub(N) else { return None };
510-
let (_, last) = self.split_at(index);
506+
if let Some(index) = self.len().checked_sub(N) {
507+
let (_, last) = self.split_at(index);
511508

512-
// SAFETY: We explicitly check for the correct number of elements,
513-
// and do not let the references outlive the slice.
514-
Some(unsafe { &*(last.as_ptr().cast::<[T; N]>()) })
509+
last.as_array()
510+
} else {
511+
None
512+
}
515513
}
516514

517515
/// Returns a mutable array reference to the last `N` items in the slice.
@@ -536,13 +534,13 @@ impl<T> [T] {
536534
#[rustc_const_stable(feature = "const_slice_first_last_chunk", since = "1.83.0")]
537535
pub const fn last_chunk_mut<const N: usize>(&mut self) -> Option<&mut [T; N]> {
538536
// FIXME(const-hack): Without const traits, we need this instead of `get`.
539-
let Some(index) = self.len().checked_sub(N) else { return None };
540-
let (_, last) = self.split_at_mut(index);
537+
if let Some(index) = self.len().checked_sub(N) {
538+
let (_, last) = self.split_at_mut(index);
541539

542-
// SAFETY: We explicitly check for the correct number of elements,
543-
// do not let the reference outlive the slice,
544-
// and require exclusive access to the entire slice to mutate the chunk.
545-
Some(unsafe { &mut *(last.as_mut_ptr().cast::<[T; N]>()) })
540+
last.as_mut_array()
541+
} else {
542+
None
543+
}
546544
}
547545

548546
/// Returns a reference to an element or subslice depending on the type of

0 commit comments

Comments
 (0)