Skip to content
Closed
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Prev Previous commit
Next Next commit
slice iter: rm all overflowing_* and switch conditions to mv dependen…
…t code close
  • Loading branch information
hkBst committed Nov 14, 2025
commit b60788e90534fdb6581ba2d8691ee636baf1981f
136 changes: 64 additions & 72 deletions library/core/src/slice/iter.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1601,15 +1601,15 @@ impl<'a, T> DoubleEndedIterator for Chunks<'a, T> {
#[inline]
fn nth_back(&mut self, n: usize) -> Option<Self::Item> {
let len = self.len();
if n >= len {
self.v = &self.v[..0]; // cheaper than &[]
None
} else {
if n < len {
let start = (len - 1 - n) * self.chunk_size;
let end = start + (self.v.len() - start).min(self.chunk_size);
let nth_back = &self.v[start..end];
self.v = &self.v[..start];
Some(nth_back)
} else {
self.v = &self.v[..0]; // cheaper than &[]
None
}
}
}
Expand Down Expand Up @@ -1770,10 +1770,7 @@ impl<'a, T> DoubleEndedIterator for ChunksMut<'a, T> {
#[inline]
fn nth_back(&mut self, n: usize) -> Option<Self::Item> {
let len = self.len();
if n >= len {
self.v = &mut [];
None
} else {
if n < len {
let start = (len - 1 - n) * self.chunk_size;
let end = match start.checked_add(self.chunk_size) {
Some(res) => cmp::min(self.v.len(), res),
Expand All @@ -1786,6 +1783,9 @@ impl<'a, T> DoubleEndedIterator for ChunksMut<'a, T> {
self.v = head;
// SAFETY: Nothing else points to or will point to the contents of this slice.
Some(unsafe { &mut *nth_back })
} else {
self.v = &mut [];
None
}
}
}
Expand Down Expand Up @@ -1952,15 +1952,15 @@ impl<'a, T> DoubleEndedIterator for ChunksExact<'a, T> {
#[inline]
fn nth_back(&mut self, n: usize) -> Option<Self::Item> {
let len = self.len();
if n >= len {
self.v = &self.v[..0]; // cheaper than &[]
None
} else {
if n < len {
let start = (len - 1 - n) * self.chunk_size;
let end = start + self.chunk_size;
let nth_back = &self.v[start..end];
self.v = &self.v[..start];
Some(nth_back)
} else {
self.v = &self.v[..0]; // cheaper than &[]
None
}
}
}
Expand Down Expand Up @@ -2111,10 +2111,7 @@ impl<'a, T> DoubleEndedIterator for ChunksExactMut<'a, T> {
#[inline]
fn nth_back(&mut self, n: usize) -> Option<Self::Item> {
let len = self.len();
if n >= len {
self.v = &mut [];
None
} else {
if n < len {
let start = (len - 1 - n) * self.chunk_size;
let end = start + self.chunk_size;
// SAFETY: The self.v contract ensures that any split_at_mut is valid.
Expand All @@ -2124,6 +2121,9 @@ impl<'a, T> DoubleEndedIterator for ChunksExactMut<'a, T> {
self.v = head;
// SAFETY: Nothing else points to or will point to the contents of this slice.
Some(unsafe { &mut *nth_back })
} else {
self.v = &mut [];
None
}
}
}
Expand Down Expand Up @@ -2307,16 +2307,12 @@ impl<'a, T> Iterator for RChunks<'a, T> {
if self.v.is_empty() {
None
} else {
let len = self.v.len();
let chunksz = cmp::min(len, self.chunk_size);
// SAFETY: split_at_unchecked just requires the argument be less
// than the length. This could only happen if the expression `len -
// chunksz` overflows. This could only happen if `chunksz > len`,
// which is impossible as we initialize it as the `min` of `len` and
// `self.chunk_size`.
let (fst, snd) = unsafe { self.v.split_at_unchecked(len - chunksz) };
self.v = fst;
Some(snd)
let idx = self.v.len().saturating_sub(self.chunk_size);
// SAFETY: self.chunk_size() > 0, so 0 <= idx < self.v.len().
// Thus `idx` is in-bounds for `self.v` and can be used as a valid argument for `split_at_mut_unchecked`.
let (rest, chunk) = unsafe { self.v.split_at_unchecked(idx) };
self.v = rest;
Some(chunk)
}
}

Expand Down Expand Up @@ -2389,17 +2385,16 @@ impl<'a, T> DoubleEndedIterator for RChunks<'a, T> {
#[inline]
fn nth_back(&mut self, n: usize) -> Option<Self::Item> {
let len = self.len();
if n >= len {
self.v = &self.v[..0]; // cheaper than &[]
None
} else {
// can't underflow because `n < len`
if n < len {
let offset_from_end = (len - 1 - n) * self.chunk_size;
let end = self.v.len() - offset_from_end;
let start = end.saturating_sub(self.chunk_size);
let nth_back = &self.v[start..end];
self.v = &self.v[end..];
Some(nth_back)
} else {
self.v = &self.v[..0]; // cheaper than &[]
None
}
}
}
Expand Down Expand Up @@ -2471,17 +2466,13 @@ impl<'a, T> Iterator for RChunksMut<'a, T> {
if self.v.is_empty() {
None
} else {
let sz = cmp::min(self.v.len(), self.chunk_size);
let len = self.v.len();
// SAFETY: split_at_mut_unchecked just requires the argument be less
// than the length. This could only happen if the expression
// `len - sz` overflows. This could only happen if `sz >
// len`, which is impossible as we initialize it as the `min` of
// `self.v.len()` (e.g. `len`) and `self.chunk_size`.
let (head, tail) = unsafe { self.v.split_at_mut_unchecked(len - sz) };
self.v = head;
let idx = self.v.len().saturating_sub(self.chunk_size);
// SAFETY: self.chunk_size() > 0, so 0 <= idx < self.v.len().
// Thus `idx` is in-bounds for `self.v` and can be used as a valid argument for `split_at_mut_unchecked`.
let (rest, chunk) = unsafe { self.v.split_at_mut_unchecked(idx) };
self.v = rest;
// SAFETY: Nothing else points to or will point to the contents of this slice.
Some(unsafe { &mut *tail })
Some(unsafe { &mut *chunk })
}
}

Expand All @@ -2502,12 +2493,9 @@ impl<'a, T> Iterator for RChunksMut<'a, T> {

#[inline]
fn nth(&mut self, n: usize) -> Option<&'a mut [T]> {
let (end, overflow) = n.overflowing_mul(self.chunk_size);
if end >= self.v.len() || overflow {
self.v = &mut [];
None
} else {
// Can't underflow because of the check above
if let Some(end) = n.checked_mul(self.chunk_size)
&& end < self.v.len()
{
let end = self.v.len() - end;
let start = match end.checked_sub(self.chunk_size) {
Some(sum) => sum,
Expand All @@ -2522,6 +2510,9 @@ impl<'a, T> Iterator for RChunksMut<'a, T> {
self.v = head;
// SAFETY: Nothing else points to or will point to the contents of this slice.
Some(unsafe { &mut *nth })
} else {
self.v = &mut [];
None
}
}

Expand Down Expand Up @@ -2566,10 +2557,7 @@ impl<'a, T> DoubleEndedIterator for RChunksMut<'a, T> {
#[inline]
fn nth_back(&mut self, n: usize) -> Option<Self::Item> {
let len = self.len();
if n >= len {
self.v = &mut [];
None
} else {
if n < len {
// can't underflow because `n < len`
let offset_from_end = (len - 1 - n) * self.chunk_size;
let end = self.v.len() - offset_from_end;
Expand All @@ -2581,6 +2569,9 @@ impl<'a, T> DoubleEndedIterator for RChunksMut<'a, T> {
self.v = tail;
// SAFETY: Nothing else points to or will point to the contents of this slice.
Some(unsafe { &mut *nth_back })
} else {
self.v = &mut [];
None
}
}
}
Expand Down Expand Up @@ -2711,14 +2702,14 @@ impl<'a, T> Iterator for RChunksExact<'a, T> {

#[inline]
fn nth(&mut self, n: usize) -> Option<Self::Item> {
let (end, overflow) = n.overflowing_mul(self.chunk_size);
if end >= self.v.len() || overflow {
if let Some(end) = n.checked_mul(self.chunk_size)
&& end < self.v.len()
{
self.v = &self.v[..self.v.len() - end];
self.next()
} else {
self.v = &self.v[..0]; // cheaper than &[]
None
} else {
let (fst, _) = self.v.split_at(self.v.len() - end);
self.v = fst;
self.next()
}
}

Expand Down Expand Up @@ -2751,10 +2742,7 @@ impl<'a, T> DoubleEndedIterator for RChunksExact<'a, T> {
#[inline]
fn nth_back(&mut self, n: usize) -> Option<Self::Item> {
let len = self.len();
if n >= len {
self.v = &self.v[..0]; // cheaper than &[]
None
} else {
if n < len {
// now that we know that `n` corresponds to a chunk,
// none of these operations can underflow/overflow
let offset = (len - n) * self.chunk_size;
Expand All @@ -2763,6 +2751,9 @@ impl<'a, T> DoubleEndedIterator for RChunksExact<'a, T> {
let nth_back = &self.v[start..end];
self.v = &self.v[end..];
Some(nth_back)
} else {
self.v = &self.v[..0]; // cheaper than &[]
None
}
}
}
Expand Down Expand Up @@ -2875,16 +2866,17 @@ impl<'a, T> Iterator for RChunksExactMut<'a, T> {

#[inline]
fn nth(&mut self, n: usize) -> Option<&'a mut [T]> {
let (end, overflow) = n.overflowing_mul(self.chunk_size);
if end >= self.v.len() || overflow {
self.v = &mut [];
None
} else {
let len = self.v.len();
if let Some(end) = n.checked_mul(self.chunk_size)
&& end < self.v.len()
{
let idx = self.v.len() - end;
// SAFETY: The self.v contract ensures that any split_at_mut is valid.
let (fst, _) = unsafe { self.v.split_at_mut(len - end) };
let (fst, _) = unsafe { self.v.split_at_mut(idx) };
self.v = fst;
self.next()
} else {
self.v = &mut [];
None
}
}

Expand Down Expand Up @@ -2919,10 +2911,7 @@ impl<'a, T> DoubleEndedIterator for RChunksExactMut<'a, T> {
#[inline]
fn nth_back(&mut self, n: usize) -> Option<Self::Item> {
let len = self.len();
if n >= len {
self.v = &mut [];
None
} else {
if n < len {
// now that we know that `n` corresponds to a chunk,
// none of these operations can underflow/overflow
let offset = (len - n) * self.chunk_size;
Expand All @@ -2935,6 +2924,9 @@ impl<'a, T> DoubleEndedIterator for RChunksExactMut<'a, T> {
self.v = tail;
// SAFETY: Nothing else points to or will point to the contents of this slice.
Some(unsafe { &mut *nth_back })
} else {
self.v = &mut [];
None
}
}
}
Expand Down
Loading