Skip to content

Commit 35040df

Browse files
author
blake2-ppc
committed
std::iterator: Use ExactSize, inheriting DoubleEndedIterator
Address discussion with acrichto; inherit DoubleEndedIterator so that `.rposition()` can be a default method, and that the nische of the trait is clear. Use assertions when using `.size_hint()` in reverse enumerate and `.rposition()`
1 parent 04845f0 commit 35040df

File tree

4 files changed

+43
-52
lines changed

4 files changed

+43
-52
lines changed

src/libstd/iterator.rs

Lines changed: 39 additions & 48 deletions
Original file line numberDiff line numberDiff line change
@@ -604,26 +604,42 @@ impl<'self, A, T: DoubleEndedIterator<&'self mut A>> MutableDoubleEndedIterator
604604
}
605605
}
606606

607-
/// A double-ended iterator with known size
608-
pub trait ExactSizeDoubleEndedIterator<A> {
607+
608+
/// An object implementing random access indexing by `uint`
609+
///
610+
/// A `RandomAccessIterator` should be either infinite or a `DoubleEndedIterator`.
611+
pub trait RandomAccessIterator<A>: Iterator<A> {
612+
/// Return the number of indexable elements. At most `std::uint::max_value`
613+
/// elements are indexable, even if the iterator represents a longer range.
614+
fn indexable(&self) -> uint;
615+
616+
/// Return an element at an index
617+
fn idx(&self, index: uint) -> Option<A>;
618+
}
619+
620+
/// An iterator that knows its exact length
621+
///
622+
/// This trait is a helper for iterators like the vector iterator, so that
623+
/// it can support double-ended enumeration.
624+
///
625+
/// `Iterator::size_hint` *must* return the exact size of the iterator.
626+
/// Note that the size must fit in `uint`.
627+
pub trait ExactSize<A> : DoubleEndedIterator<A> {
609628
/// Return the index of the last element satisfying the specified predicate
610629
///
611630
/// If no element matches, None is returned.
612631
#[inline]
613-
fn rposition(&mut self, predicate: &fn(A) -> bool) -> Option<uint>;
614-
}
615-
616-
impl<A, T: DoubleEndedIterator<A> + ExactSizeHint> ExactSizeDoubleEndedIterator<A> for T {
617632
fn rposition(&mut self, predicate: &fn(A) -> bool) -> Option<uint> {
618-
let (size, _) = self.size_hint();
619-
let mut i = size;
633+
let (lower, upper) = self.size_hint();
634+
assert!(upper == Some(lower));
635+
let mut i = lower;
620636
loop {
621637
match self.next_back() {
622638
None => break,
623639
Some(x) => {
624640
i = match i.checked_sub(&1) {
625641
Some(x) => x,
626-
None => fail!("rposition: incorrect ExactSizeHint")
642+
None => fail!("rposition: incorrect ExactSize")
627643
};
628644
if predicate(x) {
629645
return Some(i)
@@ -635,37 +651,13 @@ impl<A, T: DoubleEndedIterator<A> + ExactSizeHint> ExactSizeDoubleEndedIterator<
635651
}
636652
}
637653

638-
/// An object implementing random access indexing by `uint`
639-
///
640-
/// A `RandomAccessIterator` should be either infinite or a `DoubleEndedIterator`.
641-
pub trait RandomAccessIterator<A>: Iterator<A> {
642-
/// Return the number of indexable elements. At most `std::uint::max_value`
643-
/// elements are indexable, even if the iterator represents a longer range.
644-
fn indexable(&self) -> uint;
645-
646-
/// Return an element at an index
647-
fn idx(&self, index: uint) -> Option<A>;
648-
}
649-
650-
/// An iterator that knows its exact length
651-
///
652-
/// This trait is a helper for iterators like the vector iterator, so that
653-
/// it can support double-ended enumeration.
654-
///
655-
/// `Iterator::size_hint` *must* return the exact size of the iterator.
656-
/// Note that the size must fit in `uint`.
657-
pub trait ExactSizeHint {}
658-
659654
// All adaptors that preserve the size of the wrapped iterator are fine
660655
// Adaptors that may overflow in `size_hint` are not, i.e. `Chain`.
661-
impl<T: ExactSizeHint> ExactSizeHint for Enumerate<T> {}
662-
impl<'self, A, T: ExactSizeHint> ExactSizeHint for Inspect<'self, A, T> {}
663-
impl<T: ExactSizeHint> ExactSizeHint for Invert<T> {}
664-
impl<'self, A, B, T: ExactSizeHint> ExactSizeHint for Map<'self, A, B, T> {}
665-
impl<A, T: ExactSizeHint> ExactSizeHint for Peekable<A, T> {}
666-
impl<T: ExactSizeHint> ExactSizeHint for Skip<T> {}
667-
impl<T: ExactSizeHint> ExactSizeHint for Take<T> {}
668-
impl<T: ExactSizeHint, U: ExactSizeHint> ExactSizeHint for Zip<T, U> {}
656+
impl<A, T: ExactSize<A>> ExactSize<(uint, A)> for Enumerate<T> {}
657+
impl<'self, A, T: ExactSize<A>> ExactSize<A> for Inspect<'self, A, T> {}
658+
impl<A, T: ExactSize<A>> ExactSize<A> for Invert<T> {}
659+
impl<'self, A, B, T: ExactSize<A>> ExactSize<B> for Map<'self, A, B, T> {}
660+
impl<A, B, T: ExactSize<A>, U: ExactSize<B>> ExactSize<(A, B)> for Zip<T, U> {}
669661

670662
/// An double-ended iterator with the direction inverted
671663
#[deriving(Clone)]
@@ -967,14 +959,14 @@ impl<A, B, T: Iterator<A>, U: Iterator<B>> Iterator<(A, B)> for Zip<T, U> {
967959
}
968960
}
969961

970-
impl<A, B,
971-
T: DoubleEndedIterator<A> + ExactSizeHint,
972-
U: DoubleEndedIterator<B> + ExactSizeHint> DoubleEndedIterator<(A, B)>
962+
impl<A, B, T: ExactSize<A>, U: ExactSize<B>> DoubleEndedIterator<(A, B)>
973963
for Zip<T, U> {
974964
#[inline]
975965
fn next_back(&mut self) -> Option<(A, B)> {
976-
let (a_sz, _) = self.a.size_hint();
977-
let (b_sz, _) = self.b.size_hint();
966+
let (a_sz, a_upper) = self.a.size_hint();
967+
let (b_sz, b_upper) = self.b.size_hint();
968+
assert!(a_upper == Some(a_sz));
969+
assert!(b_upper == Some(b_sz));
978970
if a_sz < b_sz {
979971
for _ in range(0, b_sz - a_sz) { self.b.next_back(); }
980972
} else if a_sz > b_sz {
@@ -1168,15 +1160,14 @@ impl<A, T: Iterator<A>> Iterator<(uint, A)> for Enumerate<T> {
11681160
}
11691161
}
11701162

1171-
impl<A, T: DoubleEndedIterator<A> + ExactSizeHint> DoubleEndedIterator<(uint, A)>
1172-
for Enumerate<T> {
1163+
impl<A, T: ExactSize<A>> DoubleEndedIterator<(uint, A)> for Enumerate<T> {
11731164
#[inline]
11741165
fn next_back(&mut self) -> Option<(uint, A)> {
11751166
match self.iter.next_back() {
11761167
Some(a) => {
1177-
let (len, _) = self.iter.size_hint();
1178-
let ret = Some((self.count + len, a));
1179-
ret
1168+
let (lower, upper) = self.iter.size_hint();
1169+
assert!(upper == Some(lower));
1170+
Some((self.count + lower, a))
11801171
}
11811172
_ => None
11821173
}

src/libstd/prelude.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -52,7 +52,7 @@ pub use hash::Hash;
5252
pub use num::Times;
5353
pub use iterator::{FromIterator, Extendable};
5454
pub use iterator::{Iterator, DoubleEndedIterator, RandomAccessIterator, ClonableIterator};
55-
pub use iterator::{OrdIterator, MutableDoubleEndedIterator, ExactSizeDoubleEndedIterator};
55+
pub use iterator::{OrdIterator, MutableDoubleEndedIterator, ExactSize};
5656
pub use num::{Num, NumCast, CheckedAdd, CheckedSub, CheckedMul};
5757
pub use num::{Orderable, Signed, Unsigned, Round};
5858
pub use num::{Algebraic, Trigonometric, Exponential, Hyperbolic};

src/libstd/str.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@ use container::{Container, Mutable};
2424
use num::Times;
2525
use iterator::{Iterator, FromIterator, Extendable};
2626
use iterator::{Filter, AdditiveIterator, Map};
27-
use iterator::{Invert, DoubleEndedIterator, ExactSizeDoubleEndedIterator};
27+
use iterator::{Invert, DoubleEndedIterator, ExactSize};
2828
use libc;
2929
use num::{Saturating};
3030
use option::{None, Option, Some};

src/libstd/vec.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2303,8 +2303,8 @@ iterator!{impl VecIterator -> &'self T}
23032303
double_ended_iterator!{impl VecIterator -> &'self T}
23042304
pub type RevIterator<'self, T> = Invert<VecIterator<'self, T>>;
23052305

2306-
impl<'self, T> ExactSizeHint for VecIterator<'self, T> {}
2307-
impl<'self, T> ExactSizeHint for VecMutIterator<'self, T> {}
2306+
impl<'self, T> ExactSize<&'self T> for VecIterator<'self, T> {}
2307+
impl<'self, T> ExactSize<&'self mut T> for VecMutIterator<'self, T> {}
23082308

23092309
impl<'self, T> Clone for VecIterator<'self, T> {
23102310
fn clone(&self) -> VecIterator<'self, T> { *self }

0 commit comments

Comments
 (0)