Skip to content

Optimize unchecked indexing into chunks and chunks_mut #86823

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
Jul 8, 2021
Merged
Changes from all commits
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
24 changes: 11 additions & 13 deletions library/core/src/slice/iter.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1418,18 +1418,17 @@ impl<'a, T> Iterator for Chunks<'a, T> {
#[doc(hidden)]
unsafe fn __iterator_get_unchecked(&mut self, idx: usize) -> Self::Item {
let start = idx * self.chunk_size;
let end = match start.checked_add(self.chunk_size) {
None => self.v.len(),
Some(end) => cmp::min(end, self.v.len()),
};
// SAFETY: the caller guarantees that `i` is in bounds,
// which means that `start` must be in bounds of the
// underlying `self.v` slice, and we made sure that `end`
// underlying `self.v` slice, and we made sure that `len`
// is also in bounds of `self.v`. Thus, `start` cannot overflow
// an `isize`, and the slice constructed by `from_raw_parts`
// is a subslice of `self.v` which is guaranteed to be valid
// for the lifetime `'a` of `self.v`.
unsafe { from_raw_parts(self.v.as_ptr().add(start), end - start) }
unsafe {
let len = cmp::min(self.v.len().unchecked_sub(start), self.chunk_size);
from_raw_parts(self.v.as_ptr().add(start), len)
}
}
}

Expand Down Expand Up @@ -1457,7 +1456,7 @@ impl<'a, T> DoubleEndedIterator for Chunks<'a, T> {
} else {
let start = (len - 1 - n) * self.chunk_size;
let end = match start.checked_add(self.chunk_size) {
Some(res) => cmp::min(res, self.v.len()),
Some(res) => cmp::min(self.v.len(), res),
None => self.v.len(),
};
let nth_back = &self.v[start..end];
Expand Down Expand Up @@ -1579,17 +1578,16 @@ impl<'a, T> Iterator for ChunksMut<'a, T> {
#[doc(hidden)]
unsafe fn __iterator_get_unchecked(&mut self, idx: usize) -> Self::Item {
let start = idx * self.chunk_size;
let end = match start.checked_add(self.chunk_size) {
None => self.v.len(),
Some(end) => cmp::min(end, self.v.len()),
};
// SAFETY: see comments for `Chunks::__iterator_get_unchecked`.
//
// Also note that the caller also guarantees that we're never called
// with the same index again, and that no other methods that will
// access this subslice are called, so it is valid for the returned
// slice to be mutable.
unsafe { from_raw_parts_mut(self.v.as_mut_ptr().add(start), end - start) }
unsafe {
let len = cmp::min(self.v.len().unchecked_sub(start), self.chunk_size);
from_raw_parts_mut(self.v.as_mut_ptr().add(start), len)
}
}
}

Expand Down Expand Up @@ -1619,7 +1617,7 @@ impl<'a, T> DoubleEndedIterator for ChunksMut<'a, T> {
} else {
let start = (len - 1 - n) * self.chunk_size;
let end = match start.checked_add(self.chunk_size) {
Some(res) => cmp::min(res, self.v.len()),
Some(res) => cmp::min(self.v.len(), res),
None => self.v.len(),
};
let (temp, _tail) = mem::replace(&mut self.v, &mut []).split_at_mut(end);
Expand Down