Auto merge of #137795 - Jarcho:idx_opt, r=davidtwco
Allow bounds checks when enumerating `IndexSlice` to be elided Without this hint, each loop iteration has to separately bounds check the index. See https://godbolt.org/z/zrfPY4Ten for an example. This is technically a behaviour change, but only in cases where the compiler is going to crash anyways.
This commit is contained in:
commit
d2b52c5c48
2 changed files with 10 additions and 0 deletions
|
@ -65,6 +65,8 @@ impl<I: Idx, T> IndexSlice<I, T> {
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn iter_enumerated(&self) -> impl DoubleEndedIterator<Item = (I, &T)> + ExactSizeIterator {
|
pub fn iter_enumerated(&self) -> impl DoubleEndedIterator<Item = (I, &T)> + ExactSizeIterator {
|
||||||
|
// Allow the optimizer to elide the bounds checking when creating each index.
|
||||||
|
let _ = I::new(self.len());
|
||||||
self.raw.iter().enumerate().map(|(n, t)| (I::new(n), t))
|
self.raw.iter().enumerate().map(|(n, t)| (I::new(n), t))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -72,6 +74,8 @@ impl<I: Idx, T> IndexSlice<I, T> {
|
||||||
pub fn indices(
|
pub fn indices(
|
||||||
&self,
|
&self,
|
||||||
) -> impl DoubleEndedIterator<Item = I> + ExactSizeIterator + Clone + 'static {
|
) -> impl DoubleEndedIterator<Item = I> + ExactSizeIterator + Clone + 'static {
|
||||||
|
// Allow the optimizer to elide the bounds checking when creating each index.
|
||||||
|
let _ = I::new(self.len());
|
||||||
(0..self.len()).map(|n| I::new(n))
|
(0..self.len()).map(|n| I::new(n))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -84,6 +88,8 @@ impl<I: Idx, T> IndexSlice<I, T> {
|
||||||
pub fn iter_enumerated_mut(
|
pub fn iter_enumerated_mut(
|
||||||
&mut self,
|
&mut self,
|
||||||
) -> impl DoubleEndedIterator<Item = (I, &mut T)> + ExactSizeIterator {
|
) -> impl DoubleEndedIterator<Item = (I, &mut T)> + ExactSizeIterator {
|
||||||
|
// Allow the optimizer to elide the bounds checking when creating each index.
|
||||||
|
let _ = I::new(self.len());
|
||||||
self.raw.iter_mut().enumerate().map(|(n, t)| (I::new(n), t))
|
self.raw.iter_mut().enumerate().map(|(n, t)| (I::new(n), t))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -93,6 +93,8 @@ impl<I: Idx, T> IndexVec<I, T> {
|
||||||
/// be allocated only once, with a capacity of at least `n`.)
|
/// be allocated only once, with a capacity of at least `n`.)
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn from_fn_n(func: impl FnMut(I) -> T, n: usize) -> Self {
|
pub fn from_fn_n(func: impl FnMut(I) -> T, n: usize) -> Self {
|
||||||
|
// Allow the optimizer to elide the bounds checking when creating each index.
|
||||||
|
let _ = I::new(n);
|
||||||
IndexVec::from_raw((0..n).map(I::new).map(func).collect())
|
IndexVec::from_raw((0..n).map(I::new).map(func).collect())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -128,6 +130,8 @@ impl<I: Idx, T> IndexVec<I, T> {
|
||||||
pub fn into_iter_enumerated(
|
pub fn into_iter_enumerated(
|
||||||
self,
|
self,
|
||||||
) -> impl DoubleEndedIterator<Item = (I, T)> + ExactSizeIterator {
|
) -> impl DoubleEndedIterator<Item = (I, T)> + ExactSizeIterator {
|
||||||
|
// Allow the optimizer to elide the bounds checking when creating each index.
|
||||||
|
let _ = I::new(self.len());
|
||||||
self.raw.into_iter().enumerate().map(|(n, t)| (I::new(n), t))
|
self.raw.into_iter().enumerate().map(|(n, t)| (I::new(n), t))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue