From 83595f9242ad9e8a7da091f65d450e44e4434f89 Mon Sep 17 00:00:00 2001 From: Scott McMurray Date: Sat, 2 Apr 2022 14:29:41 -0700 Subject: Fix `array::IntoIter::fold` to use the optimized `Range::fold` It was using `Iterator::by_ref` in the implementation, which ended up pessimizing it enough that, for example, it didn't vectorize when we tried it in the conversation. Demonstration that the codegen test doesn't pass on the current nightly: --- library/core/src/array/iter.rs | 16 +++++++++++++++- 1 file changed, 15 insertions(+), 1 deletion(-) (limited to 'library/core/src/array') diff --git a/library/core/src/array/iter.rs b/library/core/src/array/iter.rs index e5024c215be..baf2f2d6c97 100644 --- a/library/core/src/array/iter.rs +++ b/library/core/src/array/iter.rs @@ -266,7 +266,7 @@ impl Iterator for IntoIter { Fold: FnMut(Acc, Self::Item) -> Acc, { let data = &mut self.data; - self.alive.by_ref().fold(init, |acc, idx| { + iter::ByRefSized(&mut self.alive).fold(init, |acc, idx| { // SAFETY: idx is obtained by folding over the `alive` range, which implies the // value is currently considered alive but as the range is being consumed each value // we read here will only be read once and then considered dead. @@ -323,6 +323,20 @@ impl DoubleEndedIterator for IntoIter { }) } + #[inline] + fn rfold(mut self, init: Acc, mut rfold: Fold) -> Acc + where + Fold: FnMut(Acc, Self::Item) -> Acc, + { + let data = &mut self.data; + iter::ByRefSized(&mut self.alive).rfold(init, |acc, idx| { + // SAFETY: idx is obtained by folding over the `alive` range, which implies the + // value is currently considered alive but as the range is being consumed each value + // we read here will only be read once and then considered dead. + rfold(acc, unsafe { data.get_unchecked(idx).assume_init_read() }) + }) + } + fn advance_back_by(&mut self, n: usize) -> Result<(), usize> { let len = self.len(); -- cgit 1.4.1-3-g733a5