summary refs log tree commit diff
path: root/src/libstd
diff options
context:
space:
mode:
authorChase Southwood <chase.southwood@gmail.com>2014-12-13 12:36:05 -0600
committerChase Southwood <chase.southwood@gmail.com>2014-12-15 19:31:07 -0600
commit341cf405e5be56b9b1c8f3be6d0fe9a014eeff26 (patch)
treec051eed4bc7897cfc66885f272edfe90fce9fd22 /src/libstd
parent85fe141fb7c066e88a6872e74347c5f34d0223a7 (diff)
downloadrust-341cf405e5be56b9b1c8f3be6d0fe9a014eeff26.tar.gz
rust-341cf405e5be56b9b1c8f3be6d0fe9a014eeff26.zip
Use wrapper structs for `HashSet`'s iterators.
Using a type alias for iterator implementations is fragile since this
exposes the implementation to users of the iterator, and any changes
could break existing code.

This commit changes the iterators of `HashSet` to use
proper new types, rather than type aliases.  However, since it is
fair-game to treat a type-alias as the aliased type, this is a:

[breaking-change].
Diffstat (limited to 'src/libstd')
-rw-r--r--src/libstd/collections/hash/set.rs79
1 files changed, 59 insertions, 20 deletions
diff --git a/src/libstd/collections/hash/set.rs b/src/libstd/collections/hash/set.rs
index 3993a23140b..865d8840c52 100644
--- a/src/libstd/collections/hash/set.rs
+++ b/src/libstd/collections/hash/set.rs
@@ -17,8 +17,7 @@ use default::Default;
 use fmt::Show;
 use fmt;
 use hash::{Hash, Hasher, RandomSipHasher};
-use iter::{Iterator, IteratorExt, FromIterator, FilterMap, Chain, Repeat, Zip, Extend, repeat};
-use iter;
+use iter::{Iterator, IteratorExt, FromIterator, Map, FilterMap, Chain, Repeat, Zip, Extend, repeat};
 use option::Option::{Some, None, mod};
 use result::Result::{Ok, Err};
 
@@ -252,7 +251,7 @@ impl<T: Eq + Hash<S>, S, H: Hasher<S>> HashSet<T, H> {
     /// ```
     #[unstable = "matches collection reform specification, waiting for dust to settle"]
     pub fn iter<'a>(&'a self) -> SetItems<'a, T> {
-        self.map.keys()
+        SetItems { iter: self.map.keys() }
     }
 
     /// Creates a consuming iterator, that is, one that moves each value out
@@ -279,7 +278,7 @@ impl<T: Eq + Hash<S>, S, H: Hasher<S>> HashSet<T, H> {
     pub fn into_iter(self) -> SetMoveItems<T> {
         fn first<A, B>((a, _): (A, B)) -> A { a }
 
-        self.map.into_iter().map(first)
+        SetMoveItems { iter: self.map.into_iter().map(first) }
     }
 
     /// Visit the values representing the difference.
@@ -312,7 +311,7 @@ impl<T: Eq + Hash<S>, S, H: Hasher<S>> HashSet<T, H> {
             if !other.contains(elt) { Some(elt) } else { None }
         }
 
-        repeat(other).zip(self.iter()).filter_map(filter)
+        SetAlgebraItems { iter: repeat(other).zip(self.iter()).filter_map(filter) }
     }
 
     /// Visit the values representing the symmetric difference.
@@ -337,8 +336,8 @@ impl<T: Eq + Hash<S>, S, H: Hasher<S>> HashSet<T, H> {
     /// ```
     #[unstable = "matches collection reform specification, waiting for dust to settle"]
     pub fn symmetric_difference<'a>(&'a self, other: &'a HashSet<T, H>)
-        -> Chain<SetAlgebraItems<'a, T, H>, SetAlgebraItems<'a, T, H>> {
-        self.difference(other).chain(other.difference(self))
+        -> SymDifferenceItems<'a, T, H> {
+        SymDifferenceItems { iter: self.difference(other).chain(other.difference(self)) }
     }
 
     /// Visit the values representing the intersection.
@@ -366,7 +365,7 @@ impl<T: Eq + Hash<S>, S, H: Hasher<S>> HashSet<T, H> {
             if other.contains(elt) { Some(elt) } else { None }
         }
 
-        repeat(other).zip(self.iter()).filter_map(filter)
+        SetAlgebraItems { iter: repeat(other).zip(self.iter()).filter_map(filter) }
     }
 
     /// Visit the values representing the union.
@@ -387,9 +386,8 @@ impl<T: Eq + Hash<S>, S, H: Hasher<S>> HashSet<T, H> {
     /// assert_eq!(diff, [1i, 2, 3, 4].iter().map(|&x| x).collect());
     /// ```
     #[unstable = "matches collection reform specification, waiting for dust to settle"]
-    pub fn union<'a>(&'a self, other: &'a HashSet<T, H>)
-        -> Chain<SetItems<'a, T>, SetAlgebraItems<'a, T, H>> {
-        self.iter().chain(other.difference(self))
+    pub fn union<'a>(&'a self, other: &'a HashSet<T, H>) -> UnionItems<'a, T, H> {
+        UnionItems { iter: self.iter().chain(other.difference(self)) }
     }
 
     /// Return the number of elements in the set
@@ -617,20 +615,61 @@ impl<T: Eq + Hash<S>, S, H: Hasher<S> + Default> Default for HashSet<T, H> {
 }
 
 /// HashSet iterator
-pub type SetItems<'a, K> = Keys<'a, K, ()>;
+pub struct SetItems<'a, K: 'a> {
+    iter: Keys<'a, K, ()>
+}
 
 /// HashSet move iterator
-pub type SetMoveItems<K> = iter::Map<(K, ()), K, MoveEntries<K, ()>, fn((K, ())) -> K>;
+pub struct SetMoveItems<K> {
+    iter: Map<(K, ()), K, MoveEntries<K, ()>, fn((K, ())) -> K>
+}
 
 // `Repeat` is used to feed the filter closure an explicit capture
 // of a reference to the other set
-/// Set operations iterator
-pub type SetAlgebraItems<'a, T, H> = FilterMap<
-    (&'a HashSet<T, H>, &'a T),
-    &'a T,
-    Zip<Repeat<&'a HashSet<T, H>>, SetItems<'a, T>>,
-    for<'b> fn((&HashSet<T, H>, &'b T)) -> Option<&'b T>,
->;
+/// Set operations iterator, used directly for intersection and difference
+pub struct SetAlgebraItems<'a, T: 'a, H: 'a> {
+    iter: FilterMap<
+        (&'a HashSet<T, H>, &'a T),
+        &'a T,
+        Zip<Repeat<&'a HashSet<T, H>>, SetItems<'a, T>>,
+        for<'b> fn((&HashSet<T, H>, &'b T)) -> Option<&'b T>,
+    >
+}
+
+/// Symmetric difference iterator.
+pub struct SymDifferenceItems<'a, T: 'a, H: 'a> {
+    iter: Chain<SetAlgebraItems<'a, T, H>, SetAlgebraItems<'a, T, H>>
+}
+
+/// Set union iterator.
+pub struct UnionItems<'a, T: 'a, H: 'a> {
+    iter: Chain<SetItems<'a, T>, SetAlgebraItems<'a, T, H>>
+}
+
+impl<'a, K> Iterator<&'a K> for SetItems<'a, K> {
+    fn next(&mut self) -> Option<&'a K> { self.iter.next() }
+    fn size_hint(&self) -> (uint, Option<uint>) { self.iter.size_hint() }
+}
+
+impl<K> Iterator<K> for SetMoveItems<K> {
+    fn next(&mut self) -> Option<K> { self.iter.next() }
+    fn size_hint(&self) -> (uint, Option<uint>) { self.iter.size_hint() }
+}
+
+impl<'a, T, H> Iterator<&'a T> for SetAlgebraItems<'a, T, H> {
+    fn next(&mut self) -> Option<&'a T> { self.iter.next() }
+    fn size_hint(&self) -> (uint, Option<uint>) { self.iter.size_hint() }
+}
+
+impl<'a, T, H> Iterator<&'a T> for SymDifferenceItems<'a, T, H> {
+    fn next(&mut self) -> Option<&'a T> { self.iter.next() }
+    fn size_hint(&self) -> (uint, Option<uint>) { self.iter.size_hint() }
+}
+
+impl<'a, T, H> Iterator<&'a T> for UnionItems<'a, T, H> {
+    fn next(&mut self) -> Option<&'a T> { self.iter.next() }
+    fn size_hint(&self) -> (uint, Option<uint>) { self.iter.size_hint() }
+}
 
 #[cfg(test)]
 mod test_set {