Skip to content

Commit 341cf40

Browse files
committed
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].
1 parent 85fe141 commit 341cf40

File tree

1 file changed

+59
-20
lines changed
  • src/libstd/collections/hash

1 file changed

+59
-20
lines changed

src/libstd/collections/hash/set.rs

+59-20
Original file line numberDiff line numberDiff line change
@@ -17,8 +17,7 @@ use default::Default;
1717
use fmt::Show;
1818
use fmt;
1919
use hash::{Hash, Hasher, RandomSipHasher};
20-
use iter::{Iterator, IteratorExt, FromIterator, FilterMap, Chain, Repeat, Zip, Extend, repeat};
21-
use iter;
20+
use iter::{Iterator, IteratorExt, FromIterator, Map, FilterMap, Chain, Repeat, Zip, Extend, repeat};
2221
use option::Option::{Some, None, mod};
2322
use result::Result::{Ok, Err};
2423

@@ -252,7 +251,7 @@ impl<T: Eq + Hash<S>, S, H: Hasher<S>> HashSet<T, H> {
252251
/// ```
253252
#[unstable = "matches collection reform specification, waiting for dust to settle"]
254253
pub fn iter<'a>(&'a self) -> SetItems<'a, T> {
255-
self.map.keys()
254+
SetItems { iter: self.map.keys() }
256255
}
257256

258257
/// 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> {
279278
pub fn into_iter(self) -> SetMoveItems<T> {
280279
fn first<A, B>((a, _): (A, B)) -> A { a }
281280

282-
self.map.into_iter().map(first)
281+
SetMoveItems { iter: self.map.into_iter().map(first) }
283282
}
284283

285284
/// Visit the values representing the difference.
@@ -312,7 +311,7 @@ impl<T: Eq + Hash<S>, S, H: Hasher<S>> HashSet<T, H> {
312311
if !other.contains(elt) { Some(elt) } else { None }
313312
}
314313

315-
repeat(other).zip(self.iter()).filter_map(filter)
314+
SetAlgebraItems { iter: repeat(other).zip(self.iter()).filter_map(filter) }
316315
}
317316

318317
/// Visit the values representing the symmetric difference.
@@ -337,8 +336,8 @@ impl<T: Eq + Hash<S>, S, H: Hasher<S>> HashSet<T, H> {
337336
/// ```
338337
#[unstable = "matches collection reform specification, waiting for dust to settle"]
339338
pub fn symmetric_difference<'a>(&'a self, other: &'a HashSet<T, H>)
340-
-> Chain<SetAlgebraItems<'a, T, H>, SetAlgebraItems<'a, T, H>> {
341-
self.difference(other).chain(other.difference(self))
339+
-> SymDifferenceItems<'a, T, H> {
340+
SymDifferenceItems { iter: self.difference(other).chain(other.difference(self)) }
342341
}
343342

344343
/// Visit the values representing the intersection.
@@ -366,7 +365,7 @@ impl<T: Eq + Hash<S>, S, H: Hasher<S>> HashSet<T, H> {
366365
if other.contains(elt) { Some(elt) } else { None }
367366
}
368367

369-
repeat(other).zip(self.iter()).filter_map(filter)
368+
SetAlgebraItems { iter: repeat(other).zip(self.iter()).filter_map(filter) }
370369
}
371370

372371
/// Visit the values representing the union.
@@ -387,9 +386,8 @@ impl<T: Eq + Hash<S>, S, H: Hasher<S>> HashSet<T, H> {
387386
/// assert_eq!(diff, [1i, 2, 3, 4].iter().map(|&x| x).collect());
388387
/// ```
389388
#[unstable = "matches collection reform specification, waiting for dust to settle"]
390-
pub fn union<'a>(&'a self, other: &'a HashSet<T, H>)
391-
-> Chain<SetItems<'a, T>, SetAlgebraItems<'a, T, H>> {
392-
self.iter().chain(other.difference(self))
389+
pub fn union<'a>(&'a self, other: &'a HashSet<T, H>) -> UnionItems<'a, T, H> {
390+
UnionItems { iter: self.iter().chain(other.difference(self)) }
393391
}
394392

395393
/// 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> {
617615
}
618616

619617
/// HashSet iterator
620-
pub type SetItems<'a, K> = Keys<'a, K, ()>;
618+
pub struct SetItems<'a, K: 'a> {
619+
iter: Keys<'a, K, ()>
620+
}
621621

622622
/// HashSet move iterator
623-
pub type SetMoveItems<K> = iter::Map<(K, ()), K, MoveEntries<K, ()>, fn((K, ())) -> K>;
623+
pub struct SetMoveItems<K> {
624+
iter: Map<(K, ()), K, MoveEntries<K, ()>, fn((K, ())) -> K>
625+
}
624626

625627
// `Repeat` is used to feed the filter closure an explicit capture
626628
// of a reference to the other set
627-
/// Set operations iterator
628-
pub type SetAlgebraItems<'a, T, H> = FilterMap<
629-
(&'a HashSet<T, H>, &'a T),
630-
&'a T,
631-
Zip<Repeat<&'a HashSet<T, H>>, SetItems<'a, T>>,
632-
for<'b> fn((&HashSet<T, H>, &'b T)) -> Option<&'b T>,
633-
>;
629+
/// Set operations iterator, used directly for intersection and difference
630+
pub struct SetAlgebraItems<'a, T: 'a, H: 'a> {
631+
iter: FilterMap<
632+
(&'a HashSet<T, H>, &'a T),
633+
&'a T,
634+
Zip<Repeat<&'a HashSet<T, H>>, SetItems<'a, T>>,
635+
for<'b> fn((&HashSet<T, H>, &'b T)) -> Option<&'b T>,
636+
>
637+
}
638+
639+
/// Symmetric difference iterator.
640+
pub struct SymDifferenceItems<'a, T: 'a, H: 'a> {
641+
iter: Chain<SetAlgebraItems<'a, T, H>, SetAlgebraItems<'a, T, H>>
642+
}
643+
644+
/// Set union iterator.
645+
pub struct UnionItems<'a, T: 'a, H: 'a> {
646+
iter: Chain<SetItems<'a, T>, SetAlgebraItems<'a, T, H>>
647+
}
648+
649+
impl<'a, K> Iterator<&'a K> for SetItems<'a, K> {
650+
fn next(&mut self) -> Option<&'a K> { self.iter.next() }
651+
fn size_hint(&self) -> (uint, Option<uint>) { self.iter.size_hint() }
652+
}
653+
654+
impl<K> Iterator<K> for SetMoveItems<K> {
655+
fn next(&mut self) -> Option<K> { self.iter.next() }
656+
fn size_hint(&self) -> (uint, Option<uint>) { self.iter.size_hint() }
657+
}
658+
659+
impl<'a, T, H> Iterator<&'a T> for SetAlgebraItems<'a, T, H> {
660+
fn next(&mut self) -> Option<&'a T> { self.iter.next() }
661+
fn size_hint(&self) -> (uint, Option<uint>) { self.iter.size_hint() }
662+
}
663+
664+
impl<'a, T, H> Iterator<&'a T> for SymDifferenceItems<'a, T, H> {
665+
fn next(&mut self) -> Option<&'a T> { self.iter.next() }
666+
fn size_hint(&self) -> (uint, Option<uint>) { self.iter.size_hint() }
667+
}
668+
669+
impl<'a, T, H> Iterator<&'a T> for UnionItems<'a, T, H> {
670+
fn next(&mut self) -> Option<&'a T> { self.iter.next() }
671+
fn size_hint(&self) -> (uint, Option<uint>) { self.iter.size_hint() }
672+
}
634673

635674
#[cfg(test)]
636675
mod test_set {

0 commit comments

Comments
 (0)