about summary refs log tree commit diff
diff options
context:
space:
mode:
authorMatthias Krüger <matthias.krueger@famsik.de>2022-08-24 18:20:08 +0200
committerGitHub <noreply@github.com>2022-08-24 18:20:08 +0200
commit6deca5f067684ddb120bd8897d0e55baafcdd792 (patch)
tree4790fbff583e30fb2770d717f7907b264703fb3f
parentbc05045a017f94ba6ba3a121a1ddc293f6617693 (diff)
parent7680c8b69051536a9c4ebcf943b394526af1a1be (diff)
downloadrust-6deca5f067684ddb120bd8897d0e55baafcdd792.tar.gz
rust-6deca5f067684ddb120bd8897d0e55baafcdd792.zip
Rollup merge of #100220 - scottmcm:fix-by-ref-sized, r=joshtriplett
Properly forward `ByRefSized::fold` to the inner iterator

cc ``@timvermeulen,`` who noticed this mistake in https://github.com/rust-lang/rust/pull/100214#issuecomment-1207317625
-rw-r--r--library/core/src/iter/adapters/by_ref_sized.rs29
-rw-r--r--library/core/tests/iter/adapters/by_ref_sized.rs20
-rw-r--r--library/core/tests/iter/adapters/mod.rs1
3 files changed, 38 insertions, 12 deletions
diff --git a/library/core/src/iter/adapters/by_ref_sized.rs b/library/core/src/iter/adapters/by_ref_sized.rs
index cc1e8e8a27f..477e7117c3e 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<I: Iterator> Iterator for ByRefSized<'_, I> {
     type Item = I::Item;
 
     #[inline]
     fn next(&mut self) -> Option<Self::Item> {
-        self.0.next()
+        I::next(self.0)
     }
 
     #[inline]
     fn size_hint(&self) -> (usize, Option<usize>) {
-        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::Item> {
-        self.0.nth(n)
+        I::nth(self.0, n)
     }
 
     #[inline]
@@ -37,7 +40,8 @@ impl<I: Iterator> 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<I: Iterator> Iterator for ByRefSized<'_, I> {
         F: FnMut(B, Self::Item) -> R,
         R: Try<Output = B>,
     {
-        self.0.try_fold(init, f)
+        I::try_fold(self.0, init, f)
     }
 }
 
@@ -54,17 +58,17 @@ impl<I: Iterator> Iterator for ByRefSized<'_, I> {
 impl<I: DoubleEndedIterator> DoubleEndedIterator for ByRefSized<'_, I> {
     #[inline]
     fn next_back(&mut self) -> Option<Self::Item> {
-        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::Item> {
-        self.0.nth_back(n)
+        I::nth_back(self.0, n)
     }
 
     #[inline]
@@ -72,7 +76,8 @@ impl<I: DoubleEndedIterator> 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<I: DoubleEndedIterator> DoubleEndedIterator for ByRefSized<'_, I> {
         F: FnMut(B, Self::Item) -> R,
         R: Try<Output = B>,
     {
-        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 00000000000..a9c066f0e8c
--- /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 96539c0c394..ffd5f3857ae 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;