From cb7f7ee07f6d67e36cc08b337c034f5e81343dc1 Mon Sep 17 00:00:00 2001 From: sarah <> Date: Fri, 5 Aug 2022 18:14:48 +0200 Subject: [PATCH 1/2] feat: impl internal iteration for &mut I --- library/core/src/iter/traits/double_ended.rs | 55 +++++++++++++++++++ library/core/src/iter/traits/iterator.rs | 58 +++++++++++++++++++- library/core/src/ops/function.rs | 5 ++ 3 files changed, 117 insertions(+), 1 deletion(-) diff --git a/library/core/src/iter/traits/double_ended.rs b/library/core/src/iter/traits/double_ended.rs index bdf94c792c27c..8064b96ffbac1 100644 --- a/library/core/src/iter/traits/double_ended.rs +++ b/library/core/src/iter/traits/double_ended.rs @@ -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 { (**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 { (**self).nth_back(n) } + #[inline] + fn try_rfold(&mut self, init: B, f: F) -> R + where + F: FnMut(B, Self::Item) -> R, + R: Try, + { + ByRefRFold::try_rfold(self, init, f) + } + #[inline] + fn rfold(mut self, init: B, f: F) -> B + where + F: FnMut(B, Self::Item) -> B, + { + #[inline] + fn ok(mut f: impl FnMut(B, T) -> B) -> impl FnMut(B, T) -> Result { + move |acc, x| Ok(f(acc, x)) + } + ByRefRFold::try_rfold(&mut self, init, ok(f)).unwrap() + } +} + +trait ByRefRFold: DoubleEndedIterator { + fn try_rfold(&mut self, init: B, f: F) -> R + where + F: FnMut(B, Self::Item) -> R, + R: Try; +} + +impl<'a, I: DoubleEndedIterator + ?Sized> ByRefRFold for &'a mut I { + #[inline] + default fn try_rfold(&mut self, init: B, mut f: F) -> R + where + F: FnMut(B, Self::Item) -> R, + R: Try, + { + 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(&mut self, init: B, f: F) -> R + where + F: FnMut(B, Self::Item) -> R, + R: Try, + { + (**self).try_rfold(init, f) + } } diff --git a/library/core/src/iter/traits/iterator.rs b/library/core/src/iter/traits/iterator.rs index 275412b57b55f..0c5e43dda9989 100644 --- a/library/core/src/iter/traits/iterator.rs +++ b/library/core/src/iter/traits/iterator.rs @@ -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, 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... @@ -3824,13 +3825,68 @@ impl Iterator for &mut I { fn next(&mut self) -> Option { (**self).next() } + #[inline] fn size_hint(&self) -> (usize, Option) { (**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).nth(n) } + #[inline] + fn try_fold(&mut self, init: B, f: F) -> R + where + F: FnMut(B, Self::Item) -> R, + R: Try, + { + ByRefFold::try_fold(self, init, f) + } + #[inline] + fn fold(mut self, init: B, f: F) -> B + where + F: FnMut(B, Self::Item) -> B, + { + #[inline] + fn ok(mut f: impl FnMut(B, T) -> B) -> impl FnMut(B, T) -> Result { + move |acc, x| Ok(f(acc, x)) + } + ByRefFold::try_fold(&mut self, init, ok(f)).unwrap() + } +} + +trait ByRefFold: Iterator { + fn try_fold(&mut self, init: B, f: F) -> R + where + F: FnMut(B, Self::Item) -> R, + R: Try; +} + +impl<'a, I: Iterator + ?Sized> ByRefFold for &'a mut I { + #[inline] + default fn try_fold(&mut self, init: B, mut f: F) -> R + where + F: FnMut(B, Self::Item) -> R, + R: Try, + { + 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(&mut self, init: B, f: F) -> R + where + F: FnMut(B, Self::Item) -> R, + R: Try, + { + (**self).try_fold(init, f) + } } diff --git a/library/core/src/ops/function.rs b/library/core/src/ops/function.rs index c5a194b7d0a41..c21eab0a80945 100644 --- a/library/core/src/ops/function.rs +++ b/library/core/src/ops/function.rs @@ -254,6 +254,7 @@ mod impls { where F: Fn, { + #[inline] extern "rust-call" fn call(&self, args: A) -> F::Output { (**self).call(args) } @@ -264,6 +265,7 @@ mod impls { where F: Fn, { + #[inline] extern "rust-call" fn call_mut(&mut self, args: A) -> F::Output { (**self).call(args) } @@ -276,6 +278,7 @@ mod impls { { type Output = F::Output; + #[inline] extern "rust-call" fn call_once(self, args: A) -> F::Output { (*self).call(args) } @@ -286,6 +289,7 @@ mod impls { where F: FnMut, { + #[inline] extern "rust-call" fn call_mut(&mut self, args: A) -> F::Output { (*self).call_mut(args) } @@ -297,6 +301,7 @@ mod impls { F: FnMut, { type Output = F::Output; + #[inline] extern "rust-call" fn call_once(self, args: A) -> F::Output { (*self).call_mut(args) } From f6a3462bda206ae937ff83760bf0d359fb2ddf0e Mon Sep 17 00:00:00 2001 From: sarah <> Date: Sat, 6 Aug 2022 18:07:15 +0200 Subject: [PATCH 2/2] undo changes to function.rs --- library/core/src/ops/function.rs | 5 ----- 1 file changed, 5 deletions(-) diff --git a/library/core/src/ops/function.rs b/library/core/src/ops/function.rs index c21eab0a80945..c5a194b7d0a41 100644 --- a/library/core/src/ops/function.rs +++ b/library/core/src/ops/function.rs @@ -254,7 +254,6 @@ mod impls { where F: Fn, { - #[inline] extern "rust-call" fn call(&self, args: A) -> F::Output { (**self).call(args) } @@ -265,7 +264,6 @@ mod impls { where F: Fn, { - #[inline] extern "rust-call" fn call_mut(&mut self, args: A) -> F::Output { (**self).call(args) } @@ -278,7 +276,6 @@ mod impls { { type Output = F::Output; - #[inline] extern "rust-call" fn call_once(self, args: A) -> F::Output { (*self).call(args) } @@ -289,7 +286,6 @@ mod impls { where F: FnMut, { - #[inline] extern "rust-call" fn call_mut(&mut self, args: A) -> F::Output { (*self).call_mut(args) } @@ -301,7 +297,6 @@ mod impls { F: FnMut, { type Output = F::Output; - #[inline] extern "rust-call" fn call_once(self, args: A) -> F::Output { (*self).call_mut(args) }