]> git.proxmox.com Git - rustc.git/blobdiff - src/libcore/iter/iterator.rs
New upstream version 1.31.0~beta.4+dfsg1
[rustc.git] / src / libcore / iter / iterator.rs
index b27bd3142e1ed915ac2d2c83d7077f6bbfb50b10..5b6d9e2033caa74078f804e2dbdf70d24414fb37 100644 (file)
 use cmp::Ordering;
 use ops::Try;
 
-use super::{AlwaysOk, LoopState};
+use super::LoopState;
 use super::{Chain, Cycle, Cloned, Enumerate, Filter, FilterMap, Fuse};
 use super::{Flatten, FlatMap, flatten_compat};
 use super::{Inspect, Map, Peekable, Scan, Skip, SkipWhile, StepBy, Take, TakeWhile, Rev};
 use super::{Zip, Sum, Product};
 use super::{ChainState, FromIterator, ZipImpl};
 
-fn _assert_is_object_safe(_: &Iterator<Item=()>) {}
+fn _assert_is_object_safe(_: &dyn Iterator<Item=()>) {}
 
 /// An interface for dealing with iterators.
 ///
@@ -30,11 +30,72 @@ fn _assert_is_object_safe(_: &Iterator<Item=()>) {}
 /// [impl]: index.html#implementing-iterator
 #[stable(feature = "rust1", since = "1.0.0")]
 #[rustc_on_unimplemented(
+    on(
+        _Self="[std::ops::Range<Idx>; 1]",
+        label="if you meant to iterate between two values, remove the square brackets",
+        note="`[start..end]` is an array of one `Range`; you might have meant to have a `Range` \
+              without the brackets: `start..end`"
+    ),
+    on(
+        _Self="[std::ops::RangeFrom<Idx>; 1]",
+        label="if you meant to iterate from a value onwards, remove the square brackets",
+        note="`[start..]` is an array of one `RangeFrom`; you might have meant to have a \
+              `RangeFrom` without the brackets: `start..`, keeping in mind that iterating over an \
+              unbounded iterator will run forever unless you `break` or `return` from within the \
+              loop"
+    ),
+    on(
+        _Self="[std::ops::RangeTo<Idx>; 1]",
+        label="if you meant to iterate until a value, remove the square brackets and add a \
+               starting value",
+        note="`[..end]` is an array of one `RangeTo`; you might have meant to have a bounded \
+              `Range` without the brackets: `0..end`"
+    ),
+    on(
+        _Self="[std::ops::RangeInclusive<Idx>; 1]",
+        label="if you meant to iterate between two values, remove the square brackets",
+        note="`[start..=end]` is an array of one `RangeInclusive`; you might have meant to have a \
+              `RangeInclusive` without the brackets: `start..=end`"
+    ),
+    on(
+        _Self="[std::ops::RangeToInclusive<Idx>; 1]",
+        label="if you meant to iterate until a value (including it), remove the square brackets \
+               and add a starting value",
+        note="`[..=end]` is an array of one `RangeToInclusive`; you might have meant to have a \
+              bounded `RangeInclusive` without the brackets: `0..=end`"
+    ),
+    on(
+        _Self="std::ops::RangeTo<Idx>",
+        label="if you meant to iterate until a value, add a starting value",
+        note="`..end` is a `RangeTo`, which cannot be iterated on; you might have meant to have a \
+              bounded `Range`: `0..end`"
+    ),
+    on(
+        _Self="std::ops::RangeToInclusive<Idx>",
+        label="if you meant to iterate until a value (including it), add a starting value",
+        note="`..=end` is a `RangeToInclusive`, which cannot be iterated on; you might have meant \
+              to have a bounded `RangeInclusive`: `0..=end`"
+    ),
     on(
         _Self="&str",
         label="`{Self}` is not an iterator; try calling `.chars()` or `.bytes()`"
     ),
-    label="`{Self}` is not an iterator; maybe try calling `.iter()` or a similar method"
+    on(
+        _Self="std::string::String",
+        label="`{Self}` is not an iterator; try calling `.chars()` or `.bytes()`"
+    ),
+    on(
+        _Self="[]",
+        label="borrow the array with `&` or call `.iter()` on it to iterate over it",
+        note="arrays are not an iterators, but slices like the following are: `&[1, 2, 3]`"
+    ),
+    on(
+        _Self="{integral}",
+        note="if you want to iterate between `start` until a value `end`, use the exclusive range \
+              syntax `start..end` or the inclusive range syntax `start..=end`"
+    ),
+    label="`{Self}` is not an iterator",
+    message="`{Self}` is not an iterator"
 )]
 #[doc(spotlight)]
 pub trait Iterator {
@@ -271,9 +332,30 @@ pub trait Iterator {
     /// Creates an iterator starting at the same point, but stepping by
     /// the given amount at each iteration.
     ///
-    /// Note that it will always return the first element of the iterator,
+    /// Note 1: The first element of the iterator will always be returned,
     /// regardless of the step given.
     ///
+    /// Note 2: The time at which ignored elements are pulled is not fixed.
+    /// `StepBy` behaves like the sequence `next(), nth(step-1), nth(step-1), …`,
+    /// but is also free to behave like the sequence
+    /// `advance_n_and_return_first(step), advance_n_and_return_first(step), …`
+    /// Which way is used may change for some iterators for performance reasons.
+    /// The second way will advance the iterator earlier and may consume more items.
+    ///
+    /// `advance_n_and_return_first` is the equivalent of:
+    /// ```
+    /// fn advance_n_and_return_first<I>(iter: &mut I, total_step: usize) -> Option<I::Item>
+    /// where
+    ///     I: Iterator,
+    /// {
+    ///     let next = iter.next();
+    ///     if total_step > 1 {
+    ///         iter.nth(total_step-2);
+    ///     }
+    ///     next
+    /// }
+    /// ```
+    ///
     /// # Panics
     ///
     /// The method will panic if the given step is `0`.
@@ -283,7 +365,6 @@ pub trait Iterator {
     /// Basic usage:
     ///
     /// ```
-    /// #![feature(iterator_step_by)]
     /// let a = [0, 1, 2, 3, 4, 5];
     /// let mut iter = a.into_iter().step_by(2);
     ///
@@ -293,9 +374,7 @@ pub trait Iterator {
     /// assert_eq!(iter.next(), None);
     /// ```
     #[inline]
-    #[unstable(feature = "iterator_step_by",
-               reason = "unstable replacement of Range::step_by",
-               issue = "27741")]
+    #[stable(feature = "iterator_step_by", since = "1.28.0")]
     fn step_by(self, step: usize) -> StepBy<Self> where Self: Sized {
         assert!(step != 0);
         StepBy{iter: self, step: step - 1, first_take: true}
@@ -366,8 +445,9 @@ pub trait Iterator {
     ///
     /// In other words, it zips two iterators together, into a single one.
     ///
-    /// When either iterator returns [`None`], all further calls to [`next`]
-    /// will return [`None`].
+    /// If either iterator returns [`None`], [`next`] from the zipped iterator
+    /// will return [`None`]. If the first iterator returns [`None`], `zip` will
+    /// short-circuit and `next` will not be called on the second iterator.
     ///
     /// # Examples
     ///
@@ -488,7 +568,7 @@ pub trait Iterator {
     fn map<B, F>(self, f: F) -> Map<Self, F> where
         Self: Sized, F: FnMut(Self::Item) -> B,
     {
-        Map{iter: self, f: f}
+        Map { iter: self, f }
     }
 
     /// Calls a closure on each element of an iterator.
@@ -599,7 +679,7 @@ pub trait Iterator {
     fn filter<P>(self, predicate: P) -> Filter<Self, P> where
         Self: Sized, P: FnMut(&Self::Item) -> bool,
     {
-        Filter{iter: self, predicate: predicate}
+        Filter {iter: self, predicate }
     }
 
     /// Creates an iterator that both filters and maps.
@@ -656,7 +736,7 @@ pub trait Iterator {
     fn filter_map<B, F>(self, f: F) -> FilterMap<Self, F> where
         Self: Sized, F: FnMut(Self::Item) -> Option<B>,
     {
-        FilterMap { iter: self, f: f }
+        FilterMap { iter: self, f }
     }
 
     /// Creates an iterator which gives the current iteration count as well as
@@ -809,7 +889,7 @@ pub trait Iterator {
     fn skip_while<P>(self, predicate: P) -> SkipWhile<Self, P> where
         Self: Sized, P: FnMut(&Self::Item) -> bool,
     {
-        SkipWhile{iter: self, flag: false, predicate: predicate}
+        SkipWhile { iter: self, flag: false, predicate }
     }
 
     /// Creates an iterator that yields elements based on a predicate.
@@ -889,7 +969,7 @@ pub trait Iterator {
     fn take_while<P>(self, predicate: P) -> TakeWhile<Self, P> where
         Self: Sized, P: FnMut(&Self::Item) -> bool,
     {
-        TakeWhile{iter: self, flag: false, predicate: predicate}
+        TakeWhile { iter: self, flag: false, predicate }
     }
 
     /// Creates an iterator that skips the first `n` elements.
@@ -911,7 +991,7 @@ pub trait Iterator {
     #[inline]
     #[stable(feature = "rust1", since = "1.0.0")]
     fn skip(self, n: usize) -> Skip<Self> where Self: Sized {
-        Skip{iter: self, n: n}
+        Skip { iter: self, n }
     }
 
     /// Creates an iterator that yields its first `n` elements.
@@ -943,7 +1023,7 @@ pub trait Iterator {
     #[inline]
     #[stable(feature = "rust1", since = "1.0.0")]
     fn take(self, n: usize) -> Take<Self> where Self: Sized, {
-        Take{iter: self, n: n}
+        Take { iter: self, n }
     }
 
     /// An iterator adaptor similar to [`fold`] that holds internal state and
@@ -988,7 +1068,7 @@ pub trait Iterator {
     fn scan<St, B, F>(self, initial_state: St, f: F) -> Scan<Self, St, F>
         where Self: Sized, F: FnMut(&mut St, Self::Item) -> Option<B>,
     {
-        Scan{iter: self, f: f, state: initial_state}
+        Scan { iter: self, f, state: initial_state }
     }
 
     /// Creates an iterator that works like map, but flattens nested structure.
@@ -1040,8 +1120,6 @@ pub trait Iterator {
     /// Basic usage:
     ///
     /// ```
-    /// #![feature(iterator_flatten)]
-    ///
     /// let data = vec![vec![1, 2, 3, 4], vec![5, 6]];
     /// let flattened = data.into_iter().flatten().collect::<Vec<u8>>();
     /// assert_eq!(flattened, &[1, 2, 3, 4, 5, 6]);
@@ -1050,8 +1128,6 @@ pub trait Iterator {
     /// Mapping and then flattening:
     ///
     /// ```
-    /// #![feature(iterator_flatten)]
-    ///
     /// let words = ["alpha", "beta", "gamma"];
     ///
     /// // chars() returns an iterator
@@ -1078,8 +1154,6 @@ pub trait Iterator {
     /// Flattening once only removes one level of nesting:
     ///
     /// ```
-    /// #![feature(iterator_flatten)]
-    ///
     /// let d3 = [[[1, 2], [3, 4]], [[5, 6], [7, 8]]];
     ///
     /// let d2 = d3.iter().flatten().collect::<Vec<_>>();
@@ -1097,7 +1171,7 @@ pub trait Iterator {
     ///
     /// [`flat_map()`]: #method.flat_map
     #[inline]
-    #[unstable(feature = "iterator_flatten", issue = "48213")]
+    #[stable(feature = "iterator_flatten", since = "1.29.0")]
     fn flatten(self) -> Flatten<Self>
     where Self: Sized, Self::Item: IntoIterator {
         Flatten { inner: flatten_compat(self) }
@@ -1170,8 +1244,9 @@ pub trait Iterator {
     /// happening at various parts in the pipeline. To do that, insert
     /// a call to `inspect()`.
     ///
-    /// It's much more common for `inspect()` to be used as a debugging tool
-    /// than to exist in your final code, but never say never.
+    /// It's more common for `inspect()` to be used as a debugging tool than to
+    /// exist in your final code, but applications may find it useful in certain
+    /// situations when errors need to be logged before being discarded.
     ///
     /// # Examples
     ///
@@ -1211,12 +1286,38 @@ pub trait Iterator {
     /// about to filter: 3
     /// 6
     /// ```
+    ///
+    /// Logging errors before discarding them:
+    ///
+    /// ```
+    /// let lines = ["1", "2", "a"];
+    ///
+    /// let sum: i32 = lines
+    ///     .iter()
+    ///     .map(|line| line.parse::<i32>())
+    ///     .inspect(|num| {
+    ///         if let Err(ref e) = *num {
+    ///             println!("Parsing error: {}", e);
+    ///         }
+    ///     })
+    ///     .filter_map(Result::ok)
+    ///     .sum();
+    ///
+    /// println!("Sum: {}", sum);
+    /// ```
+    ///
+    /// This will print:
+    ///
+    /// ```text
+    /// Parsing error: invalid digit found in string
+    /// Sum: 3
+    /// ```
     #[inline]
     #[stable(feature = "rust1", since = "1.0.0")]
     fn inspect<F>(self, f: F) -> Inspect<Self, F> where
         Self: Sized, F: FnMut(&Self::Item),
     {
-        Inspect{iter: self, f: f}
+        Inspect { iter: self, f }
     }
 
     /// Borrows an iterator, rather than consuming it.
@@ -1591,7 +1692,7 @@ pub trait Iterator {
     fn fold<B, F>(mut self, init: B, mut f: F) -> B where
         Self: Sized, F: FnMut(B, Self::Item) -> B,
     {
-        self.try_fold(init, move |acc, x| AlwaysOk(f(acc, x))).0
+        self.try_fold(init, move |acc, x| Ok::<B, !>(f(acc, x))).unwrap()
     }
 
     /// Tests if every element of the iterator matches a predicate.
@@ -1754,7 +1855,6 @@ pub trait Iterator {
     /// # Examples
     ///
     /// ```
-    /// #![feature(iterator_find_map)]
     /// let a = ["lol", "NaN", "2", "5"];
     ///
     /// let mut first_number = a.iter().find_map(|s| s.parse().ok());
@@ -1762,9 +1862,7 @@ pub trait Iterator {
     /// assert_eq!(first_number, Some(2));
     /// ```
     #[inline]
-    #[unstable(feature = "iterator_find_map",
-               reason = "unstable new API",
-               issue = "49602")]
+    #[stable(feature = "iterator_find_map", since = "1.30.0")]
     fn find_map<B, F>(&mut self, mut f: F) -> Option<B> where
         Self: Sized,
         F: FnMut(Self::Item) -> Option<B>,
@@ -2520,7 +2618,7 @@ fn select_fold1<I, B, FProj, FCmp>(mut it: I,
 }
 
 #[stable(feature = "rust1", since = "1.0.0")]
-impl<'a, I: Iterator + ?Sized> Iterator for &'a mut I {
+impl<I: Iterator + ?Sized> Iterator for &mut I {
     type Item = I::Item;
     fn next(&mut self) -> Option<I::Item> { (**self).next() }
     fn size_hint(&self) -> (usize, Option<usize>) { (**self).size_hint() }