Skip to content

Commit df592af

Browse files
authored
Rollup merge of rust-lang#100220 - scottmcm:fix-by-ref-sized, r=joshtriplett
Properly forward `ByRefSized::fold` to the inner iterator cc ``@timvermeulen,`` who noticed this mistake in rust-lang#100214 (comment)
2 parents 4e34bc3 + 7680c8b commit df592af

File tree

3 files changed

+38
-12
lines changed

3 files changed

+38
-12
lines changed
+17-12
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
use crate::ops::Try;
1+
use crate::ops::{NeverShortCircuit, Try};
22

33
/// Like `Iterator::by_ref`, but requiring `Sized` so it can forward generics.
44
///
@@ -8,36 +8,40 @@ use crate::ops::Try;
88
#[derive(Debug)]
99
pub struct ByRefSized<'a, I>(pub &'a mut I);
1010

11+
// The following implementations use UFCS-style, rather than trusting autoderef,
12+
// to avoid accidentally calling the `&mut Iterator` implementations.
13+
1114
#[unstable(feature = "std_internals", issue = "none")]
1215
impl<I: Iterator> Iterator for ByRefSized<'_, I> {
1316
type Item = I::Item;
1417

1518
#[inline]
1619
fn next(&mut self) -> Option<Self::Item> {
17-
self.0.next()
20+
I::next(self.0)
1821
}
1922

2023
#[inline]
2124
fn size_hint(&self) -> (usize, Option<usize>) {
22-
self.0.size_hint()
25+
I::size_hint(self.0)
2326
}
2427

2528
#[inline]
2629
fn advance_by(&mut self, n: usize) -> Result<(), usize> {
27-
self.0.advance_by(n)
30+
I::advance_by(self.0, n)
2831
}
2932

3033
#[inline]
3134
fn nth(&mut self, n: usize) -> Option<Self::Item> {
32-
self.0.nth(n)
35+
I::nth(self.0, n)
3336
}
3437

3538
#[inline]
3639
fn fold<B, F>(self, init: B, f: F) -> B
3740
where
3841
F: FnMut(B, Self::Item) -> B,
3942
{
40-
self.0.fold(init, f)
43+
// `fold` needs ownership, so this can't forward directly.
44+
I::try_fold(self.0, init, NeverShortCircuit::wrap_mut_2(f)).0
4145
}
4246

4347
#[inline]
@@ -46,33 +50,34 @@ impl<I: Iterator> Iterator for ByRefSized<'_, I> {
4650
F: FnMut(B, Self::Item) -> R,
4751
R: Try<Output = B>,
4852
{
49-
self.0.try_fold(init, f)
53+
I::try_fold(self.0, init, f)
5054
}
5155
}
5256

5357
#[unstable(feature = "std_internals", issue = "none")]
5458
impl<I: DoubleEndedIterator> DoubleEndedIterator for ByRefSized<'_, I> {
5559
#[inline]
5660
fn next_back(&mut self) -> Option<Self::Item> {
57-
self.0.next_back()
61+
I::next_back(self.0)
5862
}
5963

6064
#[inline]
6165
fn advance_back_by(&mut self, n: usize) -> Result<(), usize> {
62-
self.0.advance_back_by(n)
66+
I::advance_back_by(self.0, n)
6367
}
6468

6569
#[inline]
6670
fn nth_back(&mut self, n: usize) -> Option<Self::Item> {
67-
self.0.nth_back(n)
71+
I::nth_back(self.0, n)
6872
}
6973

7074
#[inline]
7175
fn rfold<B, F>(self, init: B, f: F) -> B
7276
where
7377
F: FnMut(B, Self::Item) -> B,
7478
{
75-
self.0.rfold(init, f)
79+
// `rfold` needs ownership, so this can't forward directly.
80+
I::try_rfold(self.0, init, NeverShortCircuit::wrap_mut_2(f)).0
7681
}
7782

7883
#[inline]
@@ -81,6 +86,6 @@ impl<I: DoubleEndedIterator> DoubleEndedIterator for ByRefSized<'_, I> {
8186
F: FnMut(B, Self::Item) -> R,
8287
R: Try<Output = B>,
8388
{
84-
self.0.try_rfold(init, f)
89+
I::try_rfold(self.0, init, f)
8590
}
8691
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
use core::iter::*;
2+
3+
#[test]
4+
fn test_iterator_by_ref_sized() {
5+
let a = ['a', 'b', 'c', 'd'];
6+
7+
let mut s = String::from("Z");
8+
let mut it = a.iter().copied();
9+
ByRefSized(&mut it).take(2).for_each(|x| s.push(x));
10+
assert_eq!(s, "Zab");
11+
ByRefSized(&mut it).fold((), |(), x| s.push(x));
12+
assert_eq!(s, "Zabcd");
13+
14+
let mut s = String::from("Z");
15+
let mut it = a.iter().copied();
16+
ByRefSized(&mut it).rev().take(2).for_each(|x| s.push(x));
17+
assert_eq!(s, "Zdc");
18+
ByRefSized(&mut it).rfold((), |(), x| s.push(x));
19+
assert_eq!(s, "Zdcba");
20+
}

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

+1
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
mod array_chunks;
2+
mod by_ref_sized;
23
mod chain;
34
mod cloned;
45
mod copied;

0 commit comments

Comments
 (0)