diff --git a/src/libstd/iterator.rs b/src/libstd/iterator.rs
index 394066f1d4cf..fa27f4560c14 100644
--- a/src/libstd/iterator.rs
+++ b/src/libstd/iterator.rs
@@ -17,6 +17,8 @@ implementing the `Iterator` trait.
*/
+#[allow(default_methods)]; // solid enough for the use case here
+
use cmp;
use iter::{FromIter, Times};
use num::{Zero, One};
@@ -31,6 +33,12 @@ use clone::Clone;
pub trait Iterator {
/// Advance the iterator and return the next value. Return `None` when the end is reached.
fn next(&mut self) -> Option;
+
+ /// Return a lower bound and upper bound on the remaining length of the iterator.
+ ///
+ /// The common use case for the estimate is pre-allocating space to store the results.
+ #[cfg(not(stage0))]
+ fn size_hint(&self) -> (Option, Option) { (None, None) }
}
/// Iterator adaptors provided for every `Iterator` implementation. The adaptor objects are also
@@ -594,6 +602,27 @@ impl, U: Iterator> Iterator for ChainIterator {
self.b.next()
}
}
+
+ #[inline]
+ #[cfg(not(stage0))]
+ fn size_hint(&self) -> (Option, Option) {
+ let (a_lower, a_upper) = self.a.size_hint();
+ let (b_lower, b_upper) = self.b.size_hint();
+
+ let lower = match (a_lower, b_lower) {
+ (Some(x), Some(y)) => Some(x + y),
+ (Some(x), None) => Some(x),
+ (None, Some(y)) => Some(y),
+ (None, None) => None
+ };
+
+ let upper = match (a_upper, b_upper) {
+ (Some(x), Some(y)) => Some(x + y),
+ _ => None
+ };
+
+ (lower, upper)
+ }
}
/// An iterator which iterates two other iterators simultaneously
@@ -627,6 +656,12 @@ impl<'self, A, B, T: Iterator> Iterator for MapIterator<'self, A, B, T> {
_ => None
}
}
+
+ #[inline]
+ #[cfg(not(stage0))]
+ fn size_hint(&self) -> (Option, Option) {
+ self.iter.size_hint()
+ }
}
/// An iterator which filters the elements of `iter` with `predicate`
@@ -647,6 +682,13 @@ impl<'self, A, T: Iterator> Iterator for FilterIterator<'self, A, T> {
}
None
}
+
+ #[inline]
+ #[cfg(not(stage0))]
+ fn size_hint(&self) -> (Option, Option) {
+ let (_, upper) = self.iter.size_hint();
+ (None, upper) // can't know a lower bound, due to the predicate
+ }
}
/// An iterator which uses `f` to both filter and map elements from `iter`
@@ -666,6 +708,13 @@ impl<'self, A, B, T: Iterator> Iterator for FilterMapIterator<'self, A, B,
}
None
}
+
+ #[inline]
+ #[cfg(not(stage0))]
+ fn size_hint(&self) -> (Option, Option) {
+ let (_, upper) = self.iter.size_hint();
+ (None, upper) // can't know a lower bound, due to the predicate
+ }
}
/// An iterator which yields the current count and the element during iteration
diff --git a/src/libstd/vec.rs b/src/libstd/vec.rs
index 703224e37c57..b03b6efcaaf3 100644
--- a/src/libstd/vec.rs
+++ b/src/libstd/vec.rs
@@ -29,6 +29,7 @@ use ptr::to_unsafe_ptr;
use ptr;
use ptr::RawPtr;
use sys;
+use sys::size_of;
use uint;
use unstable::intrinsics;
use vec;
@@ -2454,6 +2455,13 @@ macro_rules! iterator {
}
}
}
+
+ #[inline]
+ #[cfg(not(stage0))]
+ fn size_hint(&self) -> (Option, Option) {
+ let exact = Some(((self.end as uint) - (self.ptr as uint)) / size_of::<$elem>());
+ (exact, exact)
+ }
}
}
}
@@ -3909,16 +3917,23 @@ mod tests {
}
#[test]
+ #[cfg(not(stage0))]
fn test_iterator() {
use iterator::*;
let xs = [1, 2, 5, 10, 11];
- let ys = [1, 2, 5, 10, 11, 19];
let mut it = xs.iter();
- let mut i = 0;
- for it.advance |&x| {
- assert_eq!(x, ys[i]);
- i += 1;
- }
+ assert_eq!(it.size_hint(), (Some(5), Some(5)));
+ assert_eq!(it.next().unwrap(), &1);
+ assert_eq!(it.size_hint(), (Some(4), Some(4)));
+ assert_eq!(it.next().unwrap(), &2);
+ assert_eq!(it.size_hint(), (Some(3), Some(3)));
+ assert_eq!(it.next().unwrap(), &5);
+ assert_eq!(it.size_hint(), (Some(2), Some(2)));
+ assert_eq!(it.next().unwrap(), &10);
+ assert_eq!(it.size_hint(), (Some(1), Some(1)));
+ assert_eq!(it.next().unwrap(), &11);
+ assert_eq!(it.size_hint(), (Some(0), Some(0)));
+ assert!(it.next().is_none());
}
#[test]