Skip to content

Commit 53d5261

Browse files
committed
Move unsafe code of slice new function of their Iterator structs
Init false state in Split* constructors
1 parent 9fe9c6d commit 53d5261

File tree

2 files changed

+122
-141
lines changed

2 files changed

+122
-141
lines changed

library/core/src/slice/iter.rs

+106-42
Original file line numberDiff line numberDiff line change
@@ -82,8 +82,20 @@ unsafe impl<T: Sync> Sync for Iter<'_, T> {}
8282
unsafe impl<T: Sync> Send for Iter<'_, T> {}
8383

8484
impl<'a, T> Iter<'a, T> {
85-
pub(super) fn new(ptr: NonNull<T>, end: *const T) -> Self {
86-
Self { ptr, end, _marker: PhantomData }
85+
pub(super) fn new(slice: &'a [T]) -> Self {
86+
let ptr = slice.as_ptr();
87+
// SAFETY: Similar to `IterMut::new`.
88+
unsafe {
89+
assume(!ptr.is_null());
90+
91+
let end = if mem::size_of::<T>() == 0 {
92+
(ptr as *const u8).wrapping_add(slice.len()) as *const T
93+
} else {
94+
ptr.add(slice.len())
95+
};
96+
97+
Self { ptr: NonNull::new_unchecked(ptr as *mut T), end, _marker: PhantomData }
98+
}
8799
}
88100

89101
/// Views the underlying data as a subslice of the original data.
@@ -188,8 +200,35 @@ unsafe impl<T: Sync> Sync for IterMut<'_, T> {}
188200
unsafe impl<T: Send> Send for IterMut<'_, T> {}
189201

190202
impl<'a, T> IterMut<'a, T> {
191-
pub(super) fn new(ptr: NonNull<T>, end: *mut T) -> Self {
192-
Self { ptr, end, _marker: PhantomData }
203+
pub(super) fn new(slice: &'a mut [T]) -> Self {
204+
let ptr = slice.as_mut_ptr();
205+
// SAFETY: There are several things here:
206+
//
207+
// `ptr` has been obtained by `slice.as_ptr()` where `slice` is a valid
208+
// reference thus it is non-NUL and safe to use and pass to
209+
// `NonNull::new_unchecked` .
210+
//
211+
// Adding `slice.len()` to the starting pointer gives a pointer
212+
// at the end of `slice`. `end` will never be dereferenced, only checked
213+
// for direct pointer equality with `ptr` to check if the iterator is
214+
// done.
215+
//
216+
// In the case of a ZST, the end pointer is just the start pointer plus
217+
// the length, to also allows for the fast `ptr == end` check.
218+
//
219+
// See the `next_unchecked!` and `is_empty!` macros as well as the
220+
// `post_inc_start` method for more informations.
221+
unsafe {
222+
assume(!ptr.is_null());
223+
224+
let end = if mem::size_of::<T>() == 0 {
225+
(ptr as *mut u8).wrapping_add(slice.len()) as *mut T
226+
} else {
227+
ptr.add(slice.len())
228+
};
229+
230+
Self { ptr: NonNull::new_unchecked(ptr), end, _marker: PhantomData }
231+
}
193232
}
194233

195234
/// Views the underlying data as a subslice of the original data.
@@ -291,8 +330,8 @@ where
291330
}
292331

293332
impl<'a, T: 'a, P: FnMut(&T) -> bool> Split<'a, T, P> {
294-
pub(super) fn new(slice: &'a [T], pred: P, finished: bool) -> Self {
295-
Self { v: slice, pred, finished }
333+
pub(super) fn new(slice: &'a [T], pred: P) -> Self {
334+
Self { v: slice, pred, finished: false }
296335
}
297336
}
298337

@@ -405,8 +444,9 @@ where
405444
}
406445

407446
impl<'a, T: 'a, P: FnMut(&T) -> bool> SplitInclusive<'a, T, P> {
408-
pub(super) fn new(slice: &'a [T], pred: P, finished: bool) -> Self {
409-
Self { v: slice, pred, finished }
447+
#[inline]
448+
pub(super) fn new(slice: &'a [T], pred: P) -> Self {
449+
Self { v: slice, pred, finished: false }
410450
}
411451
}
412452

@@ -509,8 +549,9 @@ where
509549
}
510550

511551
impl<'a, T: 'a, P: FnMut(&T) -> bool> SplitMut<'a, T, P> {
512-
pub(super) fn new(slice: &'a mut [T], pred: P, finished: bool) -> Self {
513-
Self { v: slice, pred, finished }
552+
#[inline]
553+
pub(super) fn new(slice: &'a mut [T], pred: P) -> Self {
554+
Self { v: slice, pred, finished: false }
514555
}
515556
}
516557

@@ -630,8 +671,9 @@ where
630671
}
631672

632673
impl<'a, T: 'a, P: FnMut(&T) -> bool> SplitInclusiveMut<'a, T, P> {
633-
pub(super) fn new(slice: &'a mut [T], pred: P, finished: bool) -> Self {
634-
Self { v: slice, pred, finished }
674+
#[inline]
675+
pub(super) fn new(slice: &'a mut [T], pred: P) -> Self {
676+
Self { v: slice, pred, finished: false }
635677
}
636678
}
637679

@@ -742,8 +784,9 @@ where
742784
}
743785

744786
impl<'a, T: 'a, P: FnMut(&T) -> bool> RSplit<'a, T, P> {
745-
pub(super) fn new(slice: &'a [T], pred: P, finished: bool) -> Self {
746-
Self { inner: Split::new(slice, pred, finished) }
787+
#[inline]
788+
pub(super) fn new(slice: &'a [T], pred: P) -> Self {
789+
Self { inner: Split::new(slice, pred) }
747790
}
748791
}
749792

@@ -819,8 +862,9 @@ where
819862
}
820863

821864
impl<'a, T: 'a, P: FnMut(&T) -> bool> RSplitMut<'a, T, P> {
822-
pub(super) fn new(slice: &'a mut [T], pred: P, finished: bool) -> Self {
823-
Self { inner: SplitMut::new(slice, pred, finished) }
865+
#[inline]
866+
pub(super) fn new(slice: &'a mut [T], pred: P) -> Self {
867+
Self { inner: SplitMut::new(slice, pred) }
824868
}
825869
}
826870

@@ -1516,13 +1560,15 @@ pub struct ChunksExact<'a, T: 'a> {
15161560
chunk_size: usize,
15171561
}
15181562

1519-
impl<'a, T: 'a> ChunksExact<'a, T> {
1520-
pub(super) fn new(slice: &'a [T], rem: &'a [T], size: usize) -> Self {
1521-
Self { v: slice, rem, chunk_size: size }
1563+
impl<'a, T> ChunksExact<'a, T> {
1564+
pub(super) fn new(slice: &'a [T], chunk_size: usize) -> Self {
1565+
let rem = slice.len() % chunk_size;
1566+
let fst_len = slice.len() - rem;
1567+
// SAFETY: 0 <= fst_len <= slice.len() by construction above
1568+
let (fst, snd) = unsafe { slice.split_at_unchecked(fst_len) };
1569+
Self { v: fst, rem: snd, chunk_size }
15221570
}
1523-
}
15241571

1525-
impl<'a, T> ChunksExact<'a, T> {
15261572
/// Returns the remainder of the original slice that is not going to be
15271573
/// returned by the iterator. The returned slice has at most `chunk_size-1`
15281574
/// elements.
@@ -1662,13 +1708,15 @@ pub struct ChunksExactMut<'a, T: 'a> {
16621708
chunk_size: usize,
16631709
}
16641710

1665-
impl<'a, T: 'a> ChunksExactMut<'a, T> {
1666-
pub(super) fn new(slice: &'a mut [T], rem: &'a mut [T], size: usize) -> Self {
1667-
Self { v: slice, rem, chunk_size: size }
1711+
impl<'a, T> ChunksExactMut<'a, T> {
1712+
pub(super) fn new(slice: &'a mut [T], chunk_size: usize) -> Self {
1713+
let rem = slice.len() % chunk_size;
1714+
let fst_len = slice.len() - rem;
1715+
// SAFETY: 0 <= fst_len <= slice.len() by construction above
1716+
let (fst, snd) = unsafe { slice.split_at_mut_unchecked(fst_len) };
1717+
Self { v: fst, rem: snd, chunk_size }
16681718
}
1669-
}
16701719

1671-
impl<'a, T> ChunksExactMut<'a, T> {
16721720
/// Returns the remainder of the original slice that is not going to be
16731721
/// returned by the iterator. The returned slice has at most `chunk_size-1`
16741722
/// elements.
@@ -1801,8 +1849,9 @@ pub struct ArrayWindows<'a, T: 'a, const N: usize> {
18011849
}
18021850

18031851
impl<'a, T: 'a, const N: usize> ArrayWindows<'a, T, N> {
1804-
pub(super) fn new(head: *const T, num: usize) -> Self {
1805-
Self { slice_head: head, num, marker: PhantomData }
1852+
pub(super) fn new(slice: &'a [T]) -> Self {
1853+
let num_windows = slice.len().saturating_sub(N - 1);
1854+
Self { slice_head: slice.as_ptr(), num: num_windows, marker: PhantomData }
18061855
}
18071856
}
18081857

@@ -1910,13 +1959,17 @@ pub struct ArrayChunks<'a, T: 'a, const N: usize> {
19101959
rem: &'a [T],
19111960
}
19121961

1913-
impl<'a, T: 'a, const N: usize> ArrayChunks<'a, T, N> {
1914-
pub(super) fn new(iter: Iter<'a, [T; N]>, rem: &'a [T]) -> Self {
1915-
Self { iter, rem }
1962+
impl<'a, T, const N: usize> ArrayChunks<'a, T, N> {
1963+
pub(super) fn new(slice: &'a [T]) -> Self {
1964+
let len = slice.len() / N;
1965+
let (fst, snd) = slice.split_at(len * N);
1966+
// SAFETY: We cast a slice of `len * N` elements into
1967+
// a slice of `len` many `N` elements chunks.
1968+
let array_slice: &[[T; N]] = unsafe { from_raw_parts(fst.as_ptr().cast(), len) };
1969+
1970+
Self { iter: array_slice.iter(), rem: snd }
19161971
}
1917-
}
19181972

1919-
impl<'a, T, const N: usize> ArrayChunks<'a, T, N> {
19201973
/// Returns the remainder of the original slice that is not going to be
19211974
/// returned by the iterator. The returned slice has at most `N-1`
19221975
/// elements.
@@ -2023,13 +2076,18 @@ pub struct ArrayChunksMut<'a, T: 'a, const N: usize> {
20232076
rem: &'a mut [T],
20242077
}
20252078

2026-
impl<'a, T: 'a, const N: usize> ArrayChunksMut<'a, T, N> {
2027-
pub(super) fn new(iter: IterMut<'a, [T; N]>, rem: &'a mut [T]) -> Self {
2028-
Self { iter, rem }
2079+
impl<'a, T, const N: usize> ArrayChunksMut<'a, T, N> {
2080+
pub(super) fn new(slice: &'a mut [T]) -> Self {
2081+
let len = slice.len() / N;
2082+
let (fst, snd) = slice.split_at_mut(len * N);
2083+
// SAFETY: We cast a slice of `len * N` elements into
2084+
// a slice of `len` many `N` elements chunks.
2085+
unsafe {
2086+
let array_slice: &mut [[T; N]] = from_raw_parts_mut(fst.as_mut_ptr().cast(), len);
2087+
Self { iter: array_slice.iter_mut(), rem: snd }
2088+
}
20292089
}
2030-
}
20312090

2032-
impl<'a, T, const N: usize> ArrayChunksMut<'a, T, N> {
20332091
/// Returns the remainder of the original slice that is not going to be
20342092
/// returned by the iterator. The returned slice has at most `N-1`
20352093
/// elements.
@@ -2440,8 +2498,11 @@ pub struct RChunksExact<'a, T: 'a> {
24402498
}
24412499

24422500
impl<'a, T> RChunksExact<'a, T> {
2443-
pub(super) fn new(slice: &'a [T], rem: &'a [T], size: usize) -> Self {
2444-
Self { v: slice, rem, chunk_size: size }
2501+
pub(super) fn new(slice: &'a [T], chunk_size: usize) -> Self {
2502+
let rem = slice.len() % chunk_size;
2503+
// SAFETY: 0 <= rem <= slice.len() by construction above
2504+
let (fst, snd) = unsafe { slice.split_at_unchecked(rem) };
2505+
Self { v: snd, rem: fst, chunk_size }
24452506
}
24462507

24472508
/// Returns the remainder of the original slice that is not going to be
@@ -2589,8 +2650,11 @@ pub struct RChunksExactMut<'a, T: 'a> {
25892650
}
25902651

25912652
impl<'a, T> RChunksExactMut<'a, T> {
2592-
pub(super) fn new(slice: &'a mut [T], rem: &'a mut [T], size: usize) -> Self {
2593-
Self { v: slice, rem, chunk_size: size }
2653+
pub(super) fn new(slice: &'a mut [T], chunk_size: usize) -> Self {
2654+
let rem = slice.len() % chunk_size;
2655+
// SAFETY: 0 <= rem <= slice.len() by construction above
2656+
let (fst, snd) = unsafe { slice.split_at_mut_unchecked(rem) };
2657+
Self { v: snd, rem: fst, chunk_size }
25942658
}
25952659

25962660
/// Returns the remainder of the original slice that is not going to be

0 commit comments

Comments
 (0)