]> git.lizzy.rs Git - rust.git/commitdiff
Auto merge of #37944 - bluss:adaptors-are-empty, r=alexcrichton
authorbors <bors@rust-lang.org>
Thu, 24 Nov 2016 17:56:11 +0000 (11:56 -0600)
committerGitHub <noreply@github.com>
Thu, 24 Nov 2016 17:56:11 +0000 (11:56 -0600)
Forward ExactSizeIterator::len and is_empty for important iterator adaptors

Forward ExactSizeIterator::len and is_empty for important iterator adaptors

Because some iterators will provide improved version of len and/or is_empty,
adaptors should forward to those implementations if possible.

1  2 
src/libcore/iter/mod.rs

diff --combined src/libcore/iter/mod.rs
index 02a2e370547e9f147e038e871d4e619be0d14189,ca718d29952d93bd1b6ec905fb2d9da7d393e1b4..2e08508de67f3ad1b887c8d922ae580e1360de94
@@@ -368,7 -368,16 +368,16 @@@ impl<I> DoubleEndedIterator for Rev<I> 
  
  #[stable(feature = "rust1", since = "1.0.0")]
  impl<I> ExactSizeIterator for Rev<I>
-     where I: ExactSizeIterator + DoubleEndedIterator {}
+     where I: ExactSizeIterator + DoubleEndedIterator
+ {
+     fn len(&self) -> usize {
+         self.iter.len()
+     }
+     fn is_empty(&self) -> bool {
+         self.iter.is_empty()
+     }
+ }
  
  #[unstable(feature = "fused", issue = "35602")]
  impl<I> FusedIterator for Rev<I>
@@@ -425,7 -434,15 +434,15 @@@ impl<'a, I, T: 'a> DoubleEndedIterator 
  #[stable(feature = "iter_cloned", since = "1.1.0")]
  impl<'a, I, T: 'a> ExactSizeIterator for Cloned<I>
      where I: ExactSizeIterator<Item=&'a T>, T: Clone
- {}
+ {
+     fn len(&self) -> usize {
+         self.it.len()
+     }
+     fn is_empty(&self) -> bool {
+         self.it.is_empty()
+     }
+ }
  
  #[unstable(feature = "fused", issue = "35602")]
  impl<'a, I, T: 'a> FusedIterator for Cloned<I>
@@@ -1007,7 -1024,16 +1024,16 @@@ impl<B, I: DoubleEndedIterator, F> Doub
  
  #[stable(feature = "rust1", since = "1.0.0")]
  impl<B, I: ExactSizeIterator, F> ExactSizeIterator for Map<I, F>
-     where F: FnMut(I::Item) -> B {}
+     where F: FnMut(I::Item) -> B
+ {
+     fn len(&self) -> usize {
+         self.iter.len()
+     }
+     fn is_empty(&self) -> bool {
+         self.iter.is_empty()
+     }
+ }
  
  #[unstable(feature = "fused", issue = "35602")]
  impl<B, I: FusedIterator, F> FusedIterator for Map<I, F>
@@@ -1236,7 -1262,15 +1262,15 @@@ impl<I> DoubleEndedIterator for Enumera
  }
  
  #[stable(feature = "rust1", since = "1.0.0")]
- impl<I> ExactSizeIterator for Enumerate<I> where I: ExactSizeIterator {}
+ impl<I> ExactSizeIterator for Enumerate<I> where I: ExactSizeIterator {
+     fn len(&self) -> usize {
+         self.iter.len()
+     }
+     fn is_empty(&self) -> bool {
+         self.iter.is_empty()
+     }
+ }
  
  #[doc(hidden)]
  unsafe impl<I> TrustedRandomAccess for Enumerate<I>
@@@ -1273,68 -1307,54 +1307,68 @@@ unsafe impl<I> TrustedLen for Enumerate
  #[stable(feature = "rust1", since = "1.0.0")]
  pub struct Peekable<I: Iterator> {
      iter: I,
 -    peeked: Option<I::Item>,
 +    /// Remember a peeked value, even if it was None.
 +    peeked: Option<Option<I::Item>>,
  }
  
 +// Peekable must remember if a None has been seen in the `.peek()` method.
 +// It ensures that `.peek(); .peek();` or `.peek(); .next();` only advances the
 +// underlying iterator at most once. This does not by itself make the iterator
 +// fused.
  #[stable(feature = "rust1", since = "1.0.0")]
  impl<I: Iterator> Iterator for Peekable<I> {
      type Item = I::Item;
  
      #[inline]
      fn next(&mut self) -> Option<I::Item> {
 -        match self.peeked {
 -            Some(_) => self.peeked.take(),
 +        match self.peeked.take() {
 +            Some(v) => v,
              None => self.iter.next(),
          }
      }
  
      #[inline]
      #[rustc_inherit_overflow_checks]
 -    fn count(self) -> usize {
 -        (if self.peeked.is_some() { 1 } else { 0 }) + self.iter.count()
 +    fn count(mut self) -> usize {
 +        match self.peeked.take() {
 +            Some(None) => 0,
 +            Some(Some(_)) => 1 + self.iter.count(),
 +            None => self.iter.count(),
 +        }
      }
  
      #[inline]
      fn nth(&mut self, n: usize) -> Option<I::Item> {
 -        match self.peeked {
 -            Some(_) if n == 0 => self.peeked.take(),
 -            Some(_) => {
 -                self.peeked = None;
 -                self.iter.nth(n-1)
 -            },
 -            None => self.iter.nth(n)
 +        match self.peeked.take() {
 +            // the .take() below is just to avoid "move into pattern guard"
 +            Some(ref mut v) if n == 0 => v.take(),
 +            Some(None) => None,
 +            Some(Some(_)) => self.iter.nth(n - 1),
 +            None => self.iter.nth(n),
          }
      }
  
      #[inline]
 -    fn last(self) -> Option<I::Item> {
 -        self.iter.last().or(self.peeked)
 +    fn last(mut self) -> Option<I::Item> {
 +        let peek_opt = match self.peeked.take() {
 +            Some(None) => return None,
 +            Some(v) => v,
 +            None => None,
 +        };
 +        self.iter.last().or(peek_opt)
      }
  
      #[inline]
      fn size_hint(&self) -> (usize, Option<usize>) {
 +        let peek_len = match self.peeked {
 +            Some(None) => return (0, Some(0)),
 +            Some(Some(_)) => 1,
 +            None => 0,
 +        };
          let (lo, hi) = self.iter.size_hint();
 -        if self.peeked.is_some() {
 -            let lo = lo.saturating_add(1);
 -            let hi = hi.and_then(|x| x.checked_add(1));
 -            (lo, hi)
 -        } else {
 -            (lo, hi)
 -        }
 +        let lo = lo.saturating_add(peek_len);
 +        let hi = hi.and_then(|x| x.checked_add(peek_len));
 +        (lo, hi)
      }
  }
  
@@@ -1386,13 -1406,9 +1420,13 @@@ impl<I: Iterator> Peekable<I> 
      #[stable(feature = "rust1", since = "1.0.0")]
      pub fn peek(&mut self) -> Option<&I::Item> {
          if self.peeked.is_none() {
 -            self.peeked = self.iter.next();
 +            self.peeked = Some(self.iter.next());
 +        }
 +        match self.peeked {
 +            Some(Some(ref value)) => Some(value),
 +            Some(None) => None,
 +            _ => unreachable!(),
          }
 -        self.peeked.as_ref()
      }
  }
  
@@@ -1945,7 -1961,15 +1979,15 @@@ impl<I> DoubleEndedIterator for Fuse<I
  
  
  #[stable(feature = "rust1", since = "1.0.0")]
- impl<I> ExactSizeIterator for Fuse<I> where I: ExactSizeIterator {}
+ impl<I> ExactSizeIterator for Fuse<I> where I: ExactSizeIterator {
+     fn len(&self) -> usize {
+         self.iter.len()
+     }
+     fn is_empty(&self) -> bool {
+         self.iter.is_empty()
+     }
+ }
  
  /// An iterator that calls a function with a reference to each element before
  /// yielding it.
@@@ -2012,7 -2036,16 +2054,16 @@@ impl<I: DoubleEndedIterator, F> DoubleE
  
  #[stable(feature = "rust1", since = "1.0.0")]
  impl<I: ExactSizeIterator, F> ExactSizeIterator for Inspect<I, F>
-     where F: FnMut(&I::Item) {}
+     where F: FnMut(&I::Item)
+ {
+     fn len(&self) -> usize {
+         self.iter.len()
+     }
+     fn is_empty(&self) -> bool {
+         self.iter.is_empty()
+     }
+ }
  
  #[unstable(feature = "fused", issue = "35602")]
  impl<I: FusedIterator, F> FusedIterator for Inspect<I, F>