Use wrapper structs for `HashMap`'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 keys and values iterators of `HashMap` 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].
This commit is contained in:
Chase Southwood 2014-12-12 01:02:19 -06:00
parent a81c3ab468
commit 85fe141fb7
2 changed files with 31 additions and 38 deletions

View File

@ -20,7 +20,7 @@ use cmp::{max, Eq, Equiv, PartialEq};
use default::Default;
use fmt::{mod, Show};
use hash::{Hash, Hasher, RandomSipHasher};
use iter::{mod, Iterator, IteratorExt, FromIterator, Extend};
use iter::{mod, Iterator, IteratorExt, FromIterator, Extend, Map};
use kinds::Sized;
use mem::{mod, replace};
use num::{Int, UnsignedInt};
@ -859,7 +859,7 @@ impl<K: Eq + Hash<S>, V, S, H: Hasher<S>> HashMap<K, V, H> {
pub fn keys(&self) -> Keys<K, V> {
fn first<A, B>((a, _): (A, B)) -> A { a }
self.iter().map(first)
Keys { inner: self.iter().map(first) }
}
/// An iterator visiting all values in arbitrary order.
@ -883,7 +883,7 @@ impl<K: Eq + Hash<S>, V, S, H: Hasher<S>> HashMap<K, V, H> {
pub fn values(&self) -> Values<K, V> {
fn second<A, B>((_, b): (A, B)) -> B { b }
self.iter().map(second)
Values { inner: self.iter().map(second) }
}
/// An iterator visiting all key-value pairs in arbitrary order.
@ -1335,6 +1335,16 @@ pub struct MoveEntries<K, V> {
>
}
/// HashMap keys iterator
pub struct Keys<'a, K: 'a, V: 'a> {
inner: Map<(&'a K, &'a V), &'a K, Entries<'a, K, V>, fn((&'a K, &'a V)) -> &'a K>
}
/// HashMap values iterator
pub struct Values<'a, K: 'a, V: 'a> {
inner: Map<(&'a K, &'a V), &'a V, Entries<'a, K, V>, fn((&'a K, &'a V)) -> &'a V>
}
/// A view into a single occupied location in a HashMap
pub struct OccupiedEntry<'a, K:'a, V:'a> {
elem: FullBucket<K, V, &'a mut RawTable<K, V>>,
@ -1365,36 +1375,28 @@ enum VacantEntryState<K, V, M> {
}
impl<'a, K, V> Iterator<(&'a K, &'a V)> for Entries<'a, K, V> {
#[inline]
fn next(&mut self) -> Option<(&'a K, &'a V)> {
self.inner.next()
}
#[inline]
fn size_hint(&self) -> (uint, Option<uint>) {
self.inner.size_hint()
}
#[inline] fn next(&mut self) -> Option<(&'a K, &'a V)> { self.inner.next() }
#[inline] fn size_hint(&self) -> (uint, Option<uint>) { self.inner.size_hint() }
}
impl<'a, K, V> Iterator<(&'a K, &'a mut V)> for MutEntries<'a, K, V> {
#[inline]
fn next(&mut self) -> Option<(&'a K, &'a mut V)> {
self.inner.next()
}
#[inline]
fn size_hint(&self) -> (uint, Option<uint>) {
self.inner.size_hint()
}
#[inline] fn next(&mut self) -> Option<(&'a K, &'a mut V)> { self.inner.next() }
#[inline] fn size_hint(&self) -> (uint, Option<uint>) { self.inner.size_hint() }
}
impl<K, V> Iterator<(K, V)> for MoveEntries<K, V> {
#[inline]
fn next(&mut self) -> Option<(K, V)> {
self.inner.next()
}
#[inline]
fn size_hint(&self) -> (uint, Option<uint>) {
self.inner.size_hint()
}
#[inline] fn next(&mut self) -> Option<(K, V)> { self.inner.next() }
#[inline] fn size_hint(&self) -> (uint, Option<uint>) { self.inner.size_hint() }
}
impl<'a, K, V> Iterator<&'a K> for Keys<'a, K, V> {
#[inline] fn next(&mut self) -> Option<(&'a K)> { self.inner.next() }
#[inline] fn size_hint(&self) -> (uint, Option<uint>) { self.inner.size_hint() }
}
impl<'a, K, V> Iterator<&'a V> for Values<'a, K, V> {
#[inline] fn next(&mut self) -> Option<(&'a V)> { self.inner.next() }
#[inline] fn size_hint(&self) -> (uint, Option<uint>) { self.inner.size_hint() }
}
impl<'a, K, V> OccupiedEntry<'a, K, V> {
@ -1448,14 +1450,6 @@ impl<'a, K, V> VacantEntry<'a, K, V> {
}
}
/// HashMap keys iterator
pub type Keys<'a, K, V> =
iter::Map<(&'a K, &'a V), &'a K, Entries<'a, K, V>, fn((&'a K, &'a V)) -> &'a K>;
/// HashMap values iterator
pub type Values<'a, K, V> =
iter::Map<(&'a K, &'a V), &'a V, Entries<'a, K, V>, fn((&'a K, &'a V)) -> &'a V>;
impl<K: Eq + Hash<S>, V, S, H: Hasher<S> + Default> FromIterator<(K, V)> for HashMap<K, V, H> {
fn from_iter<T: Iterator<(K, V)>>(iter: T) -> HashMap<K, V, H> {
let (lower, _) = iter.size_hint();

View File

@ -22,7 +22,7 @@ use iter;
use option::Option::{Some, None, mod};
use result::Result::{Ok, Err};
use super::map::{HashMap, Entries, MoveEntries, INITIAL_CAPACITY};
use super::map::{HashMap, MoveEntries, Keys, INITIAL_CAPACITY};
// FIXME(conventions): implement BitOr, BitAnd, BitXor, and Sub
@ -617,8 +617,7 @@ impl<T: Eq + Hash<S>, S, H: Hasher<S> + Default> Default for HashSet<T, H> {
}
/// HashSet iterator
pub type SetItems<'a, K> =
iter::Map<(&'a K, &'a ()), &'a K, Entries<'a, K, ()>, fn((&'a K, &'a ())) -> &'a K>;
pub type SetItems<'a, K> = Keys<'a, K, ()>;
/// HashSet move iterator
pub type SetMoveItems<K> = iter::Map<(K, ()), K, MoveEntries<K, ()>, fn((K, ())) -> K>;