about summary refs log tree commit diff
diff options
context:
space:
mode:
authorbors <bors@rust-lang.org>2024-04-26 11:16:05 +0000
committerbors <bors@rust-lang.org>2024-04-26 11:16:05 +0000
commit5ff8fbb2d83d423974d21d754b5ee56a4c869551 (patch)
tree4cba6ab69ec4e1ddee7dfe96968679ee85f090fd
parent6acb9e75ebc936df737381a9d0b7a7bccd6f0b2f (diff)
parentcd47a0ed086ca89faa64776ff15e118ba6aa27f3 (diff)
downloadrust-5ff8fbb2d83d423974d21d754b5ee56a4c869551.tar.gz
rust-5ff8fbb2d83d423974d21d754b5ee56a4c869551.zip
Auto merge of #124393 - scottmcm:do-the-macros-still-matter, r=joboet
Convert some iter macros to normal functions

With all the MIR optimization changes that have happened since these were written, let's see if they still actually matter.

\*perf comes back\*

Well, it looks like it's not longer relevant for instruction, cycle, nor wall-time perf.  Looks like a bunch of things are maybe 10kb bigger in debug, but some are also 50k *smaller* in debug.

So I think they should switch to being normal functions as the "greatly improves performance" justification for them being macros seems to no longer be true -- probably thanks to us always building `core` with `-Z inline-mir` so the difference is negligible.
-rw-r--r--library/core/src/slice/iter/macros.rs41
1 files changed, 20 insertions, 21 deletions
diff --git a/library/core/src/slice/iter/macros.rs b/library/core/src/slice/iter/macros.rs
index 7910981d0f5..0b8ff5cc012 100644
--- a/library/core/src/slice/iter/macros.rs
+++ b/library/core/src/slice/iter/macros.rs
@@ -70,21 +70,19 @@ macro_rules! iterator {
         $into_ref:ident,
         {$($extra:tt)*}
     ) => {
-        // Returns the first element and moves the start of the iterator forwards by 1.
-        // Greatly improves performance compared to an inlined function. The iterator
-        // must not be empty.
-        macro_rules! next_unchecked {
-            ($self: ident) => { $self.post_inc_start(1).$into_ref() }
-        }
-
-        // Returns the last element and moves the end of the iterator backwards by 1.
-        // Greatly improves performance compared to an inlined function. The iterator
-        // must not be empty.
-        macro_rules! next_back_unchecked {
-            ($self: ident) => { $self.pre_dec_end(1).$into_ref() }
-        }
-
         impl<'a, T> $name<'a, T> {
+            /// Returns the last element and moves the end of the iterator backwards by 1.
+            ///
+            /// # Safety
+            ///
+            /// The iterator must not be empty
+            #[inline]
+            unsafe fn next_back_unchecked(&mut self) -> $elem {
+                // SAFETY: the caller promised it's not empty, so
+                // the offsetting is in-bounds and there's an element to return.
+                unsafe { self.pre_dec_end(1).$into_ref() }
+            }
+
             // Helper function for creating a slice from the iterator.
             #[inline(always)]
             fn make_slice(&self) -> &'a [T] {
@@ -156,13 +154,13 @@ macro_rules! iterator {
             fn next(&mut self) -> Option<$elem> {
                 // could be implemented with slices, but this avoids bounds checks
 
-                // SAFETY: The call to `next_unchecked!` is
+                // SAFETY: The call to `next_unchecked` is
                 // safe since we check if the iterator is empty first.
                 unsafe {
                     if is_empty!(self) {
                         None
                     } else {
-                        Some(next_unchecked!(self))
+                        Some(self.next_unchecked())
                     }
                 }
             }
@@ -191,7 +189,7 @@ macro_rules! iterator {
                 // SAFETY: We are in bounds. `post_inc_start` does the right thing even for ZSTs.
                 unsafe {
                     self.post_inc_start(n);
-                    Some(next_unchecked!(self))
+                    Some(self.next_unchecked())
                 }
             }
 
@@ -392,13 +390,13 @@ macro_rules! iterator {
             fn next_back(&mut self) -> Option<$elem> {
                 // could be implemented with slices, but this avoids bounds checks
 
-                // SAFETY: The call to `next_back_unchecked!`
+                // SAFETY: The call to `next_back_unchecked`
                 // is safe since we check if the iterator is empty first.
                 unsafe {
                     if is_empty!(self) {
                         None
                     } else {
-                        Some(next_back_unchecked!(self))
+                        Some(self.next_back_unchecked())
                     }
                 }
             }
@@ -416,7 +414,7 @@ macro_rules! iterator {
                 // SAFETY: We are in bounds. `pre_dec_end` does the right thing even for ZSTs.
                 unsafe {
                     self.pre_dec_end(n);
-                    Some(next_back_unchecked!(self))
+                    Some(self.next_back_unchecked())
                 }
             }
 
@@ -436,10 +434,11 @@ macro_rules! iterator {
         unsafe impl<T> TrustedLen for $name<'_, T> {}
 
         impl<'a, T> UncheckedIterator for $name<'a, T> {
+            #[inline]
             unsafe fn next_unchecked(&mut self) -> $elem {
                 // SAFETY: The caller promised there's at least one more item.
                 unsafe {
-                    next_unchecked!(self)
+                    self.post_inc_start(1).$into_ref()
                 }
             }
         }