about summary refs log tree commit diff
diff options
context:
space:
mode:
authorThe 8472 <git@infinite-source.de>2023-01-01 05:22:54 +0100
committerThe 8472 <git@infinite-source.de>2023-06-12 13:03:29 +0200
commitd89e4581594a5d96b9ddaa454de3b25d6cc34ee8 (patch)
treea17d9024d422e1e21b73fd481e53c07ec2258a5f
parentcfb0f11a9f506292cd213872f759078d9302e0cc (diff)
downloadrust-d89e4581594a5d96b9ddaa454de3b25d6cc34ee8.tar.gz
rust-d89e4581594a5d96b9ddaa454de3b25d6cc34ee8.zip
optimize slice::Iter::fold
-rw-r--r--library/core/src/slice/iter/macros.rs23
1 files changed, 23 insertions, 0 deletions
diff --git a/library/core/src/slice/iter/macros.rs b/library/core/src/slice/iter/macros.rs
index 3462c0e020a..dd809ca459d 100644
--- a/library/core/src/slice/iter/macros.rs
+++ b/library/core/src/slice/iter/macros.rs
@@ -191,6 +191,29 @@ macro_rules! iterator {
                 self.next_back()
             }
 
+            #[inline]
+            fn fold<B, F>(mut self, init: B, mut f: F) -> B
+                where
+                    F: FnMut(B, Self::Item) -> B,
+            {
+                // Handling the 0-len case explicitly and then using a do-while style loop
+                // helps the optimizer. See issue #106288
+                if is_empty!(self) {
+                    return init;
+                }
+                let mut acc = init;
+                // SAFETY: The 0-len case was handled above so one loop iteration is guaranteed.
+                unsafe {
+                    loop {
+                        acc = f(acc, next_unchecked!(self));
+                        if is_empty!(self) {
+                            break;
+                        }
+                    }
+                }
+                acc
+            }
+
             // We override the default implementation, which uses `try_fold`,
             // because this simple implementation generates less LLVM IR and is
             // faster to compile.