about summary refs log tree commit diff
path: root/compiler/rustc_index
diff options
context:
space:
mode:
authorbors <bors@rust-lang.org>2025-03-12 00:30:16 +0000
committerbors <bors@rust-lang.org>2025-03-12 00:30:16 +0000
commitd2b52c5c48ea024fc277feddcc92a60cc92be13c (patch)
tree5fdf99e53151706e8d2776ca0ced6645f12e944d /compiler/rustc_index
parentc6251023208f7e9789602376909af8aaf09483b7 (diff)
parentda0fbc19a5b2710d03c9f2d9ccd6bc572c2b2ffa (diff)
downloadrust-d2b52c5c48ea024fc277feddcc92a60cc92be13c.tar.gz
rust-d2b52c5c48ea024fc277feddcc92a60cc92be13c.zip
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.
Diffstat (limited to 'compiler/rustc_index')
-rw-r--r--compiler/rustc_index/src/slice.rs6
-rw-r--r--compiler/rustc_index/src/vec.rs4
2 files changed, 10 insertions, 0 deletions
diff --git a/compiler/rustc_index/src/slice.rs b/compiler/rustc_index/src/slice.rs
index f17ea9e4b59..0f4f885bb3a 100644
--- a/compiler/rustc_index/src/slice.rs
+++ b/compiler/rustc_index/src/slice.rs
@@ -65,6 +65,8 @@ impl<I: Idx, T> IndexSlice<I, T> {
 
     #[inline]
     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))
     }
 
@@ -72,6 +74,8 @@ impl<I: Idx, T> IndexSlice<I, T> {
     pub fn indices(
         &self,
     ) -> 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))
     }
 
@@ -84,6 +88,8 @@ impl<I: Idx, T> IndexSlice<I, T> {
     pub fn iter_enumerated_mut(
         &mut self,
     ) -> 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))
     }
 
diff --git a/compiler/rustc_index/src/vec.rs b/compiler/rustc_index/src/vec.rs
index 7f3f3ead5f2..13f0dda180b 100644
--- a/compiler/rustc_index/src/vec.rs
+++ b/compiler/rustc_index/src/vec.rs
@@ -93,6 +93,8 @@ impl<I: Idx, T> IndexVec<I, T> {
     /// be allocated only once, with a capacity of at least `n`.)
     #[inline]
     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())
     }
 
@@ -128,6 +130,8 @@ impl<I: Idx, T> IndexVec<I, T> {
     pub fn into_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.into_iter().enumerate().map(|(n, t)| (I::new(n), t))
     }