about summary refs log tree commit diff
diff options
context:
space:
mode:
authorThe8472 <git@infinite-source.de>2019-11-23 18:59:18 +0100
committerThe8472 <git@infinite-source.de>2020-09-03 20:59:20 +0200
commit21a17d105c9cd81dfa8bd3a178e4a6b095f69e5d (patch)
tree75540290319581550abbb71fc47c778fd1b5e0eb
parent085eb20a61164067f5c71ec64dc23100006f91c9 (diff)
downloadrust-21a17d105c9cd81dfa8bd3a178e4a6b095f69e5d.tar.gz
rust-21a17d105c9cd81dfa8bd3a178e4a6b095f69e5d.zip
support in-place iteration for most adapters
`Take` is not included since users probably call it with small constants
and it doesn't make sense to hold onto huge allocations in that case
-rw-r--r--library/core/src/iter/adapters/fuse.rs23
-rw-r--r--library/core/src/iter/adapters/mod.rs113
2 files changed, 136 insertions, 0 deletions
diff --git a/library/core/src/iter/adapters/fuse.rs b/library/core/src/iter/adapters/fuse.rs
index 94ba6f56476..e2613be4a46 100644
--- a/library/core/src/iter/adapters/fuse.rs
+++ b/library/core/src/iter/adapters/fuse.rs
@@ -3,6 +3,8 @@ use crate::iter::adapters::zip::try_get_unchecked;
 use crate::iter::TrustedRandomAccess;
 use crate::iter::{DoubleEndedIterator, ExactSizeIterator, FusedIterator, Iterator};
 use crate::ops::Try;
+use crate::iter::adapters::SourceIter;
+use super::InPlaceIterable;
 
 /// An iterator that yields `None` forever after the underlying iterator
 /// yields `None` once.
@@ -517,3 +519,24 @@ where
         unchecked!(self).is_empty()
     }
 }
+
+
+#[unstable(issue = "0", feature = "inplace_iteration")]
+unsafe impl<S: Iterator, I: FusedIterator> SourceIter for Fuse<I>
+    where
+        I: SourceIter<Source = S>,
+{
+    type Source = S;
+
+    #[inline]
+    fn as_inner(&mut self) -> &mut S {
+        match self.iter {
+            Some(ref mut iter) => SourceIter::as_inner(iter),
+            // SAFETY: the specialized iterator never sets `None`
+            None => unsafe { intrinsics::unreachable() },
+        }
+    }
+}
+
+#[unstable(issue = "0", feature = "inplace_iteration")]
+unsafe impl<I: InPlaceIterable> InPlaceIterable for Fuse<I> {}
diff --git a/library/core/src/iter/adapters/mod.rs b/library/core/src/iter/adapters/mod.rs
index aaf3f690490..a8414bf9137 100644
--- a/library/core/src/iter/adapters/mod.rs
+++ b/library/core/src/iter/adapters/mod.rs
@@ -1152,6 +1152,22 @@ where
 #[stable(feature = "fused", since = "1.26.0")]
 impl<I: FusedIterator, P> FusedIterator for Filter<I, P> where P: FnMut(&I::Item) -> bool {}
 
+#[unstable(issue = "0", feature = "inplace_iteration")]
+unsafe impl<S: Iterator, P, I: Iterator> SourceIter for Filter<I, P> where
+    P: FnMut(&I::Item) -> bool,
+    I: SourceIter<Source = S>
+{
+    type Source = S;
+
+    #[inline]
+    fn as_inner(&mut self) -> &mut S {
+        SourceIter::as_inner(&mut self.iter)
+    }
+}
+
+#[unstable(issue = "0", feature = "inplace_iteration")]
+unsafe impl<I: InPlaceIterable, P> InPlaceIterable for Filter<I, P> where P: FnMut(&I::Item) -> bool {}
+
 /// An iterator that uses `f` to both filter and map elements from `iter`.
 ///
 /// This `struct` is created by the [`filter_map`] method on [`Iterator`]. See its
@@ -1278,6 +1294,23 @@ where
 #[stable(feature = "fused", since = "1.26.0")]
 impl<B, I: FusedIterator, F> FusedIterator for FilterMap<I, F> where F: FnMut(I::Item) -> Option<B> {}
 
+#[unstable(issue = "0", feature = "inplace_iteration")]
+unsafe impl<S: Iterator, B, I: Iterator, F> SourceIter for FilterMap<I, F> where
+    F: FnMut(I::Item) -> Option<B>,
+    I: SourceIter<Source = S>
+{
+    type Source = S;
+
+    #[inline]
+    fn as_inner(&mut self) -> &mut S {
+        SourceIter::as_inner(&mut self.iter)
+    }
+}
+
+#[unstable(issue = "0", feature = "inplace_iteration")]
+unsafe impl<B, I: InPlaceIterable, F> InPlaceIterable for FilterMap<I, F> where F: FnMut(I::Item) -> Option<B> {}
+
+
 /// An iterator that yields the current count and the element during iteration.
 ///
 /// This `struct` is created by the [`enumerate`] method on [`Iterator`]. See its
@@ -1910,6 +1943,22 @@ where
 {
 }
 
+#[unstable(issue = "0", feature = "inplace_iteration")]
+unsafe impl<S: Iterator, P, I: Iterator> SourceIter for SkipWhile<I, P> where
+    P: FnMut(&I::Item) -> bool,
+    I: SourceIter<Source = S>
+{
+    type Source = S;
+
+    #[inline]
+    fn as_inner(&mut self) -> &mut S {
+        SourceIter::as_inner(&mut self.iter)
+    }
+}
+
+#[unstable(issue = "0", feature = "inplace_iteration")]
+unsafe impl<I: InPlaceIterable, F> InPlaceIterable for SkipWhile<I, F> where F: FnMut(&I::Item) -> bool {}
+
 /// An iterator that only accepts elements while `predicate` returns `true`.
 ///
 /// This `struct` is created by the [`take_while`] method on [`Iterator`]. See its
@@ -2101,6 +2150,23 @@ where
     }
 }
 
+#[unstable(issue = "0", feature = "inplace_iteration")]
+unsafe impl<S: Iterator, P, I: Iterator> SourceIter for TakeWhile<I, P> where
+    P: FnMut(&I::Item) -> bool,
+    I: SourceIter<Source = S>
+{
+    type Source = S;
+
+    #[inline]
+    fn as_inner(&mut self) -> &mut S {
+        SourceIter::as_inner(&mut self.iter)
+    }
+}
+
+#[unstable(issue = "0", feature = "inplace_iteration")]
+unsafe impl<I: InPlaceIterable, F> InPlaceIterable for TakeWhile<I, F> where F: FnMut(&I::Item) -> bool {}
+
+
 /// An iterator that skips over `n` elements of `iter`.
 ///
 /// This `struct` is created by the [`skip`] method on [`Iterator`]. See its
@@ -2410,6 +2476,19 @@ where
     }
 }
 
+#[unstable(issue = "0", feature = "inplace_iteration")]
+unsafe impl<S: Iterator, I: Iterator> SourceIter for Take<I> where I: SourceIter<Source = S> {
+    type Source = S;
+
+    #[inline]
+    fn as_inner(&mut self) -> &mut S {
+        SourceIter::as_inner(&mut self.iter)
+    }
+}
+
+#[unstable(issue = "0", feature = "inplace_iteration")]
+unsafe impl<I: InPlaceIterable> InPlaceIterable for Take<I> {}
+
 #[stable(feature = "double_ended_take_iterator", since = "1.38.0")]
 impl<I> DoubleEndedIterator for Take<I>
 where
@@ -2574,6 +2653,24 @@ where
     }
 }
 
+#[unstable(issue = "0", feature = "inplace_iteration")]
+unsafe impl<St, F, B, S: Iterator, I: Iterator> SourceIter for Scan<I, St, F>
+    where I: SourceIter<Source = S>,
+          F: FnMut(&mut St, I::Item) -> Option<B>,
+{
+    type Source = S;
+
+    #[inline]
+    fn as_inner(&mut self) -> &mut S {
+        SourceIter::as_inner(&mut self.iter)
+    }
+}
+
+#[unstable(issue = "0", feature = "inplace_iteration")]
+unsafe impl<St, F, B, I: InPlaceIterable> InPlaceIterable for Scan<I, St, F>
+    where F: FnMut(&mut St, I::Item) -> Option<B>,
+{}
+
 /// An iterator that calls a function with a reference to each element before
 /// yielding it.
 ///
@@ -2720,6 +2817,22 @@ where
 #[stable(feature = "fused", since = "1.26.0")]
 impl<I: FusedIterator, F> FusedIterator for Inspect<I, F> where F: FnMut(&I::Item) {}
 
+#[unstable(issue = "0", feature = "inplace_iteration")]
+unsafe impl<S: Iterator, I: Iterator, F> SourceIter for Inspect<I, F> where
+    F: FnMut(&I::Item),
+    I: SourceIter<Source = S>
+{
+    type Source = S;
+
+    #[inline]
+    fn as_inner(&mut self) -> &mut S {
+        SourceIter::as_inner(&mut self.iter)
+    }
+}
+
+#[unstable(issue = "0", feature = "inplace_iteration")]
+unsafe impl<I: InPlaceIterable, F> InPlaceIterable for Inspect<I, F> where F: FnMut(&I::Item)  {}
+
 /// An iterator adapter that produces output as long as the underlying
 /// iterator produces `Result::Ok` values.
 ///