From 7680c8b69051536a9c4ebcf943b394526af1a1be Mon Sep 17 00:00:00 2001 From: Scott McMurray Date: Sat, 6 Aug 2022 19:50:01 -0700 Subject: [PATCH] Properly forward `ByRefSized::fold` to the inner iterator --- .../core/src/iter/adapters/by_ref_sized.rs | 29 +++++++++++-------- .../core/tests/iter/adapters/by_ref_sized.rs | 20 +++++++++++++ library/core/tests/iter/adapters/mod.rs | 1 + 3 files changed, 38 insertions(+), 12 deletions(-) create mode 100644 library/core/tests/iter/adapters/by_ref_sized.rs diff --git a/library/core/src/iter/adapters/by_ref_sized.rs b/library/core/src/iter/adapters/by_ref_sized.rs index cc1e8e8a27fa6..477e7117c3ea1 100644 --- a/library/core/src/iter/adapters/by_ref_sized.rs +++ b/library/core/src/iter/adapters/by_ref_sized.rs @@ -1,4 +1,4 @@ -use crate::ops::Try; +use crate::ops::{NeverShortCircuit, Try}; /// Like `Iterator::by_ref`, but requiring `Sized` so it can forward generics. /// @@ -8,28 +8,31 @@ use crate::ops::Try; #[derive(Debug)] pub struct ByRefSized<'a, I>(pub &'a mut I); +// The following implementations use UFCS-style, rather than trusting autoderef, +// to avoid accidentally calling the `&mut Iterator` implementations. + #[unstable(feature = "std_internals", issue = "none")] impl Iterator for ByRefSized<'_, I> { type Item = I::Item; #[inline] fn next(&mut self) -> Option { - self.0.next() + I::next(self.0) } #[inline] fn size_hint(&self) -> (usize, Option) { - self.0.size_hint() + I::size_hint(self.0) } #[inline] fn advance_by(&mut self, n: usize) -> Result<(), usize> { - self.0.advance_by(n) + I::advance_by(self.0, n) } #[inline] fn nth(&mut self, n: usize) -> Option { - self.0.nth(n) + I::nth(self.0, n) } #[inline] @@ -37,7 +40,8 @@ impl Iterator for ByRefSized<'_, I> { where F: FnMut(B, Self::Item) -> B, { - self.0.fold(init, f) + // `fold` needs ownership, so this can't forward directly. + I::try_fold(self.0, init, NeverShortCircuit::wrap_mut_2(f)).0 } #[inline] @@ -46,7 +50,7 @@ impl Iterator for ByRefSized<'_, I> { F: FnMut(B, Self::Item) -> R, R: Try, { - self.0.try_fold(init, f) + I::try_fold(self.0, init, f) } } @@ -54,17 +58,17 @@ impl Iterator for ByRefSized<'_, I> { impl DoubleEndedIterator for ByRefSized<'_, I> { #[inline] fn next_back(&mut self) -> Option { - self.0.next_back() + I::next_back(self.0) } #[inline] fn advance_back_by(&mut self, n: usize) -> Result<(), usize> { - self.0.advance_back_by(n) + I::advance_back_by(self.0, n) } #[inline] fn nth_back(&mut self, n: usize) -> Option { - self.0.nth_back(n) + I::nth_back(self.0, n) } #[inline] @@ -72,7 +76,8 @@ impl DoubleEndedIterator for ByRefSized<'_, I> { where F: FnMut(B, Self::Item) -> B, { - self.0.rfold(init, f) + // `rfold` needs ownership, so this can't forward directly. + I::try_rfold(self.0, init, NeverShortCircuit::wrap_mut_2(f)).0 } #[inline] @@ -81,6 +86,6 @@ impl DoubleEndedIterator for ByRefSized<'_, I> { F: FnMut(B, Self::Item) -> R, R: Try, { - self.0.try_rfold(init, f) + I::try_rfold(self.0, init, f) } } diff --git a/library/core/tests/iter/adapters/by_ref_sized.rs b/library/core/tests/iter/adapters/by_ref_sized.rs new file mode 100644 index 0000000000000..a9c066f0e8cb1 --- /dev/null +++ b/library/core/tests/iter/adapters/by_ref_sized.rs @@ -0,0 +1,20 @@ +use core::iter::*; + +#[test] +fn test_iterator_by_ref_sized() { + let a = ['a', 'b', 'c', 'd']; + + let mut s = String::from("Z"); + let mut it = a.iter().copied(); + ByRefSized(&mut it).take(2).for_each(|x| s.push(x)); + assert_eq!(s, "Zab"); + ByRefSized(&mut it).fold((), |(), x| s.push(x)); + assert_eq!(s, "Zabcd"); + + let mut s = String::from("Z"); + let mut it = a.iter().copied(); + ByRefSized(&mut it).rev().take(2).for_each(|x| s.push(x)); + assert_eq!(s, "Zdc"); + ByRefSized(&mut it).rfold((), |(), x| s.push(x)); + assert_eq!(s, "Zdcba"); +} diff --git a/library/core/tests/iter/adapters/mod.rs b/library/core/tests/iter/adapters/mod.rs index 96539c0c394e2..ffd5f3857aea4 100644 --- a/library/core/tests/iter/adapters/mod.rs +++ b/library/core/tests/iter/adapters/mod.rs @@ -1,4 +1,5 @@ mod array_chunks; +mod by_ref_sized; mod chain; mod cloned; mod copied;