Skip to content

Commit a9f178c

Browse files
committed
auto merge of #7570 : kballard/rust/iterator-size-hint, r=thestinger
Change the signature of Iterator.size_hint() to always have a lower bound. Implement .size_hint() on all remaining iterators (if it differs from the default).
2 parents c1c7768 + e6f9b08 commit a9f178c

File tree

6 files changed

+161
-31
lines changed

6 files changed

+161
-31
lines changed

src/libextra/priority_queue.rs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -186,6 +186,9 @@ pub struct PriorityQueueIterator <'self, T> {
186186
impl<'self, T> Iterator<&'self T> for PriorityQueueIterator<'self, T> {
187187
#[inline]
188188
fn next(&mut self) -> Option<(&'self T)> { self.iter.next() }
189+
190+
#[inline]
191+
fn size_hint(&self) -> (uint, Option<uint>) { self.iter.size_hint() }
189192
}
190193

191194
#[cfg(test)]

src/libextra/treemap.rs

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -198,14 +198,15 @@ impl<K: TotalOrd, V> TreeMap<K, V> {
198198
/// Get a lazy iterator over the key-value pairs in the map.
199199
/// Requires that it be frozen (immutable).
200200
pub fn iter<'a>(&'a self) -> TreeMapIterator<'a, K, V> {
201-
TreeMapIterator{stack: ~[], node: &self.root}
201+
TreeMapIterator{stack: ~[], node: &self.root, remaining: self.length}
202202
}
203203
}
204204

205205
/// Lazy forward iterator over a map
206206
pub struct TreeMapIterator<'self, K, V> {
207207
priv stack: ~[&'self ~TreeNode<K, V>],
208-
priv node: &'self Option<~TreeNode<K, V>>
208+
priv node: &'self Option<~TreeNode<K, V>>,
209+
priv remaining: uint
209210
}
210211

211212
impl<'self, K, V> Iterator<(&'self K, &'self V)> for TreeMapIterator<'self, K, V> {
@@ -222,12 +223,18 @@ impl<'self, K, V> Iterator<(&'self K, &'self V)> for TreeMapIterator<'self, K, V
222223
None => {
223224
let res = self.stack.pop();
224225
self.node = &res.right;
226+
self.remaining -= 1;
225227
return Some((&res.key, &res.value));
226228
}
227229
}
228230
}
229231
None
230232
}
233+
234+
#[inline]
235+
fn size_hint(&self) -> (uint, Option<uint>) {
236+
(self.remaining, Some(self.remaining))
237+
}
231238
}
232239

233240
impl<'self, T> Iterator<&'self T> for TreeSetIterator<'self, T> {

src/librustc/util/enum_set.rs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -125,9 +125,9 @@ impl<E:CLike> Iterator<E> for EnumSetIterator<E> {
125125
Some(elem)
126126
}
127127

128-
fn size_hint(&self) -> (Option<uint>, Option<uint>) {
129-
let exact = Some(self.bits.population_count());
130-
(exact, exact)
128+
fn size_hint(&self) -> (uint, Option<uint>) {
129+
let exact = self.bits.population_count();
130+
(exact, Some(exact))
131131
}
132132
}
133133

src/libstd/iterator.rs

Lines changed: 124 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@ use option::{Option, Some, None};
2626
use ops::{Add, Mul};
2727
use cmp::Ord;
2828
use clone::Clone;
29+
use uint;
2930

3031
/// Conversion from an `Iterator`
3132
pub trait FromIterator<A, T: Iterator<A>> {
@@ -43,7 +44,7 @@ pub trait Iterator<A> {
4344
/// Return a lower bound and upper bound on the remaining length of the iterator.
4445
///
4546
/// The common use case for the estimate is pre-allocating space to store the results.
46-
fn size_hint(&self) -> (Option<uint>, Option<uint>) { (None, None) }
47+
fn size_hint(&self) -> (uint, Option<uint>) { (0, None) }
4748
}
4849

4950
/// Iterator adaptors provided for every `Iterator` implementation. The adaptor objects are also
@@ -684,18 +685,18 @@ impl<A, T: Iterator<A>, U: Iterator<A>> Iterator<A> for ChainIterator<A, T, U> {
684685
}
685686

686687
#[inline]
687-
fn size_hint(&self) -> (Option<uint>, Option<uint>) {
688+
fn size_hint(&self) -> (uint, Option<uint>) {
688689
let (a_lower, a_upper) = self.a.size_hint();
689690
let (b_lower, b_upper) = self.b.size_hint();
690691

691-
let lower = match (a_lower, b_lower) {
692-
(Some(x), Some(y)) => Some(x + y),
693-
(Some(x), None) => Some(x),
694-
(None, Some(y)) => Some(y),
695-
(None, None) => None
692+
let lower = if uint::max_value - a_lower < b_lower {
693+
uint::max_value
694+
} else {
695+
a_lower + b_lower
696696
};
697697

698698
let upper = match (a_upper, b_upper) {
699+
(Some(x), Some(y)) if uint::max_value - x < y => Some(uint::max_value),
699700
(Some(x), Some(y)) => Some(x + y),
700701
_ => None
701702
};
@@ -719,6 +720,23 @@ impl<A, B, T: Iterator<A>, U: Iterator<B>> Iterator<(A, B)> for ZipIterator<A, T
719720
_ => None
720721
}
721722
}
723+
724+
#[inline]
725+
fn size_hint(&self) -> (uint, Option<uint>) {
726+
let (a_lower, a_upper) = self.a.size_hint();
727+
let (b_lower, b_upper) = self.b.size_hint();
728+
729+
let lower = cmp::min(a_lower, b_lower);
730+
731+
let upper = match (a_upper, b_upper) {
732+
(Some(x), Some(y)) => Some(cmp::min(x,y)),
733+
(Some(x), None) => Some(x),
734+
(None, Some(y)) => Some(y),
735+
(None, None) => None
736+
};
737+
738+
(lower, upper)
739+
}
722740
}
723741

724742
/// An iterator which maps the values of `iter` with `f`
@@ -737,7 +755,7 @@ impl<'self, A, B, T: Iterator<A>> Iterator<B> for MapIterator<'self, A, B, T> {
737755
}
738756

739757
#[inline]
740-
fn size_hint(&self) -> (Option<uint>, Option<uint>) {
758+
fn size_hint(&self) -> (uint, Option<uint>) {
741759
self.iter.size_hint()
742760
}
743761
}
@@ -762,9 +780,9 @@ impl<'self, A, T: Iterator<A>> Iterator<A> for FilterIterator<'self, A, T> {
762780
}
763781

764782
#[inline]
765-
fn size_hint(&self) -> (Option<uint>, Option<uint>) {
783+
fn size_hint(&self) -> (uint, Option<uint>) {
766784
let (_, upper) = self.iter.size_hint();
767-
(None, upper) // can't know a lower bound, due to the predicate
785+
(0, upper) // can't know a lower bound, due to the predicate
768786
}
769787
}
770788

@@ -787,9 +805,9 @@ impl<'self, A, B, T: Iterator<A>> Iterator<B> for FilterMapIterator<'self, A, B,
787805
}
788806

789807
#[inline]
790-
fn size_hint(&self) -> (Option<uint>, Option<uint>) {
808+
fn size_hint(&self) -> (uint, Option<uint>) {
791809
let (_, upper) = self.iter.size_hint();
792-
(None, upper) // can't know a lower bound, due to the predicate
810+
(0, upper) // can't know a lower bound, due to the predicate
793811
}
794812
}
795813

@@ -812,6 +830,11 @@ impl<A, T: Iterator<A>> Iterator<(uint, A)> for EnumerateIterator<A, T> {
812830
_ => None
813831
}
814832
}
833+
834+
#[inline]
835+
fn size_hint(&self) -> (uint, Option<uint>) {
836+
self.iter.size_hint()
837+
}
815838
}
816839

817840
/// An iterator which rejects elements while `predicate` is true
@@ -844,6 +867,12 @@ impl<'self, A, T: Iterator<A>> Iterator<A> for SkipWhileIterator<'self, A, T> {
844867
}
845868
}
846869
}
870+
871+
#[inline]
872+
fn size_hint(&self) -> (uint, Option<uint>) {
873+
let (_, upper) = self.iter.size_hint();
874+
(0, upper) // can't know a lower bound, due to the predicate
875+
}
847876
}
848877

849878
/// An iterator which only accepts elements while `predicate` is true
@@ -872,6 +901,12 @@ impl<'self, A, T: Iterator<A>> Iterator<A> for TakeWhileIterator<'self, A, T> {
872901
}
873902
}
874903
}
904+
905+
#[inline]
906+
fn size_hint(&self) -> (uint, Option<uint>) {
907+
let (_, upper) = self.iter.size_hint();
908+
(0, upper) // can't know a lower bound, due to the predicate
909+
}
875910
}
876911

877912
/// An iterator which skips over `n` elements of `iter`.
@@ -905,6 +940,21 @@ impl<A, T: Iterator<A>> Iterator<A> for SkipIterator<A, T> {
905940
next
906941
}
907942
}
943+
944+
#[inline]
945+
fn size_hint(&self) -> (uint, Option<uint>) {
946+
let (lower, upper) = self.iter.size_hint();
947+
948+
let lower = if lower >= self.n { lower - self.n } else { 0 };
949+
950+
let upper = match upper {
951+
Some(x) if x >= self.n => Some(x - self.n),
952+
Some(_) => Some(0),
953+
None => None
954+
};
955+
956+
(lower, upper)
957+
}
908958
}
909959

910960
/// An iterator which only iterates over the first `n` iterations of `iter`.
@@ -925,6 +975,20 @@ impl<A, T: Iterator<A>> Iterator<A> for TakeIterator<A, T> {
925975
None
926976
}
927977
}
978+
979+
#[inline]
980+
fn size_hint(&self) -> (uint, Option<uint>) {
981+
let (lower, upper) = self.iter.size_hint();
982+
983+
let lower = cmp::min(lower, self.n);
984+
985+
let upper = match upper {
986+
Some(x) if x < self.n => Some(x),
987+
_ => Some(self.n)
988+
};
989+
990+
(lower, upper)
991+
}
928992
}
929993

930994
/// An iterator to maintain state while iterating another iterator
@@ -941,6 +1005,12 @@ impl<'self, A, B, T: Iterator<A>, St> Iterator<B> for ScanIterator<'self, A, B,
9411005
fn next(&mut self) -> Option<B> {
9421006
self.iter.next().chain(|a| (self.f)(&mut self.state, a))
9431007
}
1008+
1009+
#[inline]
1010+
fn size_hint(&self) -> (uint, Option<uint>) {
1011+
let (_, upper) = self.iter.size_hint();
1012+
(0, upper) // can't know a lower bound, due to the scan function
1013+
}
9441014
}
9451015

9461016
/// An iterator that maps each element to an iterator,
@@ -1022,6 +1092,11 @@ impl<A: Add<A, A> + Clone> Iterator<A> for Counter<A> {
10221092
self.state = self.state.add(&self.step); // FIXME: #6050
10231093
Some(result)
10241094
}
1095+
1096+
#[inline]
1097+
fn size_hint(&self) -> (uint, Option<uint>) {
1098+
(uint::max_value, None) // Too bad we can't specify an infinite lower bound
1099+
}
10251100
}
10261101

10271102
#[cfg(test)]
@@ -1237,6 +1312,43 @@ mod tests {
12371312
assert_eq!(v.slice(0, 0).iter().transform(|&x| x).min(), None);
12381313
}
12391314

1315+
#[test]
1316+
fn test_iterator_size_hint() {
1317+
let c = Counter::new(0, 1);
1318+
let v = &[0, 1, 2, 3, 4, 5, 6, 7, 8, 9];
1319+
let v2 = &[10, 11, 12];
1320+
let vi = v.iter();
1321+
1322+
assert_eq!(c.size_hint(), (uint::max_value, None));
1323+
assert_eq!(vi.size_hint(), (10, Some(10)));
1324+
1325+
assert_eq!(c.take_(5).size_hint(), (5, Some(5)));
1326+
assert_eq!(c.skip(5).size_hint().second(), None);
1327+
assert_eq!(c.take_while(|_| false).size_hint(), (0, None));
1328+
assert_eq!(c.skip_while(|_| false).size_hint(), (0, None));
1329+
assert_eq!(c.enumerate().size_hint(), (uint::max_value, None));
1330+
assert_eq!(c.chain_(vi.transform(|&i| i)).size_hint(), (uint::max_value, None));
1331+
assert_eq!(c.zip(vi).size_hint(), (10, Some(10)));
1332+
assert_eq!(c.scan(0, |_,_| Some(0)).size_hint(), (0, None));
1333+
assert_eq!(c.filter(|_| false).size_hint(), (0, None));
1334+
assert_eq!(c.transform(|_| 0).size_hint(), (uint::max_value, None));
1335+
assert_eq!(c.filter_map(|_| Some(0)).size_hint(), (0, None));
1336+
1337+
assert_eq!(vi.take_(5).size_hint(), (5, Some(5)));
1338+
assert_eq!(vi.take_(12).size_hint(), (10, Some(10)));
1339+
assert_eq!(vi.skip(3).size_hint(), (7, Some(7)));
1340+
assert_eq!(vi.skip(12).size_hint(), (0, Some(0)));
1341+
assert_eq!(vi.take_while(|_| false).size_hint(), (0, Some(10)));
1342+
assert_eq!(vi.skip_while(|_| false).size_hint(), (0, Some(10)));
1343+
assert_eq!(vi.enumerate().size_hint(), (10, Some(10)));
1344+
assert_eq!(vi.chain_(v2.iter()).size_hint(), (13, Some(13)));
1345+
assert_eq!(vi.zip(v2.iter()).size_hint(), (3, Some(3)));
1346+
assert_eq!(vi.scan(0, |_,_| Some(0)).size_hint(), (0, Some(10)));
1347+
assert_eq!(vi.filter(|_| false).size_hint(), (0, Some(10)));
1348+
assert_eq!(vi.transform(|i| i+1).size_hint(), (10, Some(10)));
1349+
assert_eq!(vi.filter_map(|_| Some(0)).size_hint(), (0, Some(10)));
1350+
}
1351+
12401352
#[test]
12411353
fn test_collect() {
12421354
let a = ~[1, 2, 3, 4, 5];

src/libstd/vec.rs

Lines changed: 14 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -2024,14 +2024,14 @@ macro_rules! iterator {
20242024
}
20252025

20262026
#[inline]
2027-
fn size_hint(&self) -> (Option<uint>, Option<uint>) {
2027+
fn size_hint(&self) -> (uint, Option<uint>) {
20282028
let diff = if $step > 0 {
20292029
(self.end as uint) - (self.ptr as uint)
20302030
} else {
20312031
(self.ptr as uint) - (self.end as uint)
20322032
};
2033-
let exact = Some(diff / size_of::<$elem>());
2034-
(exact, exact)
2033+
let exact = diff / size_of::<$elem>();
2034+
(exact, Some(exact))
20352035
}
20362036
}
20372037
}
@@ -2132,7 +2132,7 @@ impl<A, T: Iterator<A>> FromIterator<A, T> for ~[A] {
21322132
impl<A, T: Iterator<A>> FromIterator<A, T> for ~[A] {
21332133
pub fn from_iterator(iterator: &mut T) -> ~[A] {
21342134
let (lower, _) = iterator.size_hint();
2135-
let mut xs = with_capacity(lower.get_or_zero());
2135+
let mut xs = with_capacity(lower);
21362136
for iterator.advance |x| {
21372137
xs.push(x);
21382138
}
@@ -2968,28 +2968,28 @@ mod tests {
29682968
use iterator::*;
29692969
let xs = [1, 2, 5, 10, 11];
29702970
let mut it = xs.iter();
2971-
assert_eq!(it.size_hint(), (Some(5), Some(5)));
2971+
assert_eq!(it.size_hint(), (5, Some(5)));
29722972
assert_eq!(it.next().unwrap(), &1);
2973-
assert_eq!(it.size_hint(), (Some(4), Some(4)));
2973+
assert_eq!(it.size_hint(), (4, Some(4)));
29742974
assert_eq!(it.next().unwrap(), &2);
2975-
assert_eq!(it.size_hint(), (Some(3), Some(3)));
2975+
assert_eq!(it.size_hint(), (3, Some(3)));
29762976
assert_eq!(it.next().unwrap(), &5);
2977-
assert_eq!(it.size_hint(), (Some(2), Some(2)));
2977+
assert_eq!(it.size_hint(), (2, Some(2)));
29782978
assert_eq!(it.next().unwrap(), &10);
2979-
assert_eq!(it.size_hint(), (Some(1), Some(1)));
2979+
assert_eq!(it.size_hint(), (1, Some(1)));
29802980
assert_eq!(it.next().unwrap(), &11);
2981-
assert_eq!(it.size_hint(), (Some(0), Some(0)));
2981+
assert_eq!(it.size_hint(), (0, Some(0)));
29822982
assert!(it.next().is_none());
29832983
}
29842984

29852985
#[test]
29862986
fn test_iter_size_hints() {
29872987
use iterator::*;
29882988
let mut xs = [1, 2, 5, 10, 11];
2989-
assert_eq!(xs.iter().size_hint(), (Some(5), Some(5)));
2990-
assert_eq!(xs.rev_iter().size_hint(), (Some(5), Some(5)));
2991-
assert_eq!(xs.mut_iter().size_hint(), (Some(5), Some(5)));
2992-
assert_eq!(xs.mut_rev_iter().size_hint(), (Some(5), Some(5)));
2989+
assert_eq!(xs.iter().size_hint(), (5, Some(5)));
2990+
assert_eq!(xs.rev_iter().size_hint(), (5, Some(5)));
2991+
assert_eq!(xs.mut_iter().size_hint(), (5, Some(5)));
2992+
assert_eq!(xs.mut_rev_iter().size_hint(), (5, Some(5)));
29932993
}
29942994

29952995
#[test]

src/libsyntax/opt_vec.rs

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -146,4 +146,12 @@ impl<'self, T> Iterator<&'self T> for OptVecIterator<'self, T> {
146146
None => None
147147
}
148148
}
149+
150+
#[inline]
151+
fn size_hint(&self) -> (uint, Option<uint>) {
152+
match self.iter {
153+
Some(ref x) => x.size_hint(),
154+
None => (0, Some(0))
155+
}
156+
}
149157
}

0 commit comments

Comments
 (0)