]> git.lizzy.rs Git - rust.git/blobdiff - src/libcore/iter/traits/iterator.rs
Reduce the genericity of closures in the iterator traits
[rust.git] / src / libcore / iter / traits / iterator.rs
index 7e941267ce8246e52ab1828cd2ed79f6b0ab4d23..9028103cb97170ecf7ae420f635091567ea04a93 100644 (file)
@@ -234,11 +234,16 @@ fn size_hint(&self) -> (usize, Option<usize>) { (0, None) }
     /// assert_eq!(a.iter().count(), 5);
     /// ```
     #[inline]
-    #[rustc_inherit_overflow_checks]
     #[stable(feature = "rust1", since = "1.0.0")]
     fn count(self) -> usize where Self: Sized {
         // Might overflow.
-        self.fold(0, |cnt, _| cnt + 1)
+        #[inline]
+        #[rustc_inherit_overflow_checks]
+        fn add1<T>(count: usize, _: T) -> usize {
+            count + 1
+        }
+
+        self.fold(0, add1)
     }
 
     /// Consumes the iterator, returning the last element.
@@ -596,10 +601,15 @@ fn map<B, F>(self, f: F) -> Map<Self, F> where
     /// ```
     #[inline]
     #[stable(feature = "iterator_for_each", since = "1.21.0")]
-    fn for_each<F>(self, mut f: F) where
+    fn for_each<F>(self, f: F) where
         Self: Sized, F: FnMut(Self::Item),
     {
-        self.fold((), move |(), item| f(item));
+        #[inline]
+        fn call<T>(mut f: impl FnMut(T)) -> impl FnMut((), T) {
+            move |(), item| f(item)
+        }
+
+        self.fold((), call(f));
     }
 
     /// Creates an iterator which uses a closure to determine if an element
@@ -1490,21 +1500,30 @@ fn collect<B: FromIterator<Self::Item>>(self) -> B where Self: Sized {
     /// assert_eq!(odd, vec![1, 3]);
     /// ```
     #[stable(feature = "rust1", since = "1.0.0")]
-    fn partition<B, F>(self, mut f: F) -> (B, B) where
+    fn partition<B, F>(self, f: F) -> (B, B) where
         Self: Sized,
         B: Default + Extend<Self::Item>,
         F: FnMut(&Self::Item) -> bool
     {
+        #[inline]
+        fn extend<'a, T, B: Extend<T>>(
+            mut f: impl FnMut(&T) -> bool + 'a,
+            left: &'a mut B,
+            right: &'a mut B,
+        ) -> impl FnMut(T) + 'a {
+            move |x| {
+                if f(&x) {
+                    left.extend(Some(x));
+                } else {
+                    right.extend(Some(x));
+                }
+            }
+        }
+
         let mut left: B = Default::default();
         let mut right: B = Default::default();
 
-        self.for_each(|x| {
-            if f(&x) {
-                left.extend(Some(x))
-            } else {
-                right.extend(Some(x))
-            }
-        });
+        self.for_each(extend(f, &mut left, &mut right));
 
         (left, right)
     }
@@ -1702,10 +1721,15 @@ fn try_fold<B, F, R>(&mut self, init: B, mut f: F) -> R where
     /// ```
     #[inline]
     #[stable(feature = "iterator_try_fold", since = "1.27.0")]
-    fn try_for_each<F, R>(&mut self, mut f: F) -> R where
+    fn try_for_each<F, R>(&mut self, f: F) -> R where
         Self: Sized, F: FnMut(Self::Item) -> R, R: Try<Ok=()>
     {
-        self.try_fold((), move |(), x| f(x))
+        #[inline]
+        fn call<T, R>(mut f: impl FnMut(T) -> R) -> impl FnMut((), T) -> R {
+            move |(), x| f(x)
+        }
+
+        self.try_fold((), call(f))
     }
 
     /// An iterator method that applies a function, producing a single, final value.
@@ -1777,10 +1801,15 @@ fn try_for_each<F, R>(&mut self, mut f: F) -> R where
     /// ```
     #[inline]
     #[stable(feature = "rust1", since = "1.0.0")]
-    fn fold<B, F>(mut self, init: B, mut f: F) -> B where
+    fn fold<B, F>(mut self, init: B, f: F) -> B where
         Self: Sized, F: FnMut(B, Self::Item) -> B,
     {
-        self.try_fold(init, move |acc, x| Ok::<B, !>(f(acc, x))).unwrap()
+        #[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))
+        }
+
+        self.try_fold(init, ok(f)).unwrap()
     }
 
     /// Tests if every element of the iterator matches a predicate.
@@ -1822,13 +1851,18 @@ fn fold<B, F>(mut self, init: B, mut f: F) -> B where
     /// ```
     #[inline]
     #[stable(feature = "rust1", since = "1.0.0")]
-    fn all<F>(&mut self, mut f: F) -> bool where
+    fn all<F>(&mut self, f: F) -> bool where
         Self: Sized, F: FnMut(Self::Item) -> bool
     {
-        self.try_for_each(move |x| {
-            if f(x) { LoopState::Continue(()) }
-            else { LoopState::Break(()) }
-        }) == LoopState::Continue(())
+        #[inline]
+        fn check<T>(mut f: impl FnMut(T) -> bool) -> impl FnMut(T) -> LoopState<(), ()> {
+            move |x| {
+                if f(x) { LoopState::Continue(()) }
+                else { LoopState::Break(()) }
+            }
+        }
+
+        self.try_for_each(check(f)) == LoopState::Continue(())
     }
 
     /// Tests if any element of the iterator matches a predicate.
@@ -1870,14 +1904,19 @@ fn all<F>(&mut self, mut f: F) -> bool where
     /// ```
     #[inline]
     #[stable(feature = "rust1", since = "1.0.0")]
-    fn any<F>(&mut self, mut f: F) -> bool where
+    fn any<F>(&mut self, f: F) -> bool where
         Self: Sized,
         F: FnMut(Self::Item) -> bool
     {
-        self.try_for_each(move |x| {
-            if f(x) { LoopState::Break(()) }
-            else { LoopState::Continue(()) }
-        }) == LoopState::Break(())
+        #[inline]
+        fn check<T>(mut f: impl FnMut(T) -> bool) -> impl FnMut(T) -> LoopState<(), ()> {
+            move |x| {
+                if f(x) { LoopState::Break(()) }
+                else { LoopState::Continue(()) }
+            }
+        }
+
+        self.try_for_each(check(f)) == LoopState::Break(())
     }
 
     /// Searches for an element of an iterator that satisfies a predicate.
@@ -1924,14 +1963,19 @@ fn any<F>(&mut self, mut f: F) -> bool where
     /// ```
     #[inline]
     #[stable(feature = "rust1", since = "1.0.0")]
-    fn find<P>(&mut self, mut predicate: P) -> Option<Self::Item> where
+    fn find<P>(&mut self, predicate: P) -> Option<Self::Item> where
         Self: Sized,
         P: FnMut(&Self::Item) -> bool,
     {
-        self.try_for_each(move |x| {
-            if predicate(&x) { LoopState::Break(x) }
-            else { LoopState::Continue(()) }
-        }).break_value()
+        #[inline]
+        fn check<T>(mut predicate: impl FnMut(&T) -> bool) -> impl FnMut(T) -> LoopState<(), T> {
+            move |x| {
+                if predicate(&x) { LoopState::Break(x) }
+                else { LoopState::Continue(()) }
+            }
+        }
+
+        self.try_for_each(check(predicate)).break_value()
     }
 
     /// Applies function to the elements of iterator and returns
@@ -1951,16 +1995,19 @@ fn find<P>(&mut self, mut predicate: P) -> Option<Self::Item> where
     /// ```
     #[inline]
     #[stable(feature = "iterator_find_map", since = "1.30.0")]
-    fn find_map<B, F>(&mut self, mut f: F) -> Option<B> where
+    fn find_map<B, F>(&mut self, f: F) -> Option<B> where
         Self: Sized,
         F: FnMut(Self::Item) -> Option<B>,
     {
-        self.try_for_each(move |x| {
-            match f(x) {
+        #[inline]
+        fn check<T, B>(mut f: impl FnMut(T) -> Option<B>) -> impl FnMut(T) -> LoopState<(), B> {
+            move |x| match f(x) {
                 Some(x) => LoopState::Break(x),
                 None => LoopState::Continue(()),
             }
-        }).break_value()
+        }
+
+        self.try_for_each(check(f)).break_value()
     }
 
     /// Searches for an element in an iterator, returning its index.
@@ -2018,17 +2065,24 @@ fn find_map<B, F>(&mut self, mut f: F) -> Option<B> where
     ///
     /// ```
     #[inline]
-    #[rustc_inherit_overflow_checks]
     #[stable(feature = "rust1", since = "1.0.0")]
-    fn position<P>(&mut self, mut predicate: P) -> Option<usize> where
+    fn position<P>(&mut self, predicate: P) -> Option<usize> where
         Self: Sized,
         P: FnMut(Self::Item) -> bool,
     {
         // The addition might panic on overflow
-        self.try_fold(0, move |i, x| {
-            if predicate(x) { LoopState::Break(i) }
-            else { LoopState::Continue(i + 1) }
-        }).break_value()
+        #[inline]
+        #[rustc_inherit_overflow_checks]
+        fn check<T>(
+            mut predicate: impl FnMut(T) -> bool,
+        ) -> impl FnMut(usize, T) -> LoopState<usize, usize> {
+            move |i, x| {
+                if predicate(x) { LoopState::Break(i) }
+                else { LoopState::Continue(i + 1) }
+            }
+        }
+
+        self.try_fold(0, check(predicate)).break_value()
     }
 
     /// Searches for an element in an iterator from the right, returning its
@@ -2071,18 +2125,25 @@ fn position<P>(&mut self, mut predicate: P) -> Option<usize> where
     /// ```
     #[inline]
     #[stable(feature = "rust1", since = "1.0.0")]
-    fn rposition<P>(&mut self, mut predicate: P) -> Option<usize> where
+    fn rposition<P>(&mut self, predicate: P) -> Option<usize> where
         P: FnMut(Self::Item) -> bool,
         Self: Sized + ExactSizeIterator + DoubleEndedIterator
     {
         // No need for an overflow check here, because `ExactSizeIterator`
         // implies that the number of elements fits into a `usize`.
+        #[inline]
+        fn check<T>(
+            mut predicate: impl FnMut(T) -> bool,
+        ) -> impl FnMut(usize, T) -> LoopState<usize, usize> {
+            move |i, x| {
+                let i = i - 1;
+                if predicate(x) { LoopState::Break(i) }
+                else { LoopState::Continue(i) }
+            }
+        }
+
         let n = self.len();
-        self.try_rfold(n, move |i, x| {
-            let i = i - 1;
-            if predicate(x) { LoopState::Break(i) }
-            else { LoopState::Continue(i) }
-        }).break_value()
+        self.try_rfold(n, check(predicate)).break_value()
     }
 
     /// Returns the maximum element of an iterator.
@@ -2151,11 +2212,22 @@ fn min(self) -> Option<Self::Item> where Self: Sized, Self::Item: Ord
     /// ```
     #[inline]
     #[stable(feature = "iter_cmp_by_key", since = "1.6.0")]
-    fn max_by_key<B: Ord, F>(self, mut f: F) -> Option<Self::Item>
+    fn max_by_key<B: Ord, F>(self, f: F) -> Option<Self::Item>
         where Self: Sized, F: FnMut(&Self::Item) -> B,
     {
+        #[inline]
+        fn key<T, B>(mut f: impl FnMut(&T) -> B) -> impl FnMut(T) -> (B, T) {
+            move |x| (f(&x), x)
+        }
+
         // switch to y even if it is only equal, to preserve stability.
-        select_fold1(self.map(|x| (f(&x), x)), |(x_p, _), (y_p, _)| x_p <= y_p).map(|(_, x)| x)
+        #[inline]
+        fn select<T, B: Ord>((x_p, _): &(B, T), (y_p, _): &(B, T)) -> bool {
+            x_p <= y_p
+        }
+
+        let (_, x) = select_fold1(self.map(key(f)), select)?;
+        Some(x)
     }
 
     /// Returns the element that gives the maximum value with respect to the
@@ -2174,11 +2246,16 @@ fn max_by_key<B: Ord, F>(self, mut f: F) -> Option<Self::Item>
     /// ```
     #[inline]
     #[stable(feature = "iter_max_by", since = "1.15.0")]
-    fn max_by<F>(self, mut compare: F) -> Option<Self::Item>
+    fn max_by<F>(self, compare: F) -> Option<Self::Item>
         where Self: Sized, F: FnMut(&Self::Item, &Self::Item) -> Ordering,
     {
         // switch to y even if it is only equal, to preserve stability.
-        select_fold1(self, |x, y| compare(x, y) != Ordering::Greater)
+        #[inline]
+        fn select<T>(mut compare: impl FnMut(&T, &T) -> Ordering) -> impl FnMut(&T, &T) -> bool {
+            move |x, y| compare(x, y) != Ordering::Greater
+        }
+
+        select_fold1(self, select(compare))
     }
 
     /// Returns the element that gives the minimum value from the
@@ -2195,12 +2272,24 @@ fn max_by<F>(self, mut compare: F) -> Option<Self::Item>
     /// let a = [-3_i32, 0, 1, 5, -10];
     /// assert_eq!(*a.iter().min_by_key(|x| x.abs()).unwrap(), 0);
     /// ```
+    #[inline]
     #[stable(feature = "iter_cmp_by_key", since = "1.6.0")]
-    fn min_by_key<B: Ord, F>(self, mut f: F) -> Option<Self::Item>
+    fn min_by_key<B: Ord, F>(self, f: F) -> Option<Self::Item>
         where Self: Sized, F: FnMut(&Self::Item) -> B,
     {
+        #[inline]
+        fn key<T, B>(mut f: impl FnMut(&T) -> B) -> impl FnMut(T) -> (B, T) {
+            move |x| (f(&x), x)
+        }
+
         // only switch to y if it is strictly smaller, to preserve stability.
-        select_fold1(self.map(|x| (f(&x), x)), |(x_p, _), (y_p, _)| x_p > y_p).map(|(_, x)| x)
+        #[inline]
+        fn select<T, B: Ord>((x_p, _): &(B, T), (y_p, _): &(B, T)) -> bool {
+            x_p > y_p
+        }
+
+        let (_, x) = select_fold1(self.map(key(f)), select)?;
+        Some(x)
     }
 
     /// Returns the element that gives the minimum value with respect to the
@@ -2219,11 +2308,16 @@ fn min_by_key<B: Ord, F>(self, mut f: F) -> Option<Self::Item>
     /// ```
     #[inline]
     #[stable(feature = "iter_min_by", since = "1.15.0")]
-    fn min_by<F>(self, mut compare: F) -> Option<Self::Item>
+    fn min_by<F>(self, compare: F) -> Option<Self::Item>
         where Self: Sized, F: FnMut(&Self::Item, &Self::Item) -> Ordering,
     {
         // only switch to y if it is strictly smaller, to preserve stability.
-        select_fold1(self, |x, y| compare(x, y) == Ordering::Greater)
+        #[inline]
+        fn select<T>(mut compare: impl FnMut(&T, &T) -> Ordering) -> impl FnMut(&T, &T) -> bool {
+            move |x, y| compare(x, y) == Ordering::Greater
+        }
+
+        select_fold1(self, select(compare))
     }
 
 
@@ -2284,13 +2378,20 @@ fn unzip<A, B, FromA, FromB>(self) -> (FromA, FromB) where
         FromB: Default + Extend<B>,
         Self: Sized + Iterator<Item=(A, B)>,
     {
+        fn extend<'a, A, B>(
+            ts: &'a mut impl Extend<A>,
+            us: &'a mut impl Extend<B>,
+        ) -> impl FnMut((A, B)) + 'a {
+            move |(t, u)| {
+                ts.extend(Some(t));
+                us.extend(Some(u));
+            }
+        }
+
         let mut ts: FromA = Default::default();
         let mut us: FromB = Default::default();
 
-        self.for_each(|(t, u)| {
-            ts.extend(Some(t));
-            us.extend(Some(u));
-        });
+        self.for_each(extend(&mut ts, &mut us));
 
         (ts, us)
     }
@@ -2617,7 +2718,7 @@ fn is_sorted(self) -> bool
         Self: Sized,
         Self::Item: PartialOrd,
     {
-        self.is_sorted_by(|a, b| a.partial_cmp(b))
+        self.is_sorted_by(PartialOrd::partial_cmp)
     }
 
     /// Checks if the elements of this iterator are sorted using the given comparator function.
@@ -2639,11 +2740,9 @@ fn is_sorted_by<F>(mut self, mut compare: F) -> bool
         };
 
         while let Some(curr) = self.next() {
-            if compare(&last, &curr)
-                .map(|o| o == Ordering::Greater)
-                .unwrap_or(true)
-            {
-                return false;
+            match compare(&last, &curr) {
+                Some(Ordering::Greater) | None => return false,
+                _ => {}
             }
             last = curr;
         }
@@ -2687,17 +2786,21 @@ fn is_sorted_by_key<F, K>(self, f: F) -> bool
 /// commonalities of {max,min}{,_by}. In particular, this avoids
 /// having to implement optimizations several times.
 #[inline]
-fn select_fold1<I, F>(mut it: I, mut f: F) -> Option<I::Item>
+fn select_fold1<I, F>(mut it: I, f: F) -> Option<I::Item>
     where
         I: Iterator,
         F: FnMut(&I::Item, &I::Item) -> bool,
 {
+    #[inline]
+    fn select<T>(mut f: impl FnMut(&T, &T) -> bool) -> impl FnMut(T, T) -> T {
+        move |sel, x| if f(&sel, &x) { x } else { sel }
+    }
+
     // start with the first element as our selection. This avoids
     // having to use `Option`s inside the loop, translating to a
     // sizeable performance gain (6x in one case).
-    it.next().map(|first| {
-        it.fold(first, |sel, x| if f(&sel, &x) { x } else { sel })
-    })
+    let first = it.next()?;
+    Some(it.fold(first, select(f)))
 }
 
 #[stable(feature = "rust1", since = "1.0.0")]