diff --git a/src/liballoc/boxed.rs b/src/liballoc/boxed.rs index 7696abd659f02..8757f10c8ba53 100644 --- a/src/liballoc/boxed.rs +++ b/src/liballoc/boxed.rs @@ -312,7 +312,11 @@ impl DoubleEndedIterator for Box { fn next_back(&mut self) -> Option { (**self).next_back() } } #[stable(feature = "rust1", since = "1.0.0")] -impl ExactSizeIterator for Box {} +impl ExactSizeIterator for Box { + fn len(&self) -> usize { + (**self).len() + } +} /// `FnBox` is a version of the `FnOnce` intended for use with boxed diff --git a/src/libcore/iter.rs b/src/libcore/iter.rs index 21510e1a83b8f..46155cb04d068 100644 --- a/src/libcore/iter.rs +++ b/src/libcore/iter.rs @@ -1205,8 +1205,14 @@ pub trait RandomAccessIterator: Iterator { /// This trait is a helper for iterators like the vector iterator, so that /// it can support double-ended enumeration. /// -/// `Iterator::size_hint` *must* return the exact size of the iterator. -/// Note that the size must fit in `usize`. +/// `ExactSizeIterator::len` must return the exact size of the iterator. +/// +/// Note: The default implementation of `ExactSizeIterator::len` assumes +/// that `Iterator::size_hint` returns the exact size of the iterator +/// (`(exact_size, Some(exact_size))`). If this is not the case, you must +/// provide your own `ExactSizeIterator::len` implementation. +/// +/// Also Note: The size must fit in `usize`. #[stable(feature = "rust1", since = "1.0.0")] pub trait ExactSizeIterator: Iterator { #[inline] @@ -1224,26 +1230,53 @@ pub trait ExactSizeIterator: Iterator { } #[stable(feature = "rust1", since = "1.0.0")] -impl<'a, I: ExactSizeIterator + ?Sized> ExactSizeIterator for &'a mut I {} +impl<'a, I: ExactSizeIterator + ?Sized> ExactSizeIterator for &'a mut I { + fn len(&self) -> usize { + (*self).len() + } +} // All adaptors that preserve the size of the wrapped iterator are fine // Adaptors that may overflow in `size_hint` are not, i.e. `Chain`. #[stable(feature = "rust1", since = "1.0.0")] -impl ExactSizeIterator for Enumerate where I: ExactSizeIterator {} +impl ExactSizeIterator for Enumerate + where I: ExactSizeIterator { + + fn len(&self) -> usize { + self.iter.len() + } +} #[stable(feature = "rust1", since = "1.0.0")] -impl ExactSizeIterator for Inspect where - F: FnMut(&I::Item), -{} +impl ExactSizeIterator for Inspect + where F: FnMut(&I::Item) { + + fn len(&self) -> usize { + self.iter.len() + } +} #[stable(feature = "rust1", since = "1.0.0")] impl ExactSizeIterator for Rev - where I: ExactSizeIterator + DoubleEndedIterator {} + where I: ExactSizeIterator + DoubleEndedIterator { + + fn len(&self) -> usize { + self.iter.len() + } +} #[stable(feature = "rust1", since = "1.0.0")] -impl ExactSizeIterator for Map where - F: FnMut(I::Item) -> B, -{} +impl ExactSizeIterator for Map + where F: FnMut(I::Item) -> B { + + fn len(&self) -> usize { + self.iter.len() + } +} #[stable(feature = "rust1", since = "1.0.0")] impl ExactSizeIterator for Zip - where A: ExactSizeIterator, B: ExactSizeIterator {} + where A: ExactSizeIterator, B: ExactSizeIterator { + fn len(&self) -> usize { + cmp::min(self.a.len(), self.b.len()) + } +} /// An double-ended iterator with the direction inverted #[derive(Clone)] @@ -1369,8 +1402,12 @@ impl<'a, I, T: 'a> DoubleEndedIterator for Cloned #[stable(feature = "rust1", since = "1.0.0")] impl<'a, I, T: 'a> ExactSizeIterator for Cloned - where I: ExactSizeIterator, T: Clone -{} + where I: ExactSizeIterator, T: Clone { + + fn len(&self) -> usize { + self.it.len() + } +} #[unstable(feature = "core", reason = "trait is experimental")] impl<'a, I, T: 'a> RandomAccessIterator for Cloned @@ -1853,7 +1890,11 @@ impl Iterator for Peekable { } #[stable(feature = "rust1", since = "1.0.0")] -impl ExactSizeIterator for Peekable {} +impl ExactSizeIterator for Peekable { + fn len(&self) -> usize { + (if self.peeked.is_some() { 1 } else { 0 }) + self.iter.len() + } +} #[stable(feature = "rust1", since = "1.0.0")] impl Peekable { @@ -2018,7 +2059,11 @@ impl RandomAccessIterator for Skip where I: RandomAccessIterator{ } #[stable(feature = "rust1", since = "1.0.0")] -impl ExactSizeIterator for Skip where I: ExactSizeIterator {} +impl ExactSizeIterator for Skip where I: ExactSizeIterator { + fn len(&self) -> usize { + self.iter.len().saturating_sub(self.n) + } +} /// An iterator that only iterates over the first `n` iterations of `iter`. #[derive(Clone)] @@ -2076,7 +2121,11 @@ impl RandomAccessIterator for Take where I: RandomAccessIterator{ } #[stable(feature = "rust1", since = "1.0.0")] -impl ExactSizeIterator for Take where I: ExactSizeIterator {} +impl ExactSizeIterator for Take where I: ExactSizeIterator { + fn len(&self) -> usize { + cmp::min(self.iter.len(), self.n) + } +} /// An iterator to maintain state while iterating another iterator @@ -2243,7 +2292,11 @@ impl RandomAccessIterator for Fuse where I: RandomAccessIterator { } #[stable(feature = "rust1", since = "1.0.0")] -impl ExactSizeIterator for Fuse where I: ExactSizeIterator {} +impl ExactSizeIterator for Fuse where I: ExactSizeIterator { + fn len(&self) -> usize { + self.iter.len() + } +} impl Fuse { /// Resets the `Fuse` such that the next call to `.next()` or