]> git.lizzy.rs Git - rust.git/commitdiff
[breaking change] Update entry API as part of RFC 509.
authorBen Foppa <benjamin.foppa@gmail.com>
Sun, 4 Jan 2015 19:07:32 +0000 (14:07 -0500)
committerBen Foppa <benjamin.foppa@gmail.com>
Sun, 4 Jan 2015 20:55:54 +0000 (15:55 -0500)
20 files changed:
src/libcollections/bench.rs
src/libcollections/btree/map.rs
src/librustc/lint/builtin.rs
src/librustc/metadata/creader.rs
src/librustc/metadata/loader.rs
src/librustc/middle/const_eval.rs
src/librustc/middle/infer/freshen.rs
src/librustc/middle/infer/region_inference/graphviz.rs
src/librustc/middle/traits/fulfill.rs
src/librustc/middle/ty.rs
src/librustc/session/config.rs
src/librustc_resolve/lib.rs
src/librustc_typeck/check/_match.rs
src/librustdoc/html/render.rs
src/librustdoc/lib.rs
src/libstd/collections/hash/map.rs
src/libstd/collections/mod.rs
src/libsyntax/ext/mtwt.rs
src/libsyntax/ext/tt/macro_parser.rs
src/libtest/stats.rs

index c7164b8199cc341d6f563321e13c2430312889f9..cd4f8d203dfe94ec5d861f2af02312d440a16f28 100644 (file)
@@ -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);
     })
 }
index 3a722178bc02c90aa91de7e3486db4a85cb590f7..a9e09a584d6877d8b86c4126941f97242cd27cb5 100644 (file)
@@ -19,7 +19,7 @@
 
 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 @@ fn next_back(&mut self) -> Option<(&'a V)> { self.inner.next_back() }
 #[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 @@ pub fn entry<'a>(&'a mut self, mut key: K) -> Entry<'a, K, V> {
 #[cfg(test)]
 mod test {
     use prelude::*;
+    use std::borrow::{ToOwned, BorrowFrom};
 
     use super::{BTreeMap, Occupied, Vacant};
 
@@ -1562,11 +1586,11 @@ fn test_entry(){
         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 @@ fn test_entry(){
 
 
         // 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 @@ fn test_entry(){
         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 @@ fn test_entry(){
 
 
         // 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);
index 8f03f8821285a47c24d951abb92d114d3d651beb..ba32dbf1e4fc001416d323c1db60f55a88981353 100644 (file)
@@ -1329,8 +1329,8 @@ fn check_unused_mut_pat(&self, cx: &Context, pats: &[P<ast::Pat>]) {
                 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); },
                         }
                     }
index 5dac2bafaec3d847508de229b3244ca3a169f812..b0cf322b0688ec47baa287ca59477d45f88e7306 100644 (file)
@@ -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); },
         }
     });
index 5f554eb9c1e5c0dc577490f68704a11816d3356d..c18bd421b3b077b61946b57b615bbefd756c892d 100644 (file)
 
 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 @@ fn find_library_crate(&mut self) -> Option<Library> {
             };
             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());
index a62b134c48e71d9a1547bb398adffca87641f8d2..6671f0f72f674f44717707f3846eb640428d1bf7 100644 (file)
@@ -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),
index 0ae4a3d851e7ffaf341760b7ddc561bf0ee671b7..7488a72b4e4609382b3c9cb262d6090d7928b883 100644 (file)
@@ -66,13 +66,13 @@ fn freshen<F>(&mut self,
             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
             }
         }
index 2bf32e7bdaedee05b6d5f7e0a41b2c8ccfa1182b..98c69962bc288b6732ab1951c698d068fe10f5dd 100644 (file)
@@ -137,8 +137,8 @@ fn new(tcx: &'a ty::ctxt<'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;
                 }
             };
index 8bb7012fb075cbaed45fd423712f064e5de2dbdd..c2327adece8e04dc274e6df1ad68fbfe6a6b2469 100644 (file)
@@ -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); },
     }
 
index d168e84a01ccdb514bdf310f2f4b06c8c99559fe..4c53c360b149446caccbdec928682d8bf691fd34 100644 (file)
@@ -78,7 +78,6 @@
 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
index 1480ff016b53ddbed73e5bead8c540f6fa8eec9d..4c9bd1e3416de4edcdc05a56fcba43a262274992 100644 (file)
@@ -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()); },
         }
     }
index 3be7aa294f17a759ae795ec02a5d0e630747382c..6321486d459e65fce5de649037c968f7a6512ad9 100644 (file)
@@ -1688,15 +1688,11 @@ fn merge_import_resolution(&mut self,
         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 @@ fn upvarify(&self,
                             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 @@ fn record_def(&mut self, node_id: NodeId, (def, lp): (Def, LastPrivate)) {
                 "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 @@ fn record_def(&mut self, node_id: NodeId, (def, lp): (Def, LastPrivate)) {
                                  *entry.get(),
                                  def)[]);
             },
-            Vacant(entry) => { entry.set(def); },
+            Vacant(entry) => { entry.insert(def); },
         }
     }
 
index d8b410abf84492056bb9d57b9790eb5531cba866..56cf4acc184e5dd7613902188aefdc1cf694289c 100644 (file)
@@ -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,
index 338b9b3e0eba417c07efb5a046d3edb13f01d414..3accbbfb1a2e79124d91709b8404b667905a9371 100644 (file)
@@ -36,7 +36,6 @@
 
 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 @@ fn fold_item(&mut self, item: clean::Item) -> Option<clean::Item> {
         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 @@ fn fold_item(&mut self, item: clean::Item) -> Option<clean::Item> {
                         };
 
                         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 @@ fn build_sidebar(&self, m: &clean::Module) -> HashMap<String, Vec<String>> {
                 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);
         }
 
index 125bc21d79d067dc99f17903f953c88ebe638a21..106fe452f46a6059a931a1973681f516f3454096 100644 (file)
@@ -38,7 +38,6 @@
 
 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)
index 651f31b205da8170b28f15ab78ba6d51d3eb03e9..a6532707f3e367d74237d5f673e9ae78806bd22e 100644 (file)
@@ -14,7 +14,7 @@
 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 @@ fn last_two<A, B, C>((_, b, c): (A, B, C)) -> (B, C) { (b, c) }
         }
     }
 
-    /// 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 @@ pub fn remove<Sized? Q>(&mut self, k: &Q) -> Option<V>
     }
 }
 
-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 @@ fn size_hint(&self) -> (uint, Option<uint>) {
     }
 }
 
+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 @@ fn test_entry(){
         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 @@ fn test_entry(){
 
 
         // 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 @@ fn test_entry(){
         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 @@ fn test_entry(){
 
 
         // 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 @@ fn check(m: &HashMap<int, ()>) {
 
         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();
                 },
             }
 
index 4be83bfc6646d3ac7fa2becd36c7454964e34330..c0445fb5aea97babd873ca904f8678e4c6dcd93e 100644 (file)
 //! 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
 //! 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,
 //!     }
 //! }
 //! 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(),
 //!     };
 //!
index bac82494f28aaca0780d8f9b24ceba31fe5bf1ee..4075b208f787399d2b8b74e577d09da141188dba 100644 (file)
@@ -21,7 +21,6 @@
 
 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
index 69e473055e8e45a7be41e6dcf1fd4ddedd2c9efe..1438d152554955662f84513ac87f50fd2f2871ea 100644 (file)
@@ -219,9 +219,9 @@ fn n_rec(p_s: &ParseSess, m: &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(..) => {
index 35af0e763d7dd0711d8b3bfa8020c7fffcaed900..7e7f36f6e83fae1dbdf79b71caeffea8ff3b522b 100644 (file)
@@ -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