Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

internal iteration for &mut I #100173

Closed
wants to merge 2 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
55 changes: 55 additions & 0 deletions library/core/src/iter/traits/double_ended.rs
Original file line number Diff line number Diff line change
Expand Up @@ -362,13 +362,68 @@ pub trait DoubleEndedIterator: Iterator {

#[stable(feature = "rust1", since = "1.0.0")]
impl<'a, I: DoubleEndedIterator + ?Sized> DoubleEndedIterator for &'a mut I {
#[inline]
fn next_back(&mut self) -> Option<I::Item> {
(**self).next_back()
}
#[inline]
fn advance_back_by(&mut self, n: usize) -> Result<(), usize> {
(**self).advance_back_by(n)
}
#[inline]
fn nth_back(&mut self, n: usize) -> Option<I::Item> {
(**self).nth_back(n)
}
#[inline]
fn try_rfold<B, F, R>(&mut self, init: B, f: F) -> R
where
F: FnMut(B, Self::Item) -> R,
R: Try<Output = B>,
{
ByRefRFold::try_rfold(self, init, f)
}
#[inline]
fn rfold<B, F>(mut self, init: B, f: F) -> B
where
F: FnMut(B, Self::Item) -> B,
{
#[inline]
fn ok<B, T>(mut f: impl FnMut(B, T) -> B) -> impl FnMut(B, T) -> Result<B, !> {
move |acc, x| Ok(f(acc, x))
}
ByRefRFold::try_rfold(&mut self, init, ok(f)).unwrap()
}
}

trait ByRefRFold: DoubleEndedIterator {
fn try_rfold<B, F, R>(&mut self, init: B, f: F) -> R
where
F: FnMut(B, Self::Item) -> R,
R: Try<Output = B>;
}

impl<'a, I: DoubleEndedIterator + ?Sized> ByRefRFold for &'a mut I {
#[inline]
default fn try_rfold<B, F, R>(&mut self, init: B, mut f: F) -> R
where
F: FnMut(B, Self::Item) -> R,
R: Try<Output = B>,
{
let mut accum = init;
while let Some(x) = self.next() {
accum = f(accum, x)?;
}
try { accum }
}
}

impl<'a, I: DoubleEndedIterator + Sized> ByRefRFold for &'a mut I {
#[inline]
default fn try_rfold<B, F, R>(&mut self, init: B, f: F) -> R
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The more specific impl shouldn't have default

where
F: FnMut(B, Self::Item) -> R,
R: Try<Output = B>,
{
(**self).try_rfold(init, f)
}
}
58 changes: 57 additions & 1 deletion library/core/src/iter/traits/iterator.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2076,11 +2076,12 @@ pub trait Iterator {
/// assert!(a[i..].iter().all(|&n| n % 2 == 1)); // odds
/// ```
#[unstable(feature = "iter_partition_in_place", reason = "new API", issue = "62543")]
fn partition_in_place<'a, T: 'a, P>(mut self, ref mut predicate: P) -> usize
fn partition_in_place<'a, T: 'a, P>(mut self, mut predicate: P) -> usize
where
Self: Sized + DoubleEndedIterator<Item = &'a mut T>,
P: FnMut(&T) -> bool,
{
let predicate = &mut predicate;
// FIXME: should we worry about the count overflowing? The only way to have more than
// `usize::MAX` mutable references is with ZSTs, which aren't useful to partition...

Expand Down Expand Up @@ -3824,13 +3825,68 @@ impl<I: Iterator + ?Sized> Iterator for &mut I {
fn next(&mut self) -> Option<I::Item> {
(**self).next()
}
#[inline]
fn size_hint(&self) -> (usize, Option<usize>) {
(**self).size_hint()
}
#[inline]
fn advance_by(&mut self, n: usize) -> Result<(), usize> {
(**self).advance_by(n)
}
#[inline]
fn nth(&mut self, n: usize) -> Option<Self::Item> {
(**self).nth(n)
}
#[inline]
fn try_fold<B, F, R>(&mut self, init: B, f: F) -> R
where
F: FnMut(B, Self::Item) -> R,
R: Try<Output = B>,
{
ByRefFold::try_fold(self, init, f)
}
#[inline]
fn fold<B, F>(mut self, init: B, f: F) -> B
where
F: FnMut(B, Self::Item) -> B,
{
#[inline]
fn ok<B, T>(mut f: impl FnMut(B, T) -> B) -> impl FnMut(B, T) -> Result<B, !> {
move |acc, x| Ok(f(acc, x))
}
ByRefFold::try_fold(&mut self, init, ok(f)).unwrap()
}
}

trait ByRefFold: Iterator {
fn try_fold<B, F, R>(&mut self, init: B, f: F) -> R
where
F: FnMut(B, Self::Item) -> R,
R: Try<Output = B>;
}

impl<'a, I: Iterator + ?Sized> ByRefFold for &'a mut I {
#[inline]
default fn try_fold<B, F, R>(&mut self, init: B, mut f: F) -> R
where
F: FnMut(B, Self::Item) -> R,
R: Try<Output = B>,
{
let mut accum = init;
while let Some(x) = self.next() {
accum = f(accum, x)?;
}
try { accum }
}
}

impl<'a, I: Iterator + Sized> ByRefFold for &'a mut I {
#[inline]
default fn try_fold<B, F, R>(&mut self, init: B, f: F) -> R
where
F: FnMut(B, Self::Item) -> R,
R: Try<Output = B>,
{
(**self).try_fold(init, f)
}
}