Skip to content

Commit 1b6e730

Browse files
author
sarah
committed
apply review suggestions:
- remove size_hint check in fold - add tests for new unsafe fold implementations
1 parent 1d82bfc commit 1b6e730

File tree

2 files changed

+154
-17
lines changed
  • library/core

2 files changed

+154
-17
lines changed

library/core/src/iter/adapters/zip.rs

+1-17
Original file line numberDiff line numberDiff line change
@@ -215,17 +215,6 @@ fn ok<B, T>(mut f: impl FnMut(B, T) -> B) -> impl FnMut(B, T) -> Result<B, !> {
215215
move |acc, x| Ok(f(acc, x))
216216
}
217217

218-
#[inline]
219-
fn check_fold<AItem, B: Iterator, T, F: FnMut(T, (AItem, B::Item)) -> T>(
220-
mut b: B,
221-
mut f: F,
222-
) -> impl FnMut(T, AItem) -> T {
223-
move |acc, x| match b.next() {
224-
Some(y) => f(acc, (x, y)),
225-
None => panic!("Iterator expected Some(item), found None."),
226-
}
227-
}
228-
229218
#[inline]
230219
fn check_rfold<AItem, B: DoubleEndedIterator, T, F: FnMut(T, (AItem, B::Item)) -> T>(
231220
mut b: B,
@@ -322,12 +311,7 @@ macro_rules! zip_impl_general_defaults {
322311
where
323312
F: FnMut(T, Self::Item) -> T,
324313
{
325-
let (lower, upper) = Iterator::size_hint(&self);
326-
if upper == Some(lower) {
327-
self.a.fold(init, check_fold(self.b, f))
328-
} else {
329-
ZipImpl::try_fold(&mut self, init, ok(f)).unwrap()
330-
}
314+
ZipImpl::try_fold(&mut self, init, ok(f)).unwrap()
331315
}
332316

333317
#[inline]

library/core/tests/iter/adapters/zip.rs

+153
Original file line numberDiff line numberDiff line change
@@ -232,6 +232,159 @@ fn test_zip_trusted_random_access_composition() {
232232
assert_eq!(z2.next().unwrap(), ((1, 1), 1));
233233
}
234234

235+
#[test]
236+
fn test_zip_trusted_random_access_fold_rfold() {
237+
let a = [0, 1, 2, 3, 4];
238+
let b = [5, 6, 7, 8, 9, 10];
239+
240+
let sum = a.iter().copied().sum::<i32>() + b.iter().copied().take(a.len()).sum::<i32>();
241+
let zip = || a.iter().copied().zip(b.iter().copied());
242+
let fwd_sum = zip().fold(0, |a, (b, c)| a + b + c);
243+
let bwd_sum = zip().rfold(0, |a, (b, c)| a + b + c);
244+
245+
assert_eq!(fwd_sum, sum);
246+
assert_eq!(bwd_sum, sum);
247+
}
248+
249+
#[test]
250+
fn test_zip_trusted_random_access_try_fold_try_rfold() {
251+
let a = [0, 1, 2, 3, 4];
252+
let b = [5, 6, 7, 8, 9, 10];
253+
254+
let sum = a.iter().copied().sum::<i32>() + b.iter().copied().take(a.len()).sum::<i32>();
255+
let zip = || a.iter().copied().zip(b.iter().copied());
256+
let mut zip_fwd = zip();
257+
let mut zip_bwd = zip();
258+
259+
let fwd_sum: Result<i32, ()> = zip_fwd.try_fold(0, |a, (b, c)| Ok(a + b + c));
260+
let bwd_sum: Result<i32, ()> = zip_bwd.try_rfold(0, |a, (b, c)| Ok(a + b + c));
261+
262+
assert_eq!(fwd_sum, Ok(sum));
263+
assert_eq!(bwd_sum, Ok(sum));
264+
assert_eq!(zip_fwd.next(), None);
265+
assert_eq!(zip_fwd.next_back(), None);
266+
assert_eq!(zip_bwd.next(), None);
267+
assert_eq!(zip_bwd.next_back(), None);
268+
}
269+
270+
#[test]
271+
fn test_zip_trusted_random_access_try_fold_try_rfold_resumable() {
272+
let a = [0, 1, 2, 3, 4];
273+
let b = [5, 6, 7, 8, 9, 10];
274+
275+
fn sum_countdown(mut count: usize) -> impl FnMut(i32, (i32, i32)) -> Result<i32, i32> {
276+
move |a: i32, (b, c): (i32, i32)| {
277+
if count == 0 {
278+
Err(a)
279+
} else {
280+
count -= 1;
281+
Ok(a + b + c)
282+
}
283+
}
284+
}
285+
286+
let zip = || a.iter().copied().zip(b.iter().copied());
287+
let mut zip_fwd = zip();
288+
let mut zip_bwd = zip();
289+
290+
let fwd_sum = zip_fwd.try_fold(0, sum_countdown(2));
291+
let bwd_sum = zip_bwd.try_rfold(0, sum_countdown(2));
292+
293+
assert_eq!(fwd_sum, Err(0 + 1 + 5 + 6));
294+
assert_eq!(bwd_sum, Err(4 + 3 + 9 + 8));
295+
{
296+
let mut zip_fwd = zip_fwd.clone();
297+
let mut zip_bwd = zip_bwd.clone();
298+
assert_eq!(zip_fwd.next(), Some((3, 8)));
299+
assert_eq!(zip_fwd.next(), Some((4, 9)));
300+
assert_eq!(zip_fwd.next(), None);
301+
302+
assert_eq!(zip_bwd.next(), Some((0, 5)));
303+
assert_eq!(zip_bwd.next(), Some((1, 6)));
304+
assert_eq!(zip_bwd.next(), None);
305+
}
306+
307+
assert_eq!(zip_fwd.next_back(), Some((4, 9)));
308+
assert_eq!(zip_fwd.next_back(), Some((3, 8)));
309+
assert_eq!(zip_fwd.next_back(), None);
310+
311+
assert_eq!(zip_bwd.next_back(), Some((1, 6)));
312+
assert_eq!(zip_bwd.next_back(), Some((0, 5)));
313+
assert_eq!(zip_bwd.next_back(), None);
314+
}
315+
316+
#[test]
317+
#[cfg(panic = "unwind")]
318+
fn test_zip_trusted_random_access_try_fold_try_rfold_panic() {
319+
use std::panic::catch_unwind;
320+
use std::panic::AssertUnwindSafe;
321+
322+
let a = [0, 1, 2];
323+
let b = [3, 4, 5, 6];
324+
325+
fn sum_countdown(mut count: usize) -> impl FnMut(i32, (i32, i32)) -> Result<i32, i32> {
326+
move |a: i32, (b, c): (i32, i32)| {
327+
if count == 0 {
328+
panic!("bomb")
329+
} else {
330+
count -= 1;
331+
Ok(a + b + c)
332+
}
333+
}
334+
}
335+
336+
let zip = || a.iter().copied().zip(b.iter().copied());
337+
let mut zip_fwd = zip();
338+
let mut zip_bwd = zip();
339+
340+
let _ = catch_unwind(AssertUnwindSafe(|| {
341+
let _ = zip_fwd.try_fold(0, sum_countdown(1));
342+
}));
343+
let _ = catch_unwind(AssertUnwindSafe(|| {
344+
let _ = zip_bwd.try_rfold(0, sum_countdown(1));
345+
}));
346+
347+
{
348+
let mut zip_fwd = zip_fwd.clone();
349+
let mut zip_bwd = zip_bwd.clone();
350+
match zip_fwd.next() {
351+
Some((a, b)) => {
352+
assert!(a > 1);
353+
assert!(b > 4);
354+
assert_eq!(b - a, 3);
355+
}
356+
None => (),
357+
};
358+
359+
match zip_bwd.next_back() {
360+
Some((a, b)) => {
361+
assert!(a < 1);
362+
assert!(b < 4);
363+
assert_eq!(b - a, 3);
364+
}
365+
None => (),
366+
};
367+
}
368+
369+
match zip_fwd.next_back() {
370+
Some((a, b)) => {
371+
assert!(a > 1);
372+
assert!(b > 4);
373+
assert_eq!(b - a, 3);
374+
}
375+
None => (),
376+
};
377+
378+
match zip_bwd.next() {
379+
Some((a, b)) => {
380+
assert!(a < 1);
381+
assert!(b < 4);
382+
assert_eq!(b - a, 3);
383+
}
384+
None => (),
385+
};
386+
}
387+
235388
#[test]
236389
#[cfg(panic = "unwind")]
237390
fn test_zip_trusted_random_access_next_back_drop() {

0 commit comments

Comments
 (0)