Skip to content

Commit 85fe141

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

File tree

2 files changed

+31
-38
lines changed

2 files changed

+31
-38
lines changed

src/libstd/collections/hash/map.rs

+29-35
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@ use cmp::{max, Eq, Equiv, PartialEq};
2020
use default::Default;
2121
use fmt::{mod, Show};
2222
use hash::{Hash, Hasher, RandomSipHasher};
23-
use iter::{mod, Iterator, IteratorExt, FromIterator, Extend};
23+
use iter::{mod, Iterator, IteratorExt, FromIterator, Extend, Map};
2424
use kinds::Sized;
2525
use mem::{mod, replace};
2626
use num::{Int, UnsignedInt};
@@ -859,7 +859,7 @@ impl<K: Eq + Hash<S>, V, S, H: Hasher<S>> HashMap<K, V, H> {
859859
pub fn keys(&self) -> Keys<K, V> {
860860
fn first<A, B>((a, _): (A, B)) -> A { a }
861861

862-
self.iter().map(first)
862+
Keys { inner: self.iter().map(first) }
863863
}
864864

865865
/// 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> {
883883
pub fn values(&self) -> Values<K, V> {
884884
fn second<A, B>((_, b): (A, B)) -> B { b }
885885

886-
self.iter().map(second)
886+
Values { inner: self.iter().map(second) }
887887
}
888888

889889
/// An iterator visiting all key-value pairs in arbitrary order.
@@ -1335,6 +1335,16 @@ pub struct MoveEntries<K, V> {
13351335
>
13361336
}
13371337

1338+
/// HashMap keys iterator
1339+
pub struct Keys<'a, K: 'a, V: 'a> {
1340+
inner: Map<(&'a K, &'a V), &'a K, Entries<'a, K, V>, fn((&'a K, &'a V)) -> &'a K>
1341+
}
1342+
1343+
/// HashMap values iterator
1344+
pub struct Values<'a, K: 'a, V: 'a> {
1345+
inner: Map<(&'a K, &'a V), &'a V, Entries<'a, K, V>, fn((&'a K, &'a V)) -> &'a V>
1346+
}
1347+
13381348
/// A view into a single occupied location in a HashMap
13391349
pub struct OccupiedEntry<'a, K:'a, V:'a> {
13401350
elem: FullBucket<K, V, &'a mut RawTable<K, V>>,
@@ -1365,36 +1375,28 @@ enum VacantEntryState<K, V, M> {
13651375
}
13661376

13671377
impl<'a, K, V> Iterator<(&'a K, &'a V)> for Entries<'a, K, V> {
1368-
#[inline]
1369-
fn next(&mut self) -> Option<(&'a K, &'a V)> {
1370-
self.inner.next()
1371-
}
1372-
#[inline]
1373-
fn size_hint(&self) -> (uint, Option<uint>) {
1374-
self.inner.size_hint()
1375-
}
1378+
#[inline] fn next(&mut self) -> Option<(&'a K, &'a V)> { self.inner.next() }
1379+
#[inline] fn size_hint(&self) -> (uint, Option<uint>) { self.inner.size_hint() }
13761380
}
13771381

13781382
impl<'a, K, V> Iterator<(&'a K, &'a mut V)> for MutEntries<'a, K, V> {
1379-
#[inline]
1380-
fn next(&mut self) -> Option<(&'a K, &'a mut V)> {
1381-
self.inner.next()
1382-
}
1383-
#[inline]
1384-
fn size_hint(&self) -> (uint, Option<uint>) {
1385-
self.inner.size_hint()
1386-
}
1383+
#[inline] fn next(&mut self) -> Option<(&'a K, &'a mut V)> { self.inner.next() }
1384+
#[inline] fn size_hint(&self) -> (uint, Option<uint>) { self.inner.size_hint() }
13871385
}
13881386

13891387
impl<K, V> Iterator<(K, V)> for MoveEntries<K, V> {
1390-
#[inline]
1391-
fn next(&mut self) -> Option<(K, V)> {
1392-
self.inner.next()
1393-
}
1394-
#[inline]
1395-
fn size_hint(&self) -> (uint, Option<uint>) {
1396-
self.inner.size_hint()
1397-
}
1388+
#[inline] fn next(&mut self) -> Option<(K, V)> { self.inner.next() }
1389+
#[inline] fn size_hint(&self) -> (uint, Option<uint>) { self.inner.size_hint() }
1390+
}
1391+
1392+
impl<'a, K, V> Iterator<&'a K> for Keys<'a, K, V> {
1393+
#[inline] fn next(&mut self) -> Option<(&'a K)> { self.inner.next() }
1394+
#[inline] fn size_hint(&self) -> (uint, Option<uint>) { self.inner.size_hint() }
1395+
}
1396+
1397+
impl<'a, K, V> Iterator<&'a V> for Values<'a, K, V> {
1398+
#[inline] fn next(&mut self) -> Option<(&'a V)> { self.inner.next() }
1399+
#[inline] fn size_hint(&self) -> (uint, Option<uint>) { self.inner.size_hint() }
13981400
}
13991401

14001402
impl<'a, K, V> OccupiedEntry<'a, K, V> {
@@ -1448,14 +1450,6 @@ impl<'a, K, V> VacantEntry<'a, K, V> {
14481450
}
14491451
}
14501452

1451-
/// HashMap keys iterator
1452-
pub type Keys<'a, K, V> =
1453-
iter::Map<(&'a K, &'a V), &'a K, Entries<'a, K, V>, fn((&'a K, &'a V)) -> &'a K>;
1454-
1455-
/// HashMap values iterator
1456-
pub type Values<'a, K, V> =
1457-
iter::Map<(&'a K, &'a V), &'a V, Entries<'a, K, V>, fn((&'a K, &'a V)) -> &'a V>;
1458-
14591453
impl<K: Eq + Hash<S>, V, S, H: Hasher<S> + Default> FromIterator<(K, V)> for HashMap<K, V, H> {
14601454
fn from_iter<T: Iterator<(K, V)>>(iter: T) -> HashMap<K, V, H> {
14611455
let (lower, _) = iter.size_hint();

src/libstd/collections/hash/set.rs

+2-3
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@ use iter;
2222
use option::Option::{Some, None, mod};
2323
use result::Result::{Ok, Err};
2424

25-
use super::map::{HashMap, Entries, MoveEntries, INITIAL_CAPACITY};
25+
use super::map::{HashMap, MoveEntries, Keys, INITIAL_CAPACITY};
2626

2727
// FIXME(conventions): implement BitOr, BitAnd, BitXor, and Sub
2828

@@ -617,8 +617,7 @@ impl<T: Eq + Hash<S>, S, H: Hasher<S> + Default> Default for HashSet<T, H> {
617617
}
618618

619619
/// HashSet iterator
620-
pub type SetItems<'a, K> =
621-
iter::Map<(&'a K, &'a ()), &'a K, Entries<'a, K, ()>, fn((&'a K, &'a ())) -> &'a K>;
620+
pub type SetItems<'a, K> = Keys<'a, K, ()>;
622621

623622
/// HashSet move iterator
624623
pub type SetMoveItems<K> = iter::Map<(K, ()), K, MoveEntries<K, ()>, fn((K, ())) -> K>;

0 commit comments

Comments
 (0)