[breaking change] Update entry API as part of RFC 509.
This commit is contained in:
parent
260e46115b
commit
400c3a0ddc
@ -11,7 +11,7 @@
|
||||
use prelude::*;
|
||||
use std::rand;
|
||||
use std::rand::Rng;
|
||||
use test::Bencher;
|
||||
use test::{Bencher, black_box};
|
||||
|
||||
pub fn insert_rand_n<M, I, R>(n: uint,
|
||||
map: &mut M,
|
||||
@ -33,7 +33,8 @@ pub fn insert_rand_n<M, I, R>(n: uint,
|
||||
let k = rng.gen::<uint>() % n;
|
||||
insert(map, k);
|
||||
remove(map, k);
|
||||
})
|
||||
});
|
||||
black_box(map);
|
||||
}
|
||||
|
||||
pub fn insert_seq_n<M, I, R>(n: uint,
|
||||
@ -55,7 +56,8 @@ pub fn insert_seq_n<M, I, R>(n: uint,
|
||||
insert(map, i);
|
||||
remove(map, i);
|
||||
i = (i + 2) % n;
|
||||
})
|
||||
});
|
||||
black_box(map);
|
||||
}
|
||||
|
||||
pub fn find_rand_n<M, T, I, F>(n: uint,
|
||||
@ -82,7 +84,7 @@ pub fn find_rand_n<M, T, I, F>(n: uint,
|
||||
b.iter(|| {
|
||||
let t = find(map, keys[i]);
|
||||
i = (i + 1) % n;
|
||||
t
|
||||
black_box(t);
|
||||
})
|
||||
}
|
||||
|
||||
@ -104,6 +106,6 @@ pub fn find_seq_n<M, T, I, F>(n: uint,
|
||||
b.iter(|| {
|
||||
let x = find(map, i);
|
||||
i = (i + 1) % n;
|
||||
x
|
||||
black_box(x);
|
||||
})
|
||||
}
|
||||
|
@ -19,7 +19,7 @@ pub use self::Entry::*;
|
||||
|
||||
use core::prelude::*;
|
||||
|
||||
use core::borrow::BorrowFrom;
|
||||
use core::borrow::{BorrowFrom, ToOwned};
|
||||
use core::cmp::Ordering;
|
||||
use core::default::Default;
|
||||
use core::fmt::Show;
|
||||
@ -128,20 +128,23 @@ 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, K:'a, V:'a> {
|
||||
pub enum Entry<'a, Sized? Q:'a, K:'a, V:'a> {
|
||||
/// A vacant Entry
|
||||
Vacant(VacantEntry<'a, K, V>),
|
||||
Vacant(VacantEntry<'a, Q, K, V>),
|
||||
/// An occupied Entry
|
||||
Occupied(OccupiedEntry<'a, K, V>),
|
||||
}
|
||||
|
||||
#[stable]
|
||||
/// A vacant Entry.
|
||||
pub struct VacantEntry<'a, K:'a, V:'a> {
|
||||
key: K,
|
||||
pub struct VacantEntry<'a, Sized? Q:'a, K:'a, V:'a> {
|
||||
key: &'a Q,
|
||||
stack: stack::SearchStack<'a, K, V, node::handle::Edge, node::handle::Leaf>,
|
||||
}
|
||||
|
||||
#[stable]
|
||||
/// An occupied Entry.
|
||||
pub struct OccupiedEntry<'a, K:'a, V:'a> {
|
||||
stack: stack::SearchStack<'a, K, V, node::handle::KV, node::handle::LeafOrInternal>,
|
||||
@ -1132,40 +1135,56 @@ impl<'a, K, V> DoubleEndedIterator for Values<'a, K, V> {
|
||||
#[stable]
|
||||
impl<'a, K, V> ExactSizeIterator for Values<'a, K, V> {}
|
||||
|
||||
impl<'a, Sized? Q, K: Ord, V> Entry<'a, Q, 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>> {
|
||||
match self {
|
||||
Occupied(entry) => Ok(entry.into_mut()),
|
||||
Vacant(entry) => Err(entry),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a, K: Ord, V> VacantEntry<'a, K, V> {
|
||||
impl<'a, Sized? Q: ToOwned<K>, K: Ord, V> VacantEntry<'a, Q, K, V> {
|
||||
#[stable]
|
||||
/// Sets the value of the entry with the VacantEntry's key,
|
||||
/// and returns a mutable reference to it.
|
||||
pub fn set(self, value: V) -> &'a mut V {
|
||||
self.stack.insert(self.key, value)
|
||||
pub fn insert(self, value: V) -> &'a mut V {
|
||||
self.stack.insert(self.key.to_owned(), value)
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a, K: Ord, V> OccupiedEntry<'a, K, V> {
|
||||
#[stable]
|
||||
/// Gets a reference to the value in the entry.
|
||||
pub fn get(&self) -> &V {
|
||||
self.stack.peek()
|
||||
}
|
||||
|
||||
#[stable]
|
||||
/// Gets a mutable reference to the value in the entry.
|
||||
pub fn get_mut(&mut self) -> &mut V {
|
||||
self.stack.peek_mut()
|
||||
}
|
||||
|
||||
#[stable]
|
||||
/// Converts the entry into a mutable reference to its value.
|
||||
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.
|
||||
pub fn set(&mut self, mut value: V) -> V {
|
||||
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.
|
||||
pub fn take(self) -> V {
|
||||
pub fn remove(self) -> V {
|
||||
self.stack.remove()
|
||||
}
|
||||
}
|
||||
@ -1352,9 +1371,9 @@ impl<K: Ord, V> BTreeMap<K, V> {
|
||||
///
|
||||
/// // count the number of occurrences of letters in the vec
|
||||
/// for x in vec!["a","b","a","c","a","b"].iter() {
|
||||
/// match count.entry(*x) {
|
||||
/// match count.entry(x) {
|
||||
/// Entry::Vacant(view) => {
|
||||
/// view.set(1);
|
||||
/// view.insert(1);
|
||||
/// },
|
||||
/// Entry::Occupied(mut view) => {
|
||||
/// let v = view.get_mut();
|
||||
@ -1365,12 +1384,16 @@ impl<K: Ord, V> BTreeMap<K, V> {
|
||||
///
|
||||
/// assert_eq!(count["a"], 3u);
|
||||
/// ```
|
||||
pub fn entry<'a>(&'a mut self, mut key: K) -> Entry<'a, K, V> {
|
||||
/// The key must have the same ordering before or after `.to_owned()` is called.
|
||||
#[stable]
|
||||
pub fn entry<'a, Sized? Q>(&'a mut self, mut key: &'a Q) -> Entry<'a, Q, K, V>
|
||||
where Q: Ord + ToOwned<K>
|
||||
{
|
||||
// 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 {
|
||||
@ -1413,6 +1436,7 @@ impl<K: Ord, V> BTreeMap<K, V> {
|
||||
#[cfg(test)]
|
||||
mod test {
|
||||
use prelude::*;
|
||||
use std::borrow::{ToOwned, BorrowFrom};
|
||||
|
||||
use super::{BTreeMap, Occupied, Vacant};
|
||||
|
||||
@ -1562,11 +1586,11 @@ 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);
|
||||
assert_eq!(view.set(100), 10);
|
||||
assert_eq!(view.insert(100), 10);
|
||||
}
|
||||
}
|
||||
assert_eq!(map.get(&1).unwrap(), &100);
|
||||
@ -1574,7 +1598,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,10 +1609,10 @@ 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.take(), 30);
|
||||
assert_eq!(view.remove(), 30);
|
||||
}
|
||||
}
|
||||
assert_eq!(map.get(&3), None);
|
||||
@ -1596,10 +1620,10 @@ mod test {
|
||||
|
||||
|
||||
// Inexistent key (insert)
|
||||
match map.entry(10) {
|
||||
match map.entry(&10) {
|
||||
Occupied(_) => unreachable!(),
|
||||
Vacant(view) => {
|
||||
assert_eq!(*view.set(1000), 1000);
|
||||
assert_eq!(*view.insert(1000), 1000);
|
||||
}
|
||||
}
|
||||
assert_eq!(map.get(&10).unwrap(), &1000);
|
||||
|
@ -1329,8 +1329,8 @@ 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()) {
|
||||
Vacant(entry) => { entry.set(vec![id]); },
|
||||
match mutables.entry(&ident.name.uint()) {
|
||||
Vacant(entry) => { entry.insert(vec![id]); },
|
||||
Occupied(mut entry) => { entry.get_mut().push(id); },
|
||||
}
|
||||
}
|
||||
|
@ -87,8 +87,8 @@ fn dump_crates(cstore: &CStore) {
|
||||
fn warn_if_multiple_versions(diag: &SpanHandler, cstore: &CStore) {
|
||||
let mut map = FnvHashMap::new();
|
||||
cstore.iter_crate_data(|cnum, data| {
|
||||
match map.entry(data.name()) {
|
||||
Vacant(entry) => { entry.set(vec![cnum]); },
|
||||
match map.entry(&data.name()) {
|
||||
Vacant(entry) => { entry.insert(vec![cnum]); },
|
||||
Occupied(mut entry) => { entry.get_mut().push(cnum); },
|
||||
}
|
||||
});
|
||||
|
@ -228,7 +228,6 @@ use util::fs;
|
||||
|
||||
use std::c_str::ToCStr;
|
||||
use std::cmp;
|
||||
use std::collections::hash_map::Entry::{Occupied, Vacant};
|
||||
use std::collections::{HashMap, HashSet};
|
||||
use std::io::fs::PathExtensions;
|
||||
use std::io;
|
||||
@ -400,10 +399,9 @@ impl<'a> Context<'a> {
|
||||
};
|
||||
info!("lib candidate: {}", path.display());
|
||||
|
||||
let slot = match candidates.entry(hash.to_string()) {
|
||||
Occupied(entry) => entry.into_mut(),
|
||||
Vacant(entry) => entry.set((HashSet::new(), HashSet::new())),
|
||||
};
|
||||
let hash_str = hash.to_string();
|
||||
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 {
|
||||
rlibs.insert(fs::realpath(path).unwrap());
|
||||
|
@ -311,8 +311,8 @@ 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) {
|
||||
entry.set(def);
|
||||
if let Vacant(entry) = tcx.def_map.borrow_mut().entry(&expr.id) {
|
||||
entry.insert(def);
|
||||
}
|
||||
let path = match def {
|
||||
def::DefStruct(def_id) => def_to_path(tcx, def_id),
|
||||
|
@ -66,13 +66,13 @@ 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;
|
||||
self.freshen_count += 1;
|
||||
let t = ty::mk_infer(self.infcx.tcx, freshener(index));
|
||||
entry.set(t);
|
||||
entry.insert(t);
|
||||
t
|
||||
}
|
||||
}
|
||||
|
@ -137,8 +137,8 @@ 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) {
|
||||
e.set(i);
|
||||
if let Vacant(e) = node_ids.entry(&node) {
|
||||
e.insert(i);
|
||||
i += 1;
|
||||
}
|
||||
};
|
||||
|
@ -437,8 +437,9 @@ fn register_region_obligation<'tcx>(tcx: &ty::ctxt<'tcx>,
|
||||
debug!("register_region_obligation({})",
|
||||
region_obligation.repr(tcx));
|
||||
|
||||
match region_obligations.entry(region_obligation.cause.body_id) {
|
||||
Vacant(entry) => { entry.set(vec![region_obligation]); },
|
||||
let body_id = region_obligation.cause.body_id;
|
||||
match region_obligations.entry(&body_id) {
|
||||
Vacant(entry) => { entry.insert(vec![region_obligation]); },
|
||||
Occupied(mut entry) => { entry.get_mut().push(region_obligation); },
|
||||
}
|
||||
|
||||
|
@ -78,7 +78,6 @@ use std::ops;
|
||||
use std::rc::Rc;
|
||||
use collections::enum_set::{EnumSet, CLike};
|
||||
use std::collections::{HashMap, HashSet};
|
||||
use std::collections::hash_map::Entry::{Occupied, Vacant};
|
||||
use syntax::abi;
|
||||
use syntax::ast::{CrateNum, DefId, Ident, ItemTrait, LOCAL_CRATE};
|
||||
use syntax::ast::{MutImmutable, MutMutable, Name, NamedField, NodeId};
|
||||
@ -5651,10 +5650,8 @@ 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 = match tcache.entry(id) {
|
||||
Occupied(entry) => entry.into_mut(),
|
||||
Vacant(entry) => entry.set(csearch::get_field_type(tcx, struct_id, id)),
|
||||
};
|
||||
let pty = tcache.entry(&id).get().unwrap_or_else(
|
||||
|vacant_entry| vacant_entry.insert(csearch::get_field_type(tcx, struct_id, id)));
|
||||
pty.ty
|
||||
};
|
||||
ty.subst(tcx, substs)
|
||||
@ -6841,10 +6838,8 @@ 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 => {
|
||||
* match map.entry(br) {
|
||||
Vacant(entry) => entry.set(mapf(br, debruijn)),
|
||||
Occupied(entry) => entry.into_mut(),
|
||||
}
|
||||
* map.entry(&br).get().unwrap_or_else(
|
||||
|vacant_entry| vacant_entry.insert(mapf(br, debruijn)))
|
||||
}
|
||||
_ => {
|
||||
region
|
||||
|
@ -1114,8 +1114,8 @@ 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()) {
|
||||
Vacant(entry) => { entry.set(vec![location.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()); },
|
||||
}
|
||||
}
|
||||
|
@ -1688,15 +1688,11 @@ 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 = match import_resolutions.entry(name) {
|
||||
Occupied(entry) => {
|
||||
entry.into_mut()
|
||||
}
|
||||
Vacant(entry) => {
|
||||
let dest_import_resolution = import_resolutions.entry(&name).get().unwrap_or_else(
|
||||
|vacant_entry| {
|
||||
// Create a new import resolution from this child.
|
||||
entry.set(ImportResolution::new(id, is_public))
|
||||
}
|
||||
};
|
||||
vacant_entry.insert(ImportResolution::new(id, is_public))
|
||||
});
|
||||
|
||||
debug!("(resolving glob import) writing resolution `{}` in `{}` \
|
||||
to `{}`",
|
||||
@ -2630,16 +2626,16 @@ 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.set(NodeSet::new()),
|
||||
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.set(vec![]),
|
||||
Vacant(v) => v.insert(vec![]),
|
||||
}.push(Freevar { def: prev_def, span: span });
|
||||
seen.insert(node_id);
|
||||
}
|
||||
@ -4722,7 +4718,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
|
||||
@ -4734,7 +4730,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
|
||||
*entry.get(),
|
||||
def)[]);
|
||||
},
|
||||
Vacant(entry) => { entry.set(def); },
|
||||
Vacant(entry) => { entry.insert(def); },
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -496,7 +496,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",
|
||||
@ -507,7 +507,7 @@ pub fn check_struct_pat_fields<'a, 'tcx>(pcx: &pat_ctxt<'a, 'tcx>,
|
||||
tcx.types.err
|
||||
}
|
||||
Vacant(vacant) => {
|
||||
vacant.set(span);
|
||||
vacant.insert(span);
|
||||
field_type_map.get(&field.ident.name).cloned()
|
||||
.unwrap_or_else(|| {
|
||||
span_err!(tcx.sess, span, E0026,
|
||||
|
@ -36,7 +36,6 @@ pub use self::ExternalLocation::*;
|
||||
|
||||
use std::cell::RefCell;
|
||||
use std::cmp::Ordering::{self, Less, Greater, Equal};
|
||||
use std::collections::hash_map::Entry::{Occupied, Vacant};
|
||||
use std::collections::{HashMap, HashSet};
|
||||
use std::default::Default;
|
||||
use std::fmt;
|
||||
@ -822,10 +821,8 @@ impl DocFolder for Cache {
|
||||
if let clean::ImplItem(ref i) = item.inner {
|
||||
match i.trait_ {
|
||||
Some(clean::ResolvedPath{ did, .. }) => {
|
||||
let v = match self.implementors.entry(did) {
|
||||
Vacant(entry) => entry.set(Vec::with_capacity(1)),
|
||||
Occupied(entry) => entry.into_mut(),
|
||||
};
|
||||
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,
|
||||
generics: i.generics.clone(),
|
||||
@ -1014,10 +1011,8 @@ impl DocFolder for Cache {
|
||||
};
|
||||
|
||||
if let Some(did) = did {
|
||||
let v = match self.impls.entry(did) {
|
||||
Vacant(entry) => entry.set(Vec::with_capacity(1)),
|
||||
Occupied(entry) => entry.into_mut(),
|
||||
};
|
||||
let v = self.impls.entry(&did).get().unwrap_or_else(
|
||||
|vacant_entry| vacant_entry.insert(Vec::with_capacity(1)));
|
||||
v.push(Impl {
|
||||
impl_: i,
|
||||
dox: dox,
|
||||
@ -1264,10 +1259,9 @@ impl Context {
|
||||
None => continue,
|
||||
Some(ref s) => s.to_string(),
|
||||
};
|
||||
let v = match map.entry(short.to_string()) {
|
||||
Vacant(entry) => entry.set(Vec::with_capacity(1)),
|
||||
Occupied(entry) => entry.into_mut(),
|
||||
};
|
||||
let short = short.to_string();
|
||||
let v = map.entry(&short).get().unwrap_or_else(
|
||||
|vacant_entry| vacant_entry.insert(Vec::with_capacity(1)));
|
||||
v.push(myname);
|
||||
}
|
||||
|
||||
|
@ -38,7 +38,6 @@ extern crate "serialize" as rustc_serialize; // used by deriving
|
||||
|
||||
use std::cell::RefCell;
|
||||
use std::collections::HashMap;
|
||||
use std::collections::hash_map::Entry::{Occupied, Vacant};
|
||||
use std::io::File;
|
||||
use std::io;
|
||||
use std::rc::Rc;
|
||||
@ -321,10 +320,9 @@ fn parse_externs(matches: &getopts::Matches) -> Result<core::Externs, String> {
|
||||
return Err("--extern value must be of the format `foo=bar`".to_string());
|
||||
}
|
||||
};
|
||||
let locs = match externs.entry(name.to_string()) {
|
||||
Vacant(entry) => entry.set(Vec::with_capacity(1)),
|
||||
Occupied(entry) => entry.into_mut(),
|
||||
};
|
||||
let name = name.to_string();
|
||||
let locs = externs.entry(&name).get().unwrap_or_else(
|
||||
|vacant_entry| vacant_entry.insert(Vec::with_capacity(1)));
|
||||
locs.push(location.to_string());
|
||||
}
|
||||
Ok(externs)
|
||||
|
@ -14,7 +14,7 @@ use self::Entry::*;
|
||||
use self::SearchResult::*;
|
||||
use self::VacantEntryState::*;
|
||||
|
||||
use borrow::BorrowFrom;
|
||||
use borrow::{BorrowFrom, ToOwned};
|
||||
use clone::Clone;
|
||||
use cmp::{max, Eq, PartialEq};
|
||||
use default::Default;
|
||||
@ -920,12 +920,16 @@ impl<K: Eq + Hash<S>, V, S, H: Hasher<S>> HashMap<K, V, H> {
|
||||
}
|
||||
}
|
||||
|
||||
/// Gets the given key's corresponding entry in the map for in-place manipulation
|
||||
pub fn entry<'a>(&'a mut self, key: K) -> Entry<'a, K, V> {
|
||||
#[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, Sized? Q>(&'a mut self, key: &'a Q) -> Entry<'a, Q, K, V>
|
||||
where Q: Eq + Hash<S> + ToOwned<K>
|
||||
{
|
||||
// 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)
|
||||
}
|
||||
|
||||
@ -1138,8 +1142,10 @@ impl<K: Eq + Hash<S>, V, S, H: Hasher<S>> HashMap<K, V, H> {
|
||||
}
|
||||
}
|
||||
|
||||
fn search_entry_hashed<'a, K: Eq, V>(table: &'a mut RawTable<K,V>, hash: SafeHash, k: K)
|
||||
-> Entry<'a, K, V> {
|
||||
fn search_entry_hashed<'a, K, V, Sized? Q>(table: &'a mut RawTable<K,V>, hash: SafeHash, k: &'a Q)
|
||||
-> Entry<'a, Q, K, V>
|
||||
where Q: Eq + ToOwned<K>
|
||||
{
|
||||
// Worst case, we'll find one empty bucket among `size + 1` buckets.
|
||||
let size = table.size();
|
||||
let mut probe = Bucket::new(table, hash);
|
||||
@ -1161,7 +1167,7 @@ fn search_entry_hashed<'a, K: Eq, V>(table: &'a mut RawTable<K,V>, hash: SafeHas
|
||||
// hash matches?
|
||||
if bucket.hash() == hash {
|
||||
// key matches?
|
||||
if k == *bucket.read().0 {
|
||||
if *k == *BorrowFrom::borrow_from(bucket.read().0) {
|
||||
return Occupied(OccupiedEntry{
|
||||
elem: bucket,
|
||||
});
|
||||
@ -1343,24 +1349,27 @@ pub struct Drain<'a, K: 'a, V: 'a> {
|
||||
>
|
||||
}
|
||||
|
||||
#[stable]
|
||||
/// A view into a single occupied location in a HashMap
|
||||
pub struct OccupiedEntry<'a, K:'a, V:'a> {
|
||||
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, K:'a, V:'a> {
|
||||
pub struct VacantEntry<'a, Sized? Q: 'a, K: 'a, V: 'a> {
|
||||
hash: SafeHash,
|
||||
key: K,
|
||||
elem: VacantEntryState<K,V, &'a mut RawTable<K, V>>,
|
||||
key: &'a Q,
|
||||
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, K:'a, V:'a> {
|
||||
pub enum Entry<'a, Sized? Q: 'a, K: 'a, V: 'a> {
|
||||
/// An occupied Entry
|
||||
Occupied(OccupiedEntry<'a, K, V>),
|
||||
/// A vacant Entry
|
||||
Vacant(VacantEntry<'a, K, V>),
|
||||
Vacant(VacantEntry<'a, Q, K, V>),
|
||||
}
|
||||
|
||||
/// Possible states of a VacantEntry
|
||||
@ -1426,46 +1435,63 @@ impl<'a, K: 'a, V: 'a> Iterator for Drain<'a, K, V> {
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a, Sized? Q, K, V> Entry<'a, Q, 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>> {
|
||||
match self {
|
||||
Occupied(entry) => Ok(entry.into_mut()),
|
||||
Vacant(entry) => Err(entry),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
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 set(&mut self, mut value: V) -> V {
|
||||
pub fn insert(&mut self, mut value: V) -> V {
|
||||
let old_value = self.get_mut();
|
||||
mem::swap(&mut value, old_value);
|
||||
value
|
||||
}
|
||||
|
||||
#[stable]
|
||||
/// Takes the value out of the entry, and returns it
|
||||
pub fn take(self) -> V {
|
||||
pub fn remove(self) -> V {
|
||||
pop_internal(self.elem).1
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a, K, V> VacantEntry<'a, K, V> {
|
||||
impl<'a, Sized? Q: 'a + ToOwned<K>, K: 'a, V: 'a> VacantEntry<'a, Q, K, V> {
|
||||
#[stable]
|
||||
/// Sets the value of the entry with the VacantEntry's key,
|
||||
/// and returns a mutable reference to it
|
||||
pub fn set(self, value: V) -> &'a mut V {
|
||||
pub fn insert(self, value: V) -> &'a mut V {
|
||||
match self.elem {
|
||||
NeqElem(bucket, ib) => {
|
||||
robin_hood(bucket, ib, self.hash, self.key, value)
|
||||
robin_hood(bucket, ib, self.hash, self.key.to_owned(), value)
|
||||
}
|
||||
NoElem(bucket) => {
|
||||
bucket.put(self.hash, self.key, value).into_mut_refs().1
|
||||
bucket.put(self.hash, self.key.to_owned(), value).into_mut_refs().1
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1497,6 +1523,8 @@ 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};
|
||||
|
||||
@ -2090,11 +2118,11 @@ 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);
|
||||
assert_eq!(view.set(100), 10);
|
||||
assert_eq!(view.insert(100), 10);
|
||||
}
|
||||
}
|
||||
assert_eq!(map.get(&1).unwrap(), &100);
|
||||
@ -2102,7 +2130,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();
|
||||
@ -2114,10 +2142,10 @@ 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.take(), 30);
|
||||
assert_eq!(view.remove(), 30);
|
||||
}
|
||||
}
|
||||
assert_eq!(map.get(&3), None);
|
||||
@ -2125,10 +2153,10 @@ mod test_map {
|
||||
|
||||
|
||||
// Inexistent key (insert)
|
||||
match map.entry(10) {
|
||||
match map.entry(&10) {
|
||||
Occupied(_) => unreachable!(),
|
||||
Vacant(view) => {
|
||||
assert_eq!(*view.set(1000), 1000);
|
||||
assert_eq!(*view.insert(1000), 1000);
|
||||
}
|
||||
}
|
||||
assert_eq!(map.get(&10).unwrap(), &1000);
|
||||
@ -2156,11 +2184,11 @@ 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);
|
||||
e.take();
|
||||
e.remove();
|
||||
},
|
||||
}
|
||||
|
||||
|
@ -226,7 +226,7 @@
|
||||
//! the key has been seen or not. Normally, this would require a `find` followed by an
|
||||
//! `insert`, effectively duplicating the search effort on each insertion.
|
||||
//!
|
||||
//! When a user calls `map.entry(key)`, the map will search for the key and then yield
|
||||
//! When a user calls `map.entry(&key)`, the map will search for the key and then yield
|
||||
//! a variant of the `Entry` enum.
|
||||
//!
|
||||
//! If a `Vacant(entry)` is yielded, then the key *was not* found. In this case the
|
||||
@ -255,8 +255,8 @@
|
||||
//! let message = "she sells sea shells by the sea shore";
|
||||
//!
|
||||
//! for c in message.chars() {
|
||||
//! match count.entry(c) {
|
||||
//! Vacant(entry) => { entry.set(1u); },
|
||||
//! match count.entry(&c) {
|
||||
//! Vacant(entry) => { entry.insert(1u); },
|
||||
//! Occupied(mut entry) => *entry.get_mut() += 1,
|
||||
//! }
|
||||
//! }
|
||||
@ -290,8 +290,8 @@
|
||||
//! 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) {
|
||||
//! Vacant(entry) => entry.set(Person{id: id, blood_alcohol: 0.0}),
|
||||
//! let person = match blood_alcohol.entry(&id) {
|
||||
//! Vacant(entry) => entry.insert(Person{id: id, blood_alcohol: 0.0}),
|
||||
//! Occupied(entry) => entry.into_mut(),
|
||||
//! };
|
||||
//!
|
||||
|
@ -21,7 +21,6 @@ use ast::{Ident, Mrk, Name, SyntaxContext};
|
||||
|
||||
use std::cell::RefCell;
|
||||
use std::collections::HashMap;
|
||||
use std::collections::hash_map::Entry::{Occupied, Vacant};
|
||||
|
||||
/// The SCTable contains a table of SyntaxContext_'s. It
|
||||
/// represents a flattened tree structure, to avoid having
|
||||
@ -67,10 +66,9 @@ 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);
|
||||
* match table.mark_memo.borrow_mut().entry(key) {
|
||||
Vacant(entry) => entry.set(idx_push(&mut *table.table.borrow_mut(), Mark(m, ctxt))),
|
||||
Occupied(entry) => entry.into_mut(),
|
||||
}
|
||||
* 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))))
|
||||
}
|
||||
|
||||
/// Extend a syntax context with a given rename
|
||||
@ -86,10 +84,9 @@ fn apply_rename_internal(id: Ident,
|
||||
table: &SCTable) -> SyntaxContext {
|
||||
let key = (ctxt, id, to);
|
||||
|
||||
* match table.rename_memo.borrow_mut().entry(key) {
|
||||
Vacant(entry) => entry.set(idx_push(&mut *table.table.borrow_mut(), Rename(id, to, ctxt))),
|
||||
Occupied(entry) => entry.into_mut(),
|
||||
}
|
||||
* 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))))
|
||||
}
|
||||
|
||||
/// Apply a list of renamings to a context
|
||||
|
@ -219,9 +219,9 @@ 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.set(res[*idx].clone());
|
||||
spot.insert(res[*idx].clone());
|
||||
*idx += 1;
|
||||
}
|
||||
Occupied(..) => {
|
||||
|
@ -438,12 +438,14 @@ pub fn write_boxplot<W: Writer, T: Float + Show + FromPrimitive>(
|
||||
|
||||
/// Returns a HashMap with the number of occurrences of every element in the
|
||||
/// sequence that the iterator exposes.
|
||||
pub fn freq_count<T: Iterator<Item=U>, U: Eq+Hash>(mut iter: T) -> hash_map::HashMap<U, uint> {
|
||||
pub fn freq_count<T, U>(mut iter: T) -> hash_map::HashMap<U, uint>
|
||||
where T: Iterator<Item=U>, U: Eq + Clone + Hash
|
||||
{
|
||||
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.set(1); },
|
||||
Vacant(entry) => { entry.insert(1); },
|
||||
}
|
||||
}
|
||||
map
|
||||
|
Loading…
Reference in New Issue
Block a user