Skip to content

Commit a21554c

Browse files
author
Markus Westerlind
committed
perf: Let &mut T iterators forward try_fold and friends
Currently `impl Iterator for &mut T` does not forward `try_fold` to the inner `T` which means that it is easy to lose optimized implementations of this method and methods that forward to it. By using specialization on `T: Sized` we can allow calls on non-trait objects to still forward to the inner methods.
1 parent 1f8df25 commit a21554c

File tree

2 files changed

+84
-12
lines changed

2 files changed

+84
-12
lines changed

src/libcore/iter/traits/double_ended.rs

+39-6
Original file line numberDiff line numberDiff line change
@@ -155,17 +155,13 @@ pub trait DoubleEndedIterator: Iterator {
155155
/// ```
156156
#[inline]
157157
#[stable(feature = "iterator_try_fold", since = "1.27.0")]
158-
fn try_rfold<B, F, R>(&mut self, init: B, mut f: F) -> R
158+
fn try_rfold<B, F, R>(&mut self, init: B, f: F) -> R
159159
where
160160
Self: Sized,
161161
F: FnMut(B, Self::Item) -> R,
162162
R: Try<Ok = B>,
163163
{
164-
let mut accum = init;
165-
while let Some(x) = self.next_back() {
166-
accum = f(accum, x)?;
167-
}
168-
Try::from_ok(accum)
164+
try_rfold(self, init, f)
169165
}
170166

171167
/// An iterator method that reduces the iterator's elements to a single,
@@ -296,6 +292,20 @@ pub trait DoubleEndedIterator: Iterator {
296292
}
297293
}
298294

295+
#[inline]
296+
fn try_rfold<I, B, F, R>(iter: &mut I, init: B, mut f: F) -> R
297+
where
298+
I: DoubleEndedIterator,
299+
F: FnMut(B, I::Item) -> R,
300+
R: Try<Ok = B>,
301+
{
302+
let mut accum = init;
303+
while let Some(x) = iter.next_back() {
304+
accum = f(accum, x)?;
305+
}
306+
Try::from_ok(accum)
307+
}
308+
299309
#[stable(feature = "rust1", since = "1.0.0")]
300310
impl<'a, I: DoubleEndedIterator + ?Sized> DoubleEndedIterator for &'a mut I {
301311
fn next_back(&mut self) -> Option<I::Item> {
@@ -304,4 +314,27 @@ impl<'a, I: DoubleEndedIterator + ?Sized> DoubleEndedIterator for &'a mut I {
304314
fn nth_back(&mut self, n: usize) -> Option<I::Item> {
305315
(**self).nth_back(n)
306316
}
317+
318+
#[inline]
319+
default fn try_rfold<B, F, R>(&mut self, init: B, f: F) -> R
320+
where
321+
Self: Sized,
322+
F: FnMut(B, Self::Item) -> R,
323+
R: Try<Ok = B>,
324+
{
325+
try_rfold(self, init, f)
326+
}
327+
}
328+
329+
#[stable(feature = "rust1", since = "1.0.0")]
330+
impl<'a, I: DoubleEndedIterator> DoubleEndedIterator for &'a mut I {
331+
#[inline]
332+
fn try_rfold<B, F, R>(&mut self, init: B, f: F) -> R
333+
where
334+
Self: Sized,
335+
F: FnMut(B, Self::Item) -> R,
336+
R: Try<Ok = B>,
337+
{
338+
(**self).try_rfold(init, f)
339+
}
307340
}

src/libcore/iter/traits/iterator.rs

+45-6
Original file line numberDiff line numberDiff line change
@@ -1865,17 +1865,13 @@ pub trait Iterator {
18651865
/// ```
18661866
#[inline]
18671867
#[stable(feature = "iterator_try_fold", since = "1.27.0")]
1868-
fn try_fold<B, F, R>(&mut self, init: B, mut f: F) -> R
1868+
fn try_fold<B, F, R>(&mut self, init: B, f: F) -> R
18691869
where
18701870
Self: Sized,
18711871
F: FnMut(B, Self::Item) -> R,
18721872
R: Try<Ok = B>,
18731873
{
1874-
let mut accum = init;
1875-
while let Some(x) = self.next() {
1876-
accum = f(accum, x)?;
1877-
}
1878-
Try::from_ok(accum)
1874+
try_fold(self, init, f)
18791875
}
18801876

18811877
/// An iterator method that applies a fallible function to each item in the
@@ -3224,16 +3220,59 @@ where
32243220
Some(it.fold(first, f))
32253221
}
32263222

3223+
#[inline]
3224+
fn try_fold<I, B, F, R>(iter: &mut I, init: B, mut f: F) -> R
3225+
where
3226+
I: Iterator,
3227+
F: FnMut(B, I::Item) -> R,
3228+
R: Try<Ok = B>,
3229+
{
3230+
let mut accum = init;
3231+
while let Some(x) = iter.next() {
3232+
accum = f(accum, x)?;
3233+
}
3234+
Try::from_ok(accum)
3235+
}
3236+
32273237
#[stable(feature = "rust1", since = "1.0.0")]
32283238
impl<I: Iterator + ?Sized> Iterator for &mut I {
32293239
type Item = I::Item;
3240+
3241+
#[inline]
32303242
fn next(&mut self) -> Option<I::Item> {
32313243
(**self).next()
32323244
}
3245+
3246+
#[inline]
32333247
fn size_hint(&self) -> (usize, Option<usize>) {
32343248
(**self).size_hint()
32353249
}
3250+
3251+
#[inline]
32363252
fn nth(&mut self, n: usize) -> Option<Self::Item> {
32373253
(**self).nth(n)
32383254
}
3255+
3256+
#[inline]
3257+
default fn try_fold<Acc, F, R>(&mut self, init: Acc, f: F) -> R
3258+
where
3259+
Self: Sized,
3260+
F: FnMut(Acc, Self::Item) -> R,
3261+
R: Try<Ok = Acc>,
3262+
{
3263+
try_fold(self, init, f)
3264+
}
3265+
}
3266+
3267+
#[stable(feature = "rust1", since = "1.0.0")]
3268+
impl<I: Iterator> Iterator for &mut I {
3269+
#[inline]
3270+
fn try_fold<B, F, R>(&mut self, init: B, f: F) -> R
3271+
where
3272+
Self: Sized,
3273+
F: FnMut(B, Self::Item) -> R,
3274+
R: Try<Ok = B>,
3275+
{
3276+
(**self).try_fold(init, f)
3277+
}
32393278
}

0 commit comments

Comments
 (0)