rollup merge of #20653: alexcrichton/entry-unstable

There's been some debate over the precise form that these APIs should take, and
they've undergone some changes recently, so these APIs are going to be left
unstable for now to be fleshed out during the next release cycle.
This commit is contained in:
Alex Crichton 2015-01-06 15:29:18 -08:00
commit e3f047c8c5
18 changed files with 77 additions and 90 deletions

View File

@ -19,7 +19,7 @@ pub use self::Entry::*;
use core::prelude::*;
use core::borrow::{BorrowFrom, ToOwned};
use core::borrow::BorrowFrom;
use core::cmp::Ordering;
use core::default::Default;
use core::fmt::Show;
@ -128,24 +128,24 @@ pub struct Values<'a, K: 'a, V: 'a> {
inner: Map<(&'a K, &'a V), &'a V, Iter<'a, K, V>, fn((&'a K, &'a V)) -> &'a V>
}
#[stable]
/// A view into a single entry in a map, which may either be vacant or occupied.
pub enum Entry<'a, Q: ?Sized +'a, K:'a, V:'a> {
#[unstable = "precise API still under development"]
pub enum Entry<'a, K:'a, V:'a> {
/// A vacant Entry
Vacant(VacantEntry<'a, Q, K, V>),
Vacant(VacantEntry<'a, K, V>),
/// An occupied Entry
Occupied(OccupiedEntry<'a, K, V>),
}
#[stable]
/// A vacant Entry.
pub struct VacantEntry<'a, Q: ?Sized +'a, K:'a, V:'a> {
key: &'a Q,
#[unstable = "precise API still under development"]
pub struct VacantEntry<'a, K:'a, V:'a> {
key: K,
stack: stack::SearchStack<'a, K, V, node::handle::Edge, node::handle::Leaf>,
}
#[stable]
/// An occupied Entry.
#[unstable = "precise API still under development"]
pub struct OccupiedEntry<'a, K:'a, V:'a> {
stack: stack::SearchStack<'a, K, V, node::handle::KV, node::handle::LeafOrInternal>,
}
@ -1111,10 +1111,10 @@ impl<'a, K, V> DoubleEndedIterator for Values<'a, K, V> {
#[stable]
impl<'a, K, V> ExactSizeIterator for Values<'a, K, V> {}
impl<'a, Q: ?Sized, K: Ord, V> Entry<'a, Q, K, V> {
impl<'a, K: Ord, V> Entry<'a, K, V> {
#[unstable = "matches collection reform v2 specification, waiting for dust to settle"]
/// Returns a mutable reference to the entry if occupied, or the VacantEntry if vacant
pub fn get(self) -> Result<&'a mut V, VacantEntry<'a, Q, K, V>> {
pub fn get(self) -> Result<&'a mut V, VacantEntry<'a, K, V>> {
match self {
Occupied(entry) => Ok(entry.into_mut()),
Vacant(entry) => Err(entry),
@ -1122,44 +1122,44 @@ impl<'a, Q: ?Sized, K: Ord, V> Entry<'a, Q, K, V> {
}
}
impl<'a, Q: ?Sized + ToOwned<K>, K: Ord, V> VacantEntry<'a, Q, K, V> {
#[stable]
impl<'a, K: Ord, V> VacantEntry<'a, K, V> {
/// Sets the value of the entry with the VacantEntry's key,
/// and returns a mutable reference to it.
#[unstable = "matches collection reform v2 specification, waiting for dust to settle"]
pub fn insert(self, value: V) -> &'a mut V {
self.stack.insert(self.key.to_owned(), value)
self.stack.insert(self.key, value)
}
}
impl<'a, K: Ord, V> OccupiedEntry<'a, K, V> {
#[stable]
/// Gets a reference to the value in the entry.
#[unstable = "matches collection reform v2 specification, waiting for dust to settle"]
pub fn get(&self) -> &V {
self.stack.peek()
}
#[stable]
/// Gets a mutable reference to the value in the entry.
#[unstable = "matches collection reform v2 specification, waiting for dust to settle"]
pub fn get_mut(&mut self) -> &mut V {
self.stack.peek_mut()
}
#[stable]
/// Converts the entry into a mutable reference to its value.
#[unstable = "matches collection reform v2 specification, waiting for dust to settle"]
pub fn into_mut(self) -> &'a mut V {
self.stack.into_top()
}
#[stable]
/// Sets the value of the entry with the OccupiedEntry's key,
/// and returns the entry's old value.
#[unstable = "matches collection reform v2 specification, waiting for dust to settle"]
pub fn insert(&mut self, mut value: V) -> V {
mem::swap(self.stack.peek_mut(), &mut value);
value
}
#[stable]
/// Takes the value of the entry out of the map, and returns it.
#[unstable = "matches collection reform v2 specification, waiting for dust to settle"]
pub fn remove(self) -> V {
self.stack.remove()
}
@ -1361,15 +1361,13 @@ impl<K: Ord, V> BTreeMap<K, V> {
/// assert_eq!(count["a"], 3u);
/// ```
/// The key must have the same ordering before or after `.to_owned()` is called.
#[stable]
pub fn entry<'a, Q: ?Sized>(&'a mut self, mut key: &'a Q) -> Entry<'a, Q, K, V>
where Q: Ord + ToOwned<K>
{
#[unstable = "precise API still under development"]
pub fn entry<'a>(&'a mut self, mut key: K) -> Entry<'a, K, V> {
// same basic logic of `swap` and `pop`, blended together
let mut stack = stack::PartialSearchStack::new(self);
loop {
let result = stack.with(move |pusher, node| {
return match Node::search(node, key) {
return match Node::search(node, &key) {
Found(handle) => {
// Perfect match
Finished(Occupied(OccupiedEntry {
@ -1412,7 +1410,7 @@ impl<K: Ord, V> BTreeMap<K, V> {
#[cfg(test)]
mod test {
use prelude::*;
use std::borrow::{ToOwned, BorrowFrom};
use std::borrow::BorrowFrom;
use super::{BTreeMap, Occupied, Vacant};
@ -1562,7 +1560,7 @@ mod test {
let mut map: BTreeMap<int, int> = xs.iter().map(|&x| x).collect();
// Existing key (insert)
match map.entry(&1) {
match map.entry(1) {
Vacant(_) => unreachable!(),
Occupied(mut view) => {
assert_eq!(view.get(), &10);
@ -1574,7 +1572,7 @@ mod test {
// Existing key (update)
match map.entry(&2) {
match map.entry(2) {
Vacant(_) => unreachable!(),
Occupied(mut view) => {
let v = view.get_mut();
@ -1585,7 +1583,7 @@ mod test {
assert_eq!(map.len(), 6);
// Existing key (take)
match map.entry(&3) {
match map.entry(3) {
Vacant(_) => unreachable!(),
Occupied(view) => {
assert_eq!(view.remove(), 30);
@ -1596,7 +1594,7 @@ mod test {
// Inexistent key (insert)
match map.entry(&10) {
match map.entry(10) {
Occupied(_) => unreachable!(),
Vacant(view) => {
assert_eq!(*view.insert(1000), 1000);

View File

@ -1328,7 +1328,7 @@ impl UnusedMut {
let ident = path1.node;
if let ast::BindByValue(ast::MutMutable) = mode {
if !token::get_ident(ident).get().starts_with("_") {
match mutables.entry(&ident.name.uint()) {
match mutables.entry(ident.name.uint()) {
Vacant(entry) => { entry.insert(vec![id]); },
Occupied(mut entry) => { entry.get_mut().push(id); },
}

View File

@ -400,7 +400,7 @@ impl<'a> Context<'a> {
info!("lib candidate: {}", path.display());
let hash_str = hash.to_string();
let slot = candidates.entry(&hash_str).get().unwrap_or_else(
let slot = candidates.entry(hash_str).get().unwrap_or_else(
|vacant_entry| vacant_entry.insert((HashSet::new(), HashSet::new())));
let (ref mut rlibs, ref mut dylibs) = *slot;
if rlib {

View File

@ -311,7 +311,7 @@ pub fn const_expr_to_pat(tcx: &ty::ctxt, expr: &Expr) -> P<ast::Pat> {
ast::ExprCall(ref callee, ref args) => {
let def = tcx.def_map.borrow()[callee.id].clone();
if let Vacant(entry) = tcx.def_map.borrow_mut().entry(&expr.id) {
if let Vacant(entry) = tcx.def_map.borrow_mut().entry(expr.id) {
entry.insert(def);
}
let path = match def {

View File

@ -66,7 +66,7 @@ impl<'a, 'tcx> TypeFreshener<'a, 'tcx> {
None => { }
}
match self.freshen_map.entry(&key) {
match self.freshen_map.entry(key) {
Entry::Occupied(entry) => *entry.get(),
Entry::Vacant(entry) => {
let index = self.freshen_count;

View File

@ -137,7 +137,7 @@ impl<'a, 'tcx> ConstraintGraph<'a, 'tcx> {
let mut node_ids = FnvHashMap::new();
{
let mut add_node = |&mut : node| {
if let Vacant(e) = node_ids.entry(&node) {
if let Vacant(e) = node_ids.entry(node) {
e.insert(i);
i += 1;
}

View File

@ -437,11 +437,9 @@ fn register_region_obligation<'tcx>(tcx: &ty::ctxt<'tcx>,
debug!("register_region_obligation({})",
region_obligation.repr(tcx));
let body_id = region_obligation.cause.body_id;
match region_obligations.entry(&body_id) {
match region_obligations.entry(region_obligation.cause.body_id) {
Vacant(entry) => { entry.insert(vec![region_obligation]); },
Occupied(mut entry) => { entry.get_mut().push(region_obligation); },
}
}

View File

@ -5616,7 +5616,7 @@ pub fn lookup_field_type<'tcx>(tcx: &ctxt<'tcx>,
node_id_to_type(tcx, id.node)
} else {
let mut tcache = tcx.tcache.borrow_mut();
let pty = tcache.entry(&id).get().unwrap_or_else(
let pty = tcache.entry(id).get().unwrap_or_else(
|vacant_entry| vacant_entry.insert(csearch::get_field_type(tcx, struct_id, id)));
pty.ty
};
@ -6755,7 +6755,7 @@ pub fn replace_late_bound_regions<'tcx, T, F>(
debug!("region={}", region.repr(tcx));
match region {
ty::ReLateBound(debruijn, br) if debruijn.depth == current_depth => {
* map.entry(&br).get().unwrap_or_else(
* map.entry(br).get().unwrap_or_else(
|vacant_entry| vacant_entry.insert(mapf(br, debruijn)))
}
_ => {

View File

@ -1115,7 +1115,7 @@ pub fn build_session_options(matches: &getopts::Matches) -> Options {
None => early_error("--extern value must be of the format `foo=bar`"),
};
match externs.entry(&name.to_string()) {
match externs.entry(name.to_string()) {
Vacant(entry) => { entry.insert(vec![location.to_string()]); },
Occupied(mut entry) => { entry.get_mut().push(location.to_string()); },
}

View File

@ -1688,7 +1688,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
let is_public = import_directive.is_public;
let mut import_resolutions = module_.import_resolutions.borrow_mut();
let dest_import_resolution = import_resolutions.entry(&name).get().unwrap_or_else(
let dest_import_resolution = import_resolutions.entry(name).get().unwrap_or_else(
|vacant_entry| {
// Create a new import resolution from this child.
vacant_entry.insert(ImportResolution::new(id, is_public))
@ -2626,14 +2626,14 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
def = DefUpvar(node_id, function_id, last_proc_body_id);
let mut seen = self.freevars_seen.borrow_mut();
let seen = match seen.entry(&function_id) {
let seen = match seen.entry(function_id) {
Occupied(v) => v.into_mut(),
Vacant(v) => v.insert(NodeSet::new()),
};
if seen.contains(&node_id) {
continue;
}
match self.freevars.borrow_mut().entry(&function_id) {
match self.freevars.borrow_mut().entry(function_id) {
Occupied(v) => v.into_mut(),
Vacant(v) => v.insert(vec![]),
}.push(Freevar { def: prev_def, span: span });
@ -4710,7 +4710,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
"Import should only be used for `use` directives");
self.last_private.insert(node_id, lp);
match self.def_map.borrow_mut().entry(&node_id) {
match self.def_map.borrow_mut().entry(node_id) {
// Resolve appears to "resolve" the same ID multiple
// times, so here is a sanity check it at least comes to
// the same conclusion! - nmatsakis

View File

@ -604,7 +604,7 @@ pub fn check_struct_pat_fields<'a, 'tcx>(pcx: &pat_ctxt<'a, 'tcx>,
// Typecheck each field.
for &Spanned { node: ref field, span } in fields.iter() {
let field_type = match used_fields.entry(&field.ident.name) {
let field_type = match used_fields.entry(field.ident.name) {
Occupied(occupied) => {
span_err!(tcx.sess, span, E0025,
"field `{}` bound multiple times in the pattern",

View File

@ -821,7 +821,7 @@ impl DocFolder for Cache {
if let clean::ImplItem(ref i) = item.inner {
match i.trait_ {
Some(clean::ResolvedPath{ did, .. }) => {
let v = self.implementors.entry(&did).get().unwrap_or_else(
let v = self.implementors.entry(did).get().unwrap_or_else(
|vacant_entry| vacant_entry.insert(Vec::with_capacity(1)));
v.push(Implementor {
def_id: item.def_id,
@ -1011,7 +1011,7 @@ impl DocFolder for Cache {
};
if let Some(did) = did {
let v = self.impls.entry(&did).get().unwrap_or_else(
let v = self.impls.entry(did).get().unwrap_or_else(
|vacant_entry| vacant_entry.insert(Vec::with_capacity(1)));
v.push(Impl {
impl_: i,
@ -1260,7 +1260,7 @@ impl Context {
Some(ref s) => s.to_string(),
};
let short = short.to_string();
let v = map.entry(&short).get().unwrap_or_else(
let v = map.entry(short).get().unwrap_or_else(
|vacant_entry| vacant_entry.insert(Vec::with_capacity(1)));
v.push(myname);
}

View File

@ -317,7 +317,7 @@ fn parse_externs(matches: &getopts::Matches) -> Result<core::Externs, String> {
}
};
let name = name.to_string();
let locs = externs.entry(&name).get().unwrap_or_else(
let locs = externs.entry(name).get().unwrap_or_else(
|vacant_entry| vacant_entry.insert(Vec::with_capacity(1)));
locs.push(location.to_string());
}

View File

@ -14,7 +14,7 @@ use self::Entry::*;
use self::SearchResult::*;
use self::VacantEntryState::*;
use borrow::{BorrowFrom, ToOwned};
use borrow::BorrowFrom;
use clone::Clone;
use cmp::{max, Eq, PartialEq};
use default::Default;
@ -920,16 +920,14 @@ impl<K: Eq + Hash<S>, V, S, H: Hasher<S>> HashMap<K, V, H> {
}
}
#[stable]
/// Gets the given key's corresponding entry in the map for in-place manipulation.
/// Regardless of whether or not `to_owned()` has been called, the key must hash the same way.
pub fn entry<'a, Q: ?Sized>(&'a mut self, key: &'a Q) -> Entry<'a, Q, K, V>
where Q: Eq + Hash<S> + ToOwned<K>
#[unstable = "precise API still being fleshed out"]
pub fn entry<'a>(&'a mut self, key: K) -> Entry<'a, K, V>
{
// Gotta resize now.
self.reserve(1);
let hash = self.make_hash(key);
let hash = self.make_hash(&key);
search_entry_hashed(&mut self.table, hash, key)
}
@ -1142,9 +1140,8 @@ impl<K: Eq + Hash<S>, V, S, H: Hasher<S>> HashMap<K, V, H> {
}
}
fn search_entry_hashed<'a, K, V, Q: ?Sized>(table: &'a mut RawTable<K,V>, hash: SafeHash, k: &'a Q)
-> Entry<'a, Q, K, V>
where Q: Eq + ToOwned<K>
fn search_entry_hashed<'a, K: Eq, V>(table: &'a mut RawTable<K,V>, hash: SafeHash, k: K)
-> Entry<'a, K, V>
{
// Worst case, we'll find one empty bucket among `size + 1` buckets.
let size = table.size();
@ -1167,7 +1164,7 @@ fn search_entry_hashed<'a, K, V, Q: ?Sized>(table: &'a mut RawTable<K,V>, hash:
// hash matches?
if bucket.hash() == hash {
// key matches?
if *k == *BorrowFrom::borrow_from(bucket.read().0) {
if k == *bucket.read().0 {
return Occupied(OccupiedEntry{
elem: bucket,
});
@ -1323,27 +1320,27 @@ pub struct Drain<'a, K: 'a, V: 'a> {
>
}
#[stable]
/// A view into a single occupied location in a HashMap
#[unstable = "precise API still being fleshed out"]
pub struct OccupiedEntry<'a, K: 'a, V: 'a> {
elem: FullBucket<K, V, &'a mut RawTable<K, V>>,
}
#[stable]
/// A view into a single empty location in a HashMap
pub struct VacantEntry<'a, Q: ?Sized + 'a, K: 'a, V: 'a> {
#[unstable = "precise API still being fleshed out"]
pub struct VacantEntry<'a, K: 'a, V: 'a> {
hash: SafeHash,
key: &'a Q,
key: K,
elem: VacantEntryState<K, V, &'a mut RawTable<K, V>>,
}
#[stable]
/// A view into a single location in a map, which may be vacant or occupied
pub enum Entry<'a, Q: ?Sized + 'a, K: 'a, V: 'a> {
#[unstable = "precise API still being fleshed out"]
pub enum Entry<'a, K: 'a, V: 'a> {
/// An occupied Entry
Occupied(OccupiedEntry<'a, K, V>),
/// A vacant Entry
Vacant(VacantEntry<'a, Q, K, V>),
Vacant(VacantEntry<'a, K, V>),
}
/// Possible states of a VacantEntry
@ -1409,10 +1406,10 @@ impl<'a, K: 'a, V: 'a> Iterator for Drain<'a, K, V> {
}
}
impl<'a, Q: ?Sized, K, V> Entry<'a, Q, K, V> {
#[unstable = "matches collection reform v2 specification, waiting for dust to settle"]
#[unstable = "matches collection reform v2 specification, waiting for dust to settle"]
impl<'a, K, V> Entry<'a, K, V> {
/// Returns a mutable reference to the entry if occupied, or the VacantEntry if vacant
pub fn get(self) -> Result<&'a mut V, VacantEntry<'a, Q, K, V>> {
pub fn get(self) -> Result<&'a mut V, VacantEntry<'a, K, V>> {
match self {
Occupied(entry) => Ok(entry.into_mut()),
Vacant(entry) => Err(entry),
@ -1420,27 +1417,24 @@ impl<'a, Q: ?Sized, K, V> Entry<'a, Q, K, V> {
}
}
#[unstable = "matches collection reform v2 specification, waiting for dust to settle"]
impl<'a, K, V> OccupiedEntry<'a, K, V> {
#[stable]
/// Gets a reference to the value in the entry
pub fn get(&self) -> &V {
self.elem.read().1
}
#[stable]
/// Gets a mutable reference to the value in the entry
pub fn get_mut(&mut self) -> &mut V {
self.elem.read_mut().1
}
#[stable]
/// Converts the OccupiedEntry into a mutable reference to the value in the entry
/// with a lifetime bound to the map itself
pub fn into_mut(self) -> &'a mut V {
self.elem.into_mut_refs().1
}
#[stable]
/// Sets the value of the entry, and returns the entry's old value
pub fn insert(&mut self, mut value: V) -> V {
let old_value = self.get_mut();
@ -1448,24 +1442,23 @@ impl<'a, K, V> OccupiedEntry<'a, K, V> {
value
}
#[stable]
/// Takes the value out of the entry, and returns it
pub fn remove(self) -> V {
pop_internal(self.elem).1
}
}
impl<'a, Q: ?Sized + 'a + ToOwned<K>, K: 'a, V: 'a> VacantEntry<'a, Q, K, V> {
#[stable]
#[unstable = "matches collection reform v2 specification, waiting for dust to settle"]
impl<'a, K: 'a, V: 'a> VacantEntry<'a, K, V> {
/// Sets the value of the entry with the VacantEntry's key,
/// and returns a mutable reference to it
pub fn insert(self, value: V) -> &'a mut V {
match self.elem {
NeqElem(bucket, ib) => {
robin_hood(bucket, ib, self.hash, self.key.to_owned(), value)
robin_hood(bucket, ib, self.hash, self.key, value)
}
NoElem(bucket) => {
bucket.put(self.hash, self.key.to_owned(), value).into_mut_refs().1
bucket.put(self.hash, self.key, value).into_mut_refs().1
}
}
}
@ -1497,8 +1490,6 @@ mod test_map {
use super::HashMap;
use super::Entry::{Occupied, Vacant};
use iter::{range_inclusive, range_step_inclusive, repeat};
use borrow::ToOwned;
use hash;
use cell::RefCell;
use rand::{weak_rng, Rng};
@ -2092,7 +2083,7 @@ mod test_map {
let mut map: HashMap<int, int> = xs.iter().map(|&x| x).collect();
// Existing key (insert)
match map.entry(&1) {
match map.entry(1) {
Vacant(_) => unreachable!(),
Occupied(mut view) => {
assert_eq!(view.get(), &10);
@ -2104,7 +2095,7 @@ mod test_map {
// Existing key (update)
match map.entry(&2) {
match map.entry(2) {
Vacant(_) => unreachable!(),
Occupied(mut view) => {
let v = view.get_mut();
@ -2116,7 +2107,7 @@ mod test_map {
assert_eq!(map.len(), 6);
// Existing key (take)
match map.entry(&3) {
match map.entry(3) {
Vacant(_) => unreachable!(),
Occupied(view) => {
assert_eq!(view.remove(), 30);
@ -2127,7 +2118,7 @@ mod test_map {
// Inexistent key (insert)
match map.entry(&10) {
match map.entry(10) {
Occupied(_) => unreachable!(),
Vacant(view) => {
assert_eq!(*view.insert(1000), 1000);
@ -2158,7 +2149,7 @@ mod test_map {
for i in range(0u, 1000) {
let x = rng.gen_range(-10, 10);
match m.entry(&x) {
match m.entry(x) {
Vacant(_) => {},
Occupied(e) => {
println!("{}: remove {}", i, x);

View File

@ -255,7 +255,7 @@
//! let message = "she sells sea shells by the sea shore";
//!
//! for c in message.chars() {
//! match count.entry(&c) {
//! match count.entry(c) {
//! Vacant(entry) => { entry.insert(1u); },
//! Occupied(mut entry) => *entry.get_mut() += 1,
//! }
@ -290,7 +290,7 @@
//! for id in orders.into_iter() {
//! // If this is the first time we've seen this customer, initialize them
//! // with no blood alcohol. Otherwise, just retrieve them.
//! let person = match blood_alcohol.entry(&id) {
//! let person = match blood_alcohol.entry(id) {
//! Vacant(entry) => entry.insert(Person{id: id, blood_alcohol: 0.0}),
//! Occupied(entry) => entry.into_mut(),
//! };

View File

@ -66,7 +66,7 @@ pub fn apply_mark(m: Mrk, ctxt: SyntaxContext) -> SyntaxContext {
/// Extend a syntax context with a given mark and sctable (explicit memoization)
fn apply_mark_internal(m: Mrk, ctxt: SyntaxContext, table: &SCTable) -> SyntaxContext {
let key = (ctxt, m);
* table.mark_memo.borrow_mut().entry(&key).get().unwrap_or_else(
* table.mark_memo.borrow_mut().entry(key).get().unwrap_or_else(
|vacant_entry|
vacant_entry.insert(idx_push(&mut *table.table.borrow_mut(), Mark(m, ctxt))))
}
@ -84,7 +84,7 @@ fn apply_rename_internal(id: Ident,
table: &SCTable) -> SyntaxContext {
let key = (ctxt, id, to);
* table.rename_memo.borrow_mut().entry(&key).get().unwrap_or_else(
* table.rename_memo.borrow_mut().entry(key).get().unwrap_or_else(
|vacant_entry|
vacant_entry.insert(idx_push(&mut *table.table.borrow_mut(), Rename(id, to, ctxt))))
}

View File

@ -219,7 +219,7 @@ pub fn nameize(p_s: &ParseSess, ms: &[TokenTree], res: &[Rc<NamedMatch>])
}
}
&TtToken(sp, MatchNt(bind_name, _, _, _)) => {
match ret_val.entry(&bind_name) {
match ret_val.entry(bind_name) {
Vacant(spot) => {
spot.insert(res[*idx].clone());
*idx += 1;

View File

@ -444,7 +444,7 @@ pub fn freq_count<T, U>(mut iter: T) -> hash_map::HashMap<U, uint>
{
let mut map: hash_map::HashMap<U,uint> = hash_map::HashMap::new();
for elem in iter {
match map.entry(&elem) {
match map.entry(elem) {
Occupied(mut entry) => { *entry.get_mut() += 1; },
Vacant(entry) => { entry.insert(1); },
}