Skip to content

Commit b7da2c6

Browse files
committed
Auto merge of #56630 - sinkuu:core_iter, r=kennytm
Resolve FIXME in libcore/iter/mod.rs and makes a few improvements.
2 parents d7a9d96 + 5728a04 commit b7da2c6

File tree

4 files changed

+39
-22
lines changed

4 files changed

+39
-22
lines changed

src/libcore/benches/iter.rs

+6
Original file line numberDiff line numberDiff line change
@@ -282,6 +282,12 @@ bench_sums! {
282282
(0i64..1000000).chain(1000000..).take_while(|&x| x < 1111111)
283283
}
284284

285+
bench_sums! {
286+
bench_cycle_take_sum,
287+
bench_cycle_take_ref_sum,
288+
(0i64..10000).cycle().take(1000000)
289+
}
290+
285291
// Checks whether Skip<Zip<A,B>> is as fast as Zip<Skip<A>, Skip<B>>, from
286292
// https://users.rust-lang.org/t/performance-difference-between-iterator-zip-and-skip-order/15743
287293
#[bench]

src/libcore/iter/mod.rs

+30-22
Original file line numberDiff line numberDiff line change
@@ -649,6 +649,19 @@ impl<I> Iterator for Cycle<I> where I: Clone + Iterator {
649649
_ => (usize::MAX, None)
650650
}
651651
}
652+
653+
#[inline]
654+
fn try_fold<Acc, F, R>(&mut self, init: Acc, mut f: F) -> R where
655+
Self: Sized, F: FnMut(Acc, Self::Item) -> R, R: Try<Ok=Acc>
656+
{
657+
let mut accum = init;
658+
while let Some(x) = self.iter.next() {
659+
accum = f(accum, x)?;
660+
accum = self.iter.try_fold(accum, &mut f)?;
661+
self.iter = self.orig.clone();
662+
}
663+
Try::from_ok(accum)
664+
}
652665
}
653666

654667
#[stable(feature = "fused", since = "1.26.0")]
@@ -1855,18 +1868,11 @@ impl<I: Iterator> Iterator for Peekable<I> {
18551868

18561869
#[inline]
18571870
fn nth(&mut self, n: usize) -> Option<I::Item> {
1858-
// FIXME(#43234): merge these when borrow-checking gets better.
1859-
if n == 0 {
1860-
match self.peeked.take() {
1861-
Some(v) => v,
1862-
None => self.iter.nth(n),
1863-
}
1864-
} else {
1865-
match self.peeked.take() {
1866-
Some(None) => None,
1867-
Some(Some(_)) => self.iter.nth(n - 1),
1868-
None => self.iter.nth(n),
1869-
}
1871+
match self.peeked.take() {
1872+
Some(None) => None,
1873+
Some(v @ Some(_)) if n == 0 => v,
1874+
Some(Some(_)) => self.iter.nth(n - 1),
1875+
None => self.iter.nth(n),
18701876
}
18711877
}
18721878

@@ -1965,14 +1971,8 @@ impl<I: Iterator> Peekable<I> {
19651971
#[inline]
19661972
#[stable(feature = "rust1", since = "1.0.0")]
19671973
pub fn peek(&mut self) -> Option<&I::Item> {
1968-
if self.peeked.is_none() {
1969-
self.peeked = Some(self.iter.next());
1970-
}
1971-
match self.peeked {
1972-
Some(Some(ref value)) => Some(value),
1973-
Some(None) => None,
1974-
_ => unreachable!(),
1975-
}
1974+
let iter = &mut self.iter;
1975+
self.peeked.get_or_insert_with(|| iter.next()).as_ref()
19761976
}
19771977
}
19781978

@@ -2109,8 +2109,12 @@ impl<I: Iterator, P> Iterator for TakeWhile<I, P>
21092109

21102110
#[inline]
21112111
fn size_hint(&self) -> (usize, Option<usize>) {
2112-
let (_, upper) = self.iter.size_hint();
2113-
(0, upper) // can't know a lower bound, due to the predicate
2112+
if self.flag {
2113+
(0, Some(0))
2114+
} else {
2115+
let (_, upper) = self.iter.size_hint();
2116+
(0, upper) // can't know a lower bound, due to the predicate
2117+
}
21142118
}
21152119

21162120
#[inline]
@@ -2321,6 +2325,10 @@ impl<I> Iterator for Take<I> where I: Iterator{
23212325

23222326
#[inline]
23232327
fn size_hint(&self) -> (usize, Option<usize>) {
2328+
if self.n == 0 {
2329+
return (0, Some(0));
2330+
}
2331+
23242332
let (lower, upper) = self.iter.size_hint();
23252333

23262334
let lower = cmp::min(lower, self.n);

src/libcore/lib.rs

+1
Original file line numberDiff line numberDiff line change
@@ -92,6 +92,7 @@
9292
#![feature(link_llvm_intrinsics)]
9393
#![feature(never_type)]
9494
#![feature(nll)]
95+
#![feature(bind_by_move_pattern_guards)]
9596
#![feature(exhaustive_patterns)]
9697
#![feature(no_core)]
9798
#![feature(on_unimplemented)]

src/libcore/tests/iter.rs

+2
Original file line numberDiff line numberDiff line change
@@ -1001,6 +1001,8 @@ fn test_cycle() {
10011001
let mut it = (0..).step_by(1).take(0).cycle();
10021002
assert_eq!(it.size_hint(), (0, Some(0)));
10031003
assert_eq!(it.next(), None);
1004+
1005+
assert_eq!(empty::<i32>().cycle().fold(0, |acc, x| acc + x), 0);
10041006
}
10051007

10061008
#[test]

0 commit comments

Comments
 (0)