From e5b9a3b1ca6dc4813daf24267fefd55a340915af Mon Sep 17 00:00:00 2001 From: Sebastian Waisbrot Date: Tue, 23 Jun 2015 09:31:38 -0700 Subject: [PATCH 1/5] Add member operations to collections Set and Map will may the type on get, insert and remove using get_member, insert_member and remove_member. Previous to this commit, there is no way to recovering the key from a map upon removal, and it might even be useful for get because two elements that are equal are not necessarily the same, or indistinguishible. --- src/libcollections/btree/map.rs | 180 ++++++++++++++++++++++++++++- src/libcollections/vec_map.rs | 80 +++++++++++++ src/libstd/collections/hash/map.rs | 94 ++++++++++++++- src/libstd/collections/hash/set.rs | 65 +++++++++++ 4 files changed, 409 insertions(+), 10 deletions(-) diff --git a/src/libcollections/btree/map.rs b/src/libcollections/btree/map.rs index 27b10213ecd7c..92fb654dbfdfe 100644 --- a/src/libcollections/btree/map.rs +++ b/src/libcollections/btree/map.rs @@ -228,6 +228,40 @@ impl BTreeMap { } } + /// Returns a reference to the key and the value corresponding to the key. + /// + /// The key may be any borrowed form of the map's key type, but the ordering + /// on the borrowed form *must* match the ordering on the key type. + /// + /// # Examples + /// + /// ``` + /// # #![feature(collection_member)] + /// use std::collections::BTreeMap; + /// + /// let mut map = BTreeMap::new(); + /// map.insert(1, "a"); + /// assert_eq!(map.get_member(&1), Some((&1, &"a"))); + /// assert_eq!(map.get(&2), None); + /// ``` + #[unstable(feature = "collection_member", + reason="member stuff is unclear")] + pub fn get_member(&self, key: &Q) -> Option<(&K, &V)> where K: Borrow, Q: Ord { + let mut cur_node = &self.root; + loop { + match Node::search(cur_node, key) { + Found(handle) => return Some(handle.into_kv()), + GoDown(handle) => match handle.force() { + Leaf(_) => return None, + Internal(internal_handle) => { + cur_node = internal_handle.into_edge(); + continue; + } + } + } + } + } + /// Returns true if the map contains a value for the specified key. /// /// The key may be any borrowed form of the map's key type, but the ordering @@ -385,6 +419,84 @@ impl BTreeMap { } } + /// Inserts a key-value pair into the map. If the key already had a value + /// present in the map, that key and value are returned. Otherwise, + /// `None` is returned. + /// + /// # Examples + /// + /// ``` + /// # #![feature(collection_member)] + /// use std::collections::BTreeMap; + /// + /// let mut map = BTreeMap::new(); + /// assert_eq!(map.insert_member(37, "a"), None); + /// assert_eq!(map.is_empty(), false); + /// + /// map.insert(37, "b"); + /// assert_eq!(map.insert_member(37, "c"), Some((37, "b"))); + /// assert_eq!(map[&37], "c"); + /// ``` + #[unstable(feature = "collection_member", + reason="member stuff is unclear")] + pub fn insert_member(&mut self, mut key: K, mut value: V) -> Option<(K, V)> { + // This is a stack of rawptrs to nodes paired with indices, respectively + // representing the nodes and edges of our search path. We have to store rawptrs + // because as far as Rust is concerned, we can mutate aliased data with such a + // stack. It is of course correct, but what it doesn't know is that we will only + // be popping and using these ptrs one at a time in child-to-parent order. The alternative + // to doing this is to take the Nodes from their parents. This actually makes + // borrowck *really* happy and everything is pretty smooth. However, this creates + // *tons* of pointless writes, and requires us to always walk all the way back to + // the root after an insertion, even if we only needed to change a leaf. Therefore, + // we accept this potential unsafety and complexity in the name of performance. + // + // Regardless, the actual dangerous logic is completely abstracted away from BTreeMap + // by the stack module. All it can do is immutably read nodes, and ask the search stack + // to proceed down some edge by index. This makes the search logic we'll be reusing in a + // few different methods much neater, and of course drastically improves safety. + let mut stack = stack::PartialSearchStack::new(self); + + loop { + let result = stack.with(move |pusher, node| { + // Same basic logic as found in `find`, but with PartialSearchStack mediating the + // actual nodes for us + match Node::search(node, &key) { + Found(mut handle) => { + // Perfect match, swap the values and return the old one + mem::swap(handle.val_mut(), &mut value); + mem::swap(handle.key_mut(), &mut key); + Finished(Some((key, value))) + }, + GoDown(handle) => { + // We need to keep searching, try to get the search stack + // to go down further + match handle.force() { + Leaf(leaf_handle) => { + // We've reached a leaf, perform the insertion here + pusher.seal(leaf_handle).insert(key, value); + Finished(None) + } + Internal(internal_handle) => { + // We've found the subtree to insert this key/value pair in, + // keep searching + Continue((pusher.push(internal_handle), key, value)) + } + } + } + } + }); + match result { + Finished(ret) => return ret, + Continue((new_stack, renewed_key, renewed_val)) => { + stack = new_stack; + key = renewed_key; + value = renewed_val; + } + } + } + } + // Deletion is the most complicated operation for a B-Tree. // // First we do the same kind of search described in @@ -463,6 +575,52 @@ impl BTreeMap { } } } + + /// Removes a key from the map, returning the key and the value at the key + /// if the key was previously in the map. + /// + /// The key may be any borrowed form of the map's key type, but the ordering + /// on the borrowed form *must* match the ordering on the key type. + /// + /// # Examples + /// + /// ``` + /// # #![feature(collection_member)] + /// use std::collections::BTreeMap; + /// + /// let mut map = BTreeMap::new(); + /// map.insert(1, "a"); + /// assert_eq!(map.remove_member(&1), Some((1, "a"))); + /// assert_eq!(map.remove_member(&1), None); + /// ``` + #[unstable(feature = "collection_member", + reason="member stuff is unclear")] + pub fn remove_member(&mut self, key: &Q) -> Option<(K, V)> where K: Borrow, Q: Ord { + // See `swap` for a more thorough description of the stuff going on in here + let mut stack = stack::PartialSearchStack::new(self); + loop { + let result = stack.with(move |pusher, node| { + match Node::search(node, key) { + Found(handle) => { + // Perfect match. Terminate the stack here, and remove the entry + Finished(Some(pusher.seal(handle).remove_member())) + }, + GoDown(handle) => { + // We need to keep searching, try to go down the next edge + match handle.force() { + // We're at a leaf; the key isn't in here + Leaf(_) => Finished(None), + Internal(internal_handle) => Continue(pusher.push(internal_handle)) + } + } + } + }); + match result { + Finished(ret) => return ret, + Continue(new_stack) => stack = new_stack + } + } + } } #[stable(feature = "rust1", since = "1.0.0")] @@ -693,16 +851,16 @@ mod stack { impl<'a, K, V> SearchStack<'a, K, V, handle::KV, handle::Leaf> { /// Removes the key and value in the top element of the stack, then handles underflows as /// described in BTree's pop function. - fn remove_leaf(mut self) -> V { + fn remove_leaf(mut self) -> (K, V) { self.map.length -= 1; // Remove the key-value pair from the leaf that this search stack points to. // Then, note if the leaf is underfull, and promptly forget the leaf and its ptr // to avoid ownership issues. - let (value, mut underflow) = unsafe { - let (_, value) = self.top.from_raw_mut().remove_as_leaf(); + let (key, value, mut underflow) = unsafe { + let (key, value) = self.top.from_raw_mut().remove_as_leaf(); let underflow = self.top.from_raw().node().is_underfull(); - (value, underflow) + (key, value, underflow) }; loop { @@ -717,7 +875,7 @@ mod stack { self.map.depth -= 1; self.map.root.hoist_lone_child(); } - return value; + return (key, value); } Some(mut handle) => { if underflow { @@ -728,7 +886,7 @@ mod stack { } } else { // All done! - return value; + return (key, value); } } } @@ -740,6 +898,16 @@ mod stack { /// Removes the key and value in the top element of the stack, then handles underflows as /// described in BTree's pop function. pub fn remove(self) -> V { + // Ensure that the search stack goes to a leaf. This is necessary to perform deletion + // in a BTree. Note that this may put the tree in an inconsistent state (further + // described in into_leaf's comments), but this is immediately fixed by the + // removing the value we want to remove + self.into_leaf().remove_leaf().1 + } + + /// Removes the key and value in the top element of the stack, then handles underflows as + /// described in BTree's pop function. + pub fn remove_member(self) -> (K, V) { // Ensure that the search stack goes to a leaf. This is necessary to perform deletion // in a BTree. Note that this may put the tree in an inconsistent state (further // described in into_leaf's comments), but this is immediately fixed by the diff --git a/src/libcollections/vec_map.rs b/src/libcollections/vec_map.rs index 685bb5dc4b4f3..33f64db69fb55 100644 --- a/src/libcollections/vec_map.rs +++ b/src/libcollections/vec_map.rs @@ -500,6 +500,33 @@ impl VecMap { } } + /// Returns a reference to the key and the value corresponding to the key. + /// + /// # Examples + /// + /// ``` + /// # #![feature(vecmap)] + /// # #![feature(collection_member)] + /// use std::collections::VecMap; + /// + /// let mut map = VecMap::new(); + /// map.insert(1, "a"); + /// assert_eq!(map.get_member(&1), Some((&1, &"a"))); + /// assert_eq!(map.get_member(&2), None); + /// ``` + #[unstable(feature = "collection_member", + reason="member stuff is unclear")] + pub fn get_member<'a>(&self, key: &'a usize) -> Option<(&'a usize, &V)> { + if *key < self.v.len() { + match self.v[*key] { + Some(ref value) => Some((key, value)), + None => None + } + } else { + None + } + } + /// Returns true if the map contains a value for the specified key. /// /// # Examples @@ -572,6 +599,35 @@ impl VecMap { replace(&mut self.v[key], Some(value)) } + /// Inserts a key-value pair into the map. If the key already had a value + /// present in the map, that key and value are returned. Otherwise, + /// `None` is returned. + /// + /// # Examples + /// + /// ``` + /// # #![feature(vecmap)] + /// # #![feature(collection_member)] + /// use std::collections::VecMap; + /// + /// let mut map = VecMap::new(); + /// assert_eq!(map.insert_member(37, "a"), None); + /// assert_eq!(map.is_empty(), false); + /// + /// map.insert(37, "b"); + /// assert_eq!(map.insert_member(37, "c"), Some((37, "b"))); + /// assert_eq!(map[37], "c"); + /// ``` + #[unstable(feature = "collection_member", + reason="member stuff is unclear")] + pub fn insert_member(&mut self, key: usize, value: V) -> Option<(usize, V)> { + let len = self.v.len(); + if len <= key { + self.v.extend((0..key - len + 1).map(|_| None)); + } + replace(&mut self.v[key], Some(value)).map(|x| (key, x)) + } + /// Removes a key from the map, returning the value at the key if the key /// was previously in the map. /// @@ -595,6 +651,30 @@ impl VecMap { result.take() } + /// Removes a key from the map, returning the key and value at the key if + /// it was previously in the map. + /// + /// # Examples + /// + /// ``` + /// # #![feature(vecmap)] + /// # #![feature(collection_member)] + /// use std::collections::VecMap; + /// + /// let mut map = VecMap::new(); + /// map.insert(1, "a"); + /// assert_eq!(map.remove_member(&1), Some((1, "a"))); + /// assert_eq!(map.remove_member(&1), None); + /// ``` + #[stable(feature = "rust1", since = "1.0.0")] + pub fn remove_member(&mut self, key: &usize) -> Option<(usize, V)> { + if *key >= self.v.len() { + return None; + } + let result = &mut self.v[*key]; + result.take().map(|x| (*key, x)) + } + /// Gets the given key's corresponding entry in the map for in-place manipulation. /// /// # Examples diff --git a/src/libstd/collections/hash/map.rs b/src/libstd/collections/hash/map.rs index 1dca3b77f3880..a4eb600ad277b 100644 --- a/src/libstd/collections/hash/map.rs +++ b/src/libstd/collections/hash/map.rs @@ -765,7 +765,7 @@ impl HashMap /// If the key already exists, the hashtable will be returned untouched /// and a reference to the existing element will be returned. fn insert_hashed_nocheck(&mut self, hash: SafeHash, k: K, v: V) -> &mut V { - self.insert_or_replace_with(hash, k, v, |_, _, _| ()) + self.insert_or_replace_with(hash, k, v, |_, _, _, _| ()) } fn insert_or_replace_with<'a, F>(&'a mut self, @@ -774,7 +774,7 @@ impl HashMap v: V, mut found_existing: F) -> &'a mut V where - F: FnMut(&mut K, &mut V, V), + F: FnMut(&mut K, K, &mut V, V), { // Worst case, we'll find one empty bucket among `size + 1` buckets. let size = self.table.size(); @@ -797,7 +797,7 @@ impl HashMap let (bucket_k, bucket_v) = bucket.into_mut_refs(); debug_assert!(k == *bucket_k); // Key already exists. Get its reference. - found_existing(bucket_k, bucket_v, v); + found_existing(bucket_k, k, bucket_v, v); return bucket_v; } } @@ -1024,6 +1024,31 @@ impl HashMap self.drain(); } + /// Returns a reference to the key and value value corresponding to the key. + /// + /// The key may be any borrowed form of the map's key type, but + /// `Hash` and `Eq` on the borrowed form *must* match those for + /// the key type. + /// + /// # Examples + /// + /// ``` + /// # #![feature(collection_member)] + /// use std::collections::HashMap; + /// + /// let mut map = HashMap::new(); + /// map.insert(1, "a"); + /// assert_eq!(map.get_member(&1), Some((&1, &"a"))); + /// assert_eq!(map.get_member(&2), None); + /// ``` + #[unstable(feature = "collection_member", + reason="member stuff is unclear")] + pub fn get_member(&self, k: &Q) -> Option<(&K, &V)> + where K: Borrow, Q: Hash + Eq + { + self.search(k).map(|bucket| bucket.into_refs()) + } + /// Returns a reference to the value corresponding to the key. /// /// The key may be any borrowed form of the map's key type, but @@ -1117,12 +1142,43 @@ impl HashMap self.reserve(1); let mut retval = None; - self.insert_or_replace_with(hash, k, v, |_, val_ref, val| { + self.insert_or_replace_with(hash, k, v, |_, _, val_ref, val| { retval = Some(replace(val_ref, val)); }); retval } + /// Inserts a key-value pair into the map. If the key already had a value + /// present in the map, that old key and value are returned. Otherwise, + /// `None` is returned. + /// + /// # Examples + /// + /// ``` + /// # #![feature(collection_member)] + /// use std::collections::HashMap; + /// + /// let mut map = HashMap::new(); + /// assert_eq!(map.insert_member(37, "a"), None); + /// assert_eq!(map.is_empty(), false); + /// + /// map.insert(37, "b"); + /// assert_eq!(map.insert_member(37, "c"), Some((37, "b"))); + /// assert_eq!(map[&37], "c"); + /// ``` + #[unstable(feature = "collection_member", + reason="member stuff is unclear")] + pub fn insert_member(&mut self, k: K, v: V) -> Option<(K, V)> { + let hash = self.make_hash(&k); + self.reserve(1); + + let mut retval = None; + self.insert_or_replace_with(hash, k, v, |key_ref, key, val_ref, val| { + retval = Some((replace(key_ref, key), replace(val_ref, val))); + }); + retval + } + /// Removes a key from the map, returning the value at the key if the key /// was previously in the map. /// @@ -1150,6 +1206,36 @@ impl HashMap self.search_mut(k).map(|bucket| pop_internal(bucket).1) } + + /// Removes a key from the map, returning the key and the value at the key + /// if the key was previously in the map. + /// + /// The key may be any borrowed form of the map's key type, but + /// `Hash` and `Eq` on the borrowed form *must* match those for + /// the key type. + /// + /// # Examples + /// + /// ``` + /// # #![feature(collection_member)] + /// use std::collections::HashMap; + /// + /// let mut map = HashMap::new(); + /// map.insert(1, "a"); + /// assert_eq!(map.remove_member(&1), Some((1, "a"))); + /// assert_eq!(map.remove_member(&1), None); + /// ``` + #[unstable(feature = "collection_member", + reason="member stuff is unclear")] + pub fn remove_member(&mut self, k: &Q) -> Option<(K, V)> + where K: Borrow, Q: Hash + Eq + { + if self.table.size() == 0 { + return None + } + + self.search_mut(k).map(|bucket| pop_internal(bucket)) + } } fn search_entry_hashed<'a, K: Eq, V>(table: &'a mut RawTable, hash: SafeHash, k: K) diff --git a/src/libstd/collections/hash/set.rs b/src/libstd/collections/hash/set.rs index ba50b156ab230..47d60adb0e3a7 100644 --- a/src/libstd/collections/hash/set.rs +++ b/src/libstd/collections/hash/set.rs @@ -454,6 +454,25 @@ impl HashSet self.map.contains_key(value) } + /// Gets a value from a set. + /// + /// # Examples + /// + /// ``` + /// # #![feature(collection_member)] + /// use std::collections::HashSet; + /// + /// let mut set = HashSet::new(); + /// + /// assert_eq!(set.insert(2), true); + /// assert_eq!(set.get_member(&2), Some(&2)); + /// ``` + #[unstable(feature = "collection_member", + reason="member stuff is unclear")] + pub fn get_member(&mut self, value: &T) -> Option<&T> { + self.map.get_member(value).map(|x| x.0) + } + /// Returns `true` if the set has no elements in common with `other`. /// This is equivalent to checking for an empty intersection. /// @@ -539,6 +558,25 @@ impl HashSet #[stable(feature = "rust1", since = "1.0.0")] pub fn insert(&mut self, value: T) -> bool { self.map.insert(value, ()).is_none() } + /// Adds a value to the set. Returns the value that was already in the set, + /// if any. + /// + /// # Examples + /// + /// ``` + /// # #![feature(collection_member)] + /// use std::collections::HashSet; + /// + /// let mut set = HashSet::new(); + /// + /// assert_eq!(set.insert_member(2), None); + /// assert_eq!(set.insert_member(2), Some(2)); + /// assert_eq!(set.len(), 1); + /// ``` + #[unstable(feature = "collection_member", + reason="member stuff is unclear")] + pub fn insert_member(&mut self, value: T) -> Option { self.map.insert_member(value, ()).map(|x| x.0) } + /// Removes a value from the set. Returns `true` if the value was /// present in the set. /// @@ -563,6 +601,33 @@ impl HashSet { self.map.remove(value).is_some() } + + /// Removes a value from the set. Returns the value if it was + /// present in the set. + /// + /// The value may be any borrowed form of the set's value type, but + /// `Hash` and `Eq` on the borrowed form *must* match those for + /// the value type. + /// + /// # Examples + /// + /// ``` + /// # #![feature(collection_member)] + /// use std::collections::HashSet; + /// + /// let mut set = HashSet::new(); + /// + /// set.insert(2); + /// assert_eq!(set.remove_member(&2), Some(2)); + /// assert_eq!(set.remove_member(&2), None); + /// ``` + #[unstable(feature = "collection_member", + reason="member stuff is unclear")] + pub fn remove_member(&mut self, value: &Q) -> Option + where T: Borrow, Q: Hash + Eq + { + self.map.remove_member(value).map(|x| x.0) + } } #[stable(feature = "rust1", since = "1.0.0")] From 73a24b19edbaa55bf57eea460fb92eac15099d3e Mon Sep 17 00:00:00 2001 From: Sebastian Waisbrot Date: Tue, 23 Jun 2015 16:34:31 -0700 Subject: [PATCH 2/5] Break long lines --- src/libcollections/btree/map.rs | 3 ++- src/libstd/collections/hash/set.rs | 4 +++- 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/src/libcollections/btree/map.rs b/src/libcollections/btree/map.rs index 92fb654dbfdfe..da8422772b80b 100644 --- a/src/libcollections/btree/map.rs +++ b/src/libcollections/btree/map.rs @@ -595,7 +595,8 @@ impl BTreeMap { /// ``` #[unstable(feature = "collection_member", reason="member stuff is unclear")] - pub fn remove_member(&mut self, key: &Q) -> Option<(K, V)> where K: Borrow, Q: Ord { + pub fn remove_member(&mut self, key: &Q) -> Option<(K, V)> where + K: Borrow, Q: Ord { // See `swap` for a more thorough description of the stuff going on in here let mut stack = stack::PartialSearchStack::new(self); loop { diff --git a/src/libstd/collections/hash/set.rs b/src/libstd/collections/hash/set.rs index 47d60adb0e3a7..9067ba2dbe197 100644 --- a/src/libstd/collections/hash/set.rs +++ b/src/libstd/collections/hash/set.rs @@ -575,7 +575,9 @@ impl HashSet /// ``` #[unstable(feature = "collection_member", reason="member stuff is unclear")] - pub fn insert_member(&mut self, value: T) -> Option { self.map.insert_member(value, ()).map(|x| x.0) } + pub fn insert_member(&mut self, value: T) -> Option { + self.map.insert_member(value, ()).map(|x| x.0) + } /// Removes a value from the set. Returns `true` if the value was /// present in the set. From b7e20446617433c363e38e43d311d1b20f61fb99 Mon Sep 17 00:00:00 2001 From: Sebastian Waisbrot Date: Tue, 23 Jun 2015 17:05:41 -0700 Subject: [PATCH 3/5] Deduplicate code from members methods --- src/libcollections/btree/map.rs | 96 ++---------------------------- src/libcollections/vec_map.rs | 21 +------ src/libstd/collections/hash/map.rs | 17 +----- 3 files changed, 10 insertions(+), 124 deletions(-) diff --git a/src/libcollections/btree/map.rs b/src/libcollections/btree/map.rs index da8422772b80b..4617c439b7177 100644 --- a/src/libcollections/btree/map.rs +++ b/src/libcollections/btree/map.rs @@ -213,19 +213,7 @@ impl BTreeMap { /// ``` #[stable(feature = "rust1", since = "1.0.0")] pub fn get(&self, key: &Q) -> Option<&V> where K: Borrow, Q: Ord { - let mut cur_node = &self.root; - loop { - match Node::search(cur_node, key) { - Found(handle) => return Some(handle.into_kv().1), - GoDown(handle) => match handle.force() { - Leaf(_) => return None, - Internal(internal_handle) => { - cur_node = internal_handle.into_edge(); - continue; - } - } - } - } + self.get_member(key).map(|x| x.1) } /// Returns a reference to the key and the value corresponding to the key. @@ -362,61 +350,8 @@ impl BTreeMap { /// assert_eq!(map[&37], "c"); /// ``` #[stable(feature = "rust1", since = "1.0.0")] - pub fn insert(&mut self, mut key: K, mut value: V) -> Option { - // This is a stack of rawptrs to nodes paired with indices, respectively - // representing the nodes and edges of our search path. We have to store rawptrs - // because as far as Rust is concerned, we can mutate aliased data with such a - // stack. It is of course correct, but what it doesn't know is that we will only - // be popping and using these ptrs one at a time in child-to-parent order. The alternative - // to doing this is to take the Nodes from their parents. This actually makes - // borrowck *really* happy and everything is pretty smooth. However, this creates - // *tons* of pointless writes, and requires us to always walk all the way back to - // the root after an insertion, even if we only needed to change a leaf. Therefore, - // we accept this potential unsafety and complexity in the name of performance. - // - // Regardless, the actual dangerous logic is completely abstracted away from BTreeMap - // by the stack module. All it can do is immutably read nodes, and ask the search stack - // to proceed down some edge by index. This makes the search logic we'll be reusing in a - // few different methods much neater, and of course drastically improves safety. - let mut stack = stack::PartialSearchStack::new(self); - - loop { - let result = stack.with(move |pusher, node| { - // Same basic logic as found in `find`, but with PartialSearchStack mediating the - // actual nodes for us - match Node::search(node, &key) { - Found(mut handle) => { - // Perfect match, swap the values and return the old one - mem::swap(handle.val_mut(), &mut value); - Finished(Some(value)) - }, - GoDown(handle) => { - // We need to keep searching, try to get the search stack - // to go down further - match handle.force() { - Leaf(leaf_handle) => { - // We've reached a leaf, perform the insertion here - pusher.seal(leaf_handle).insert(key, value); - Finished(None) - } - Internal(internal_handle) => { - // We've found the subtree to insert this key/value pair in, - // keep searching - Continue((pusher.push(internal_handle), key, value)) - } - } - } - } - }); - match result { - Finished(ret) => return ret, - Continue((new_stack, renewed_key, renewed_val)) => { - stack = new_stack; - key = renewed_key; - value = renewed_val; - } - } - } + pub fn insert(&mut self, key: K, value: V) -> Option { + self.insert_member(key, value).map(|x| x.1) } /// Inserts a key-value pair into the map. If the key already had a value @@ -550,30 +485,7 @@ impl BTreeMap { /// ``` #[stable(feature = "rust1", since = "1.0.0")] pub fn remove(&mut self, key: &Q) -> Option where K: Borrow, Q: Ord { - // See `swap` for a more thorough description of the stuff going on in here - let mut stack = stack::PartialSearchStack::new(self); - loop { - let result = stack.with(move |pusher, node| { - match Node::search(node, key) { - Found(handle) => { - // Perfect match. Terminate the stack here, and remove the entry - Finished(Some(pusher.seal(handle).remove())) - }, - GoDown(handle) => { - // We need to keep searching, try to go down the next edge - match handle.force() { - // We're at a leaf; the key isn't in here - Leaf(_) => Finished(None), - Internal(internal_handle) => Continue(pusher.push(internal_handle)) - } - } - } - }); - match result { - Finished(ret) => return ret, - Continue(new_stack) => stack = new_stack - } - } + self.remove_member(key).map(|x| x.1) } /// Removes a key from the map, returning the key and the value at the key diff --git a/src/libcollections/vec_map.rs b/src/libcollections/vec_map.rs index 33f64db69fb55..76ffec2f54638 100644 --- a/src/libcollections/vec_map.rs +++ b/src/libcollections/vec_map.rs @@ -490,14 +490,7 @@ impl VecMap { /// ``` #[stable(feature = "rust1", since = "1.0.0")] pub fn get(&self, key: &usize) -> Option<&V> { - if *key < self.v.len() { - match self.v[*key] { - Some(ref value) => Some(value), - None => None - } - } else { - None - } + self.get_member(key).map(|x| x.1) } /// Returns a reference to the key and the value corresponding to the key. @@ -592,11 +585,7 @@ impl VecMap { /// ``` #[stable(feature = "rust1", since = "1.0.0")] pub fn insert(&mut self, key: usize, value: V) -> Option { - let len = self.v.len(); - if len <= key { - self.v.extend((0..key - len + 1).map(|_| None)); - } - replace(&mut self.v[key], Some(value)) + self.insert_member(key, value).map(|x| x.1) } /// Inserts a key-value pair into the map. If the key already had a value @@ -644,11 +633,7 @@ impl VecMap { /// ``` #[stable(feature = "rust1", since = "1.0.0")] pub fn remove(&mut self, key: &usize) -> Option { - if *key >= self.v.len() { - return None; - } - let result = &mut self.v[*key]; - result.take() + self.remove_member(key).map(|x| x.1) } /// Removes a key from the map, returning the key and value at the key if diff --git a/src/libstd/collections/hash/map.rs b/src/libstd/collections/hash/map.rs index a4eb600ad277b..a309bc27dbbf8 100644 --- a/src/libstd/collections/hash/map.rs +++ b/src/libstd/collections/hash/map.rs @@ -1069,7 +1069,7 @@ impl HashMap pub fn get(&self, k: &Q) -> Option<&V> where K: Borrow, Q: Hash + Eq { - self.search(k).map(|bucket| bucket.into_refs().1) + self.get_member(k).map(|x| x.1) } /// Returns true if the map contains a value for the specified key. @@ -1138,14 +1138,7 @@ impl HashMap /// ``` #[stable(feature = "rust1", since = "1.0.0")] pub fn insert(&mut self, k: K, v: V) -> Option { - let hash = self.make_hash(&k); - self.reserve(1); - - let mut retval = None; - self.insert_or_replace_with(hash, k, v, |_, _, val_ref, val| { - retval = Some(replace(val_ref, val)); - }); - retval + self.insert_member(k, v).map(|x| x.1) } /// Inserts a key-value pair into the map. If the key already had a value @@ -1200,11 +1193,7 @@ impl HashMap pub fn remove(&mut self, k: &Q) -> Option where K: Borrow, Q: Hash + Eq { - if self.table.size() == 0 { - return None - } - - self.search_mut(k).map(|bucket| pop_internal(bucket).1) + self.remove_member(k).map(|x| x.1) } /// Removes a key from the map, returning the key and the value at the key From b4f01ffef9961d20adb17d9c4de9c04a12fb8d74 Mon Sep 17 00:00:00 2001 From: Sebastian Waisbrot Date: Tue, 23 Jun 2015 21:09:04 -0700 Subject: [PATCH 4/5] Rename member suffix for keyed prefix For sets, use item suffix instead. Also add keyed_get_mut. --- src/libcollections/btree/map.rs | 75 +++++++++++++++++++++--------- src/libcollections/vec_map.rs | 63 +++++++++++++++++-------- src/libstd/collections/hash/map.rs | 75 +++++++++++++++++++++--------- src/libstd/collections/hash/set.rs | 40 ++++++++-------- 4 files changed, 168 insertions(+), 85 deletions(-) diff --git a/src/libcollections/btree/map.rs b/src/libcollections/btree/map.rs index 4617c439b7177..f9a197acaaaac 100644 --- a/src/libcollections/btree/map.rs +++ b/src/libcollections/btree/map.rs @@ -213,7 +213,7 @@ impl BTreeMap { /// ``` #[stable(feature = "rust1", since = "1.0.0")] pub fn get(&self, key: &Q) -> Option<&V> where K: Borrow, Q: Ord { - self.get_member(key).map(|x| x.1) + self.keyed_get(key).map(|x| x.1) } /// Returns a reference to the key and the value corresponding to the key. @@ -224,17 +224,17 @@ impl BTreeMap { /// # Examples /// /// ``` - /// # #![feature(collection_member)] + /// # #![feature(collection_keyed)] /// use std::collections::BTreeMap; /// /// let mut map = BTreeMap::new(); /// map.insert(1, "a"); - /// assert_eq!(map.get_member(&1), Some((&1, &"a"))); + /// assert_eq!(map.keyed_get(&1), Some((&1, &"a"))); /// assert_eq!(map.get(&2), None); /// ``` - #[unstable(feature = "collection_member", - reason="member stuff is unclear")] - pub fn get_member(&self, key: &Q) -> Option<(&K, &V)> where K: Borrow, Q: Ord { + #[unstable(feature = "collection_keyed", + reason="keyed was recently added")] + pub fn keyed_get(&self, key: &Q) -> Option<(&K, &V)> where K: Borrow, Q: Ord { let mut cur_node = &self.root; loop { match Node::search(cur_node, key) { @@ -290,12 +290,41 @@ impl BTreeMap { // See `get` for implementation notes, this is basically a copy-paste with mut's added #[stable(feature = "rust1", since = "1.0.0")] pub fn get_mut(&mut self, key: &Q) -> Option<&mut V> where K: Borrow, Q: Ord { + self.keyed_get_mut(key).map(|x| x.1) + } + + /// Returns a mutable reference to the value corresponding to the key. + /// + /// The key may be any borrowed form of the map's key type, but the ordering + /// on the borrowed form *must* match the ordering on the key type. + /// + /// # Examples + /// + /// ``` + /// # #![feature(collection_keyed)] + /// use std::collections::BTreeMap; + /// + /// let mut map = BTreeMap::new(); + /// map.insert(1, "a"); + /// if let Some((key, x)) = map.keyed_get_mut(&1) { + /// assert_eq!(key, &1); + /// *x = "b"; + /// } + /// assert_eq!(map[&1], "b"); + /// ``` + // See `keyed_get` for implementation notes, this is basically a copy-paste with mut's added + #[unstable(feature = "collection_keyed", + reason="keyed was recently added")] + pub fn keyed_get_mut(&mut self, key: &Q) -> Option<(&K, &mut V)> where K: Borrow, Q: Ord { // temp_node is a Borrowck hack for having a mutable value outlive a loop iteration let mut temp_node = &mut self.root; loop { let cur_node = temp_node; match Node::search(cur_node, key) { - Found(handle) => return Some(handle.into_kv_mut().1), + Found(handle) => { + let (key, value) = handle.into_kv_mut(); + return Some((&*key, value)); + }, GoDown(handle) => match handle.force() { Leaf(_) => return None, Internal(internal_handle) => { @@ -351,7 +380,7 @@ impl BTreeMap { /// ``` #[stable(feature = "rust1", since = "1.0.0")] pub fn insert(&mut self, key: K, value: V) -> Option { - self.insert_member(key, value).map(|x| x.1) + self.keyed_insert(key, value).map(|x| x.1) } /// Inserts a key-value pair into the map. If the key already had a value @@ -361,20 +390,20 @@ impl BTreeMap { /// # Examples /// /// ``` - /// # #![feature(collection_member)] + /// # #![feature(collection_keyed)] /// use std::collections::BTreeMap; /// /// let mut map = BTreeMap::new(); - /// assert_eq!(map.insert_member(37, "a"), None); + /// assert_eq!(map.keyed_insert(37, "a"), None); /// assert_eq!(map.is_empty(), false); /// /// map.insert(37, "b"); - /// assert_eq!(map.insert_member(37, "c"), Some((37, "b"))); + /// assert_eq!(map.keyed_insert(37, "c"), Some((37, "b"))); /// assert_eq!(map[&37], "c"); /// ``` - #[unstable(feature = "collection_member", - reason="member stuff is unclear")] - pub fn insert_member(&mut self, mut key: K, mut value: V) -> Option<(K, V)> { + #[unstable(feature = "collection_keyed", + reason="keyed was recently added")] + pub fn keyed_insert(&mut self, mut key: K, mut value: V) -> Option<(K, V)> { // This is a stack of rawptrs to nodes paired with indices, respectively // representing the nodes and edges of our search path. We have to store rawptrs // because as far as Rust is concerned, we can mutate aliased data with such a @@ -485,7 +514,7 @@ impl BTreeMap { /// ``` #[stable(feature = "rust1", since = "1.0.0")] pub fn remove(&mut self, key: &Q) -> Option where K: Borrow, Q: Ord { - self.remove_member(key).map(|x| x.1) + self.keyed_remove(key).map(|x| x.1) } /// Removes a key from the map, returning the key and the value at the key @@ -497,17 +526,17 @@ impl BTreeMap { /// # Examples /// /// ``` - /// # #![feature(collection_member)] + /// # #![feature(collection_keyed)] /// use std::collections::BTreeMap; /// /// let mut map = BTreeMap::new(); /// map.insert(1, "a"); - /// assert_eq!(map.remove_member(&1), Some((1, "a"))); - /// assert_eq!(map.remove_member(&1), None); + /// assert_eq!(map.keyed_remove(&1), Some((1, "a"))); + /// assert_eq!(map.keyed_remove(&1), None); /// ``` - #[unstable(feature = "collection_member", - reason="member stuff is unclear")] - pub fn remove_member(&mut self, key: &Q) -> Option<(K, V)> where + #[unstable(feature = "collection_keyed", + reason="keyed was recently added")] + pub fn keyed_remove(&mut self, key: &Q) -> Option<(K, V)> where K: Borrow, Q: Ord { // See `swap` for a more thorough description of the stuff going on in here let mut stack = stack::PartialSearchStack::new(self); @@ -516,7 +545,7 @@ impl BTreeMap { match Node::search(node, key) { Found(handle) => { // Perfect match. Terminate the stack here, and remove the entry - Finished(Some(pusher.seal(handle).remove_member())) + Finished(Some(pusher.seal(handle).keyed_remove())) }, GoDown(handle) => { // We need to keep searching, try to go down the next edge @@ -820,7 +849,7 @@ mod stack { /// Removes the key and value in the top element of the stack, then handles underflows as /// described in BTree's pop function. - pub fn remove_member(self) -> (K, V) { + pub fn keyed_remove(self) -> (K, V) { // Ensure that the search stack goes to a leaf. This is necessary to perform deletion // in a BTree. Note that this may put the tree in an inconsistent state (further // described in into_leaf's comments), but this is immediately fixed by the diff --git a/src/libcollections/vec_map.rs b/src/libcollections/vec_map.rs index 76ffec2f54638..bb6076d152083 100644 --- a/src/libcollections/vec_map.rs +++ b/src/libcollections/vec_map.rs @@ -490,7 +490,7 @@ impl VecMap { /// ``` #[stable(feature = "rust1", since = "1.0.0")] pub fn get(&self, key: &usize) -> Option<&V> { - self.get_member(key).map(|x| x.1) + self.keyed_get(key).map(|x| x.1) } /// Returns a reference to the key and the value corresponding to the key. @@ -499,17 +499,17 @@ impl VecMap { /// /// ``` /// # #![feature(vecmap)] - /// # #![feature(collection_member)] + /// # #![feature(collection_keyed)] /// use std::collections::VecMap; /// /// let mut map = VecMap::new(); /// map.insert(1, "a"); - /// assert_eq!(map.get_member(&1), Some((&1, &"a"))); - /// assert_eq!(map.get_member(&2), None); + /// assert_eq!(map.keyed_get(&1), Some((&1, &"a"))); + /// assert_eq!(map.keyed_get(&2), None); /// ``` - #[unstable(feature = "collection_member", - reason="member stuff is unclear")] - pub fn get_member<'a>(&self, key: &'a usize) -> Option<(&'a usize, &V)> { + #[unstable(feature = "collection_keyed", + reason="keyed was recently added")] + pub fn keyed_get<'a>(&self, key: &'a usize) -> Option<(&'a usize, &V)> { if *key < self.v.len() { match self.v[*key] { Some(ref value) => Some((key, value)), @@ -556,9 +556,32 @@ impl VecMap { /// ``` #[stable(feature = "rust1", since = "1.0.0")] pub fn get_mut(&mut self, key: &usize) -> Option<&mut V> { + self.keyed_get_mut(key).map(|x| x.1) + } + + /// Returns a mutable reference to the value corresponding to the key. + /// + /// # Examples + /// + /// ``` + /// # #![feature(collection_keyed)] + /// # #![feature(vecmap)] + /// use std::collections::VecMap; + /// + /// let mut map = VecMap::new(); + /// map.insert(1, "a"); + /// if let Some((key, x)) = map.keyed_get_mut(&1) { + /// assert_eq!(key, &1); + /// *x = "b"; + /// } + /// assert_eq!(map[1], "b"); + /// ``` + #[unstable(feature = "collection_keyed", + reason="keyed was recently added")] + pub fn keyed_get_mut<'a>(&mut self, key: &'a usize) -> Option<(&'a usize, &mut V)> { if *key < self.v.len() { match *(&mut self.v[*key]) { - Some(ref mut value) => Some(value), + Some(ref mut value) => Some((key, value)), None => None } } else { @@ -585,7 +608,7 @@ impl VecMap { /// ``` #[stable(feature = "rust1", since = "1.0.0")] pub fn insert(&mut self, key: usize, value: V) -> Option { - self.insert_member(key, value).map(|x| x.1) + self.keyed_insert(key, value).map(|x| x.1) } /// Inserts a key-value pair into the map. If the key already had a value @@ -596,20 +619,20 @@ impl VecMap { /// /// ``` /// # #![feature(vecmap)] - /// # #![feature(collection_member)] + /// # #![feature(collection_keyed)] /// use std::collections::VecMap; /// /// let mut map = VecMap::new(); - /// assert_eq!(map.insert_member(37, "a"), None); + /// assert_eq!(map.keyed_insert(37, "a"), None); /// assert_eq!(map.is_empty(), false); /// /// map.insert(37, "b"); - /// assert_eq!(map.insert_member(37, "c"), Some((37, "b"))); + /// assert_eq!(map.keyed_insert(37, "c"), Some((37, "b"))); /// assert_eq!(map[37], "c"); /// ``` - #[unstable(feature = "collection_member", - reason="member stuff is unclear")] - pub fn insert_member(&mut self, key: usize, value: V) -> Option<(usize, V)> { + #[unstable(feature = "collection_keyed", + reason="keyed was recently added")] + pub fn keyed_insert(&mut self, key: usize, value: V) -> Option<(usize, V)> { let len = self.v.len(); if len <= key { self.v.extend((0..key - len + 1).map(|_| None)); @@ -633,7 +656,7 @@ impl VecMap { /// ``` #[stable(feature = "rust1", since = "1.0.0")] pub fn remove(&mut self, key: &usize) -> Option { - self.remove_member(key).map(|x| x.1) + self.keyed_remove(key).map(|x| x.1) } /// Removes a key from the map, returning the key and value at the key if @@ -643,16 +666,16 @@ impl VecMap { /// /// ``` /// # #![feature(vecmap)] - /// # #![feature(collection_member)] + /// # #![feature(collection_keyed)] /// use std::collections::VecMap; /// /// let mut map = VecMap::new(); /// map.insert(1, "a"); - /// assert_eq!(map.remove_member(&1), Some((1, "a"))); - /// assert_eq!(map.remove_member(&1), None); + /// assert_eq!(map.keyed_remove(&1), Some((1, "a"))); + /// assert_eq!(map.keyed_remove(&1), None); /// ``` #[stable(feature = "rust1", since = "1.0.0")] - pub fn remove_member(&mut self, key: &usize) -> Option<(usize, V)> { + pub fn keyed_remove(&mut self, key: &usize) -> Option<(usize, V)> { if *key >= self.v.len() { return None; } diff --git a/src/libstd/collections/hash/map.rs b/src/libstd/collections/hash/map.rs index a309bc27dbbf8..8ef3624c13a20 100644 --- a/src/libstd/collections/hash/map.rs +++ b/src/libstd/collections/hash/map.rs @@ -1033,17 +1033,17 @@ impl HashMap /// # Examples /// /// ``` - /// # #![feature(collection_member)] + /// # #![feature(collection_keyed)] /// use std::collections::HashMap; /// /// let mut map = HashMap::new(); /// map.insert(1, "a"); - /// assert_eq!(map.get_member(&1), Some((&1, &"a"))); - /// assert_eq!(map.get_member(&2), None); + /// assert_eq!(map.keyed_get(&1), Some((&1, &"a"))); + /// assert_eq!(map.keyed_get(&2), None); /// ``` - #[unstable(feature = "collection_member", - reason="member stuff is unclear")] - pub fn get_member(&self, k: &Q) -> Option<(&K, &V)> + #[unstable(feature = "collection_keyed", + reason="keyed was recently added")] + pub fn keyed_get(&self, k: &Q) -> Option<(&K, &V)> where K: Borrow, Q: Hash + Eq { self.search(k).map(|bucket| bucket.into_refs()) @@ -1069,7 +1069,7 @@ impl HashMap pub fn get(&self, k: &Q) -> Option<&V> where K: Borrow, Q: Hash + Eq { - self.get_member(k).map(|x| x.1) + self.keyed_get(k).map(|x| x.1) } /// Returns true if the map contains a value for the specified key. @@ -1117,7 +1117,38 @@ impl HashMap pub fn get_mut(&mut self, k: &Q) -> Option<&mut V> where K: Borrow, Q: Hash + Eq { - self.search_mut(k).map(|bucket| bucket.into_mut_refs().1) + self.keyed_get_mut(k).map(|x| x.1) + } + + /// Returns a mutable reference to the value corresponding to the key. + /// + /// The key may be any borrowed form of the map's key type, but + /// `Hash` and `Eq` on the borrowed form *must* match those for + /// the key type. + /// + /// # Examples + /// + /// ``` + /// # #![feature(collection_keyed)] + /// use std::collections::HashMap; + /// + /// let mut map = HashMap::new(); + /// map.insert(1, "a"); + /// if let Some((key, x)) = map.keyed_get_mut(&1) { + /// assert_eq!(key, &1); + /// *x = "b"; + /// } + /// assert_eq!(map[&1], "b"); + /// ``` + #[unstable(feature = "collection_keyed", + reason="keyed was recently added")] + pub fn keyed_get_mut(&mut self, k: &Q) -> Option<(&K, &mut V)> + where K: Borrow, Q: Hash + Eq + { + self.search_mut(k).map(|bucket| { + let (k, v) = bucket.into_mut_refs(); + (&*k, v) + }) } /// Inserts a key-value pair into the map. If the key already had a value @@ -1138,7 +1169,7 @@ impl HashMap /// ``` #[stable(feature = "rust1", since = "1.0.0")] pub fn insert(&mut self, k: K, v: V) -> Option { - self.insert_member(k, v).map(|x| x.1) + self.keyed_insert(k, v).map(|x| x.1) } /// Inserts a key-value pair into the map. If the key already had a value @@ -1148,20 +1179,20 @@ impl HashMap /// # Examples /// /// ``` - /// # #![feature(collection_member)] + /// # #![feature(collection_keyed)] /// use std::collections::HashMap; /// /// let mut map = HashMap::new(); - /// assert_eq!(map.insert_member(37, "a"), None); + /// assert_eq!(map.keyed_insert(37, "a"), None); /// assert_eq!(map.is_empty(), false); /// /// map.insert(37, "b"); - /// assert_eq!(map.insert_member(37, "c"), Some((37, "b"))); + /// assert_eq!(map.keyed_insert(37, "c"), Some((37, "b"))); /// assert_eq!(map[&37], "c"); /// ``` - #[unstable(feature = "collection_member", - reason="member stuff is unclear")] - pub fn insert_member(&mut self, k: K, v: V) -> Option<(K, V)> { + #[unstable(feature = "collection_keyed", + reason="keyed was recently added")] + pub fn keyed_insert(&mut self, k: K, v: V) -> Option<(K, V)> { let hash = self.make_hash(&k); self.reserve(1); @@ -1193,7 +1224,7 @@ impl HashMap pub fn remove(&mut self, k: &Q) -> Option where K: Borrow, Q: Hash + Eq { - self.remove_member(k).map(|x| x.1) + self.keyed_remove(k).map(|x| x.1) } /// Removes a key from the map, returning the key and the value at the key @@ -1206,17 +1237,17 @@ impl HashMap /// # Examples /// /// ``` - /// # #![feature(collection_member)] + /// # #![feature(collection_keyed)] /// use std::collections::HashMap; /// /// let mut map = HashMap::new(); /// map.insert(1, "a"); - /// assert_eq!(map.remove_member(&1), Some((1, "a"))); - /// assert_eq!(map.remove_member(&1), None); + /// assert_eq!(map.keyed_remove(&1), Some((1, "a"))); + /// assert_eq!(map.keyed_remove(&1), None); /// ``` - #[unstable(feature = "collection_member", - reason="member stuff is unclear")] - pub fn remove_member(&mut self, k: &Q) -> Option<(K, V)> + #[unstable(feature = "collection_keyed", + reason="keyed was recently added")] + pub fn keyed_remove(&mut self, k: &Q) -> Option<(K, V)> where K: Borrow, Q: Hash + Eq { if self.table.size() == 0 { diff --git a/src/libstd/collections/hash/set.rs b/src/libstd/collections/hash/set.rs index 9067ba2dbe197..fce3bc38a4adf 100644 --- a/src/libstd/collections/hash/set.rs +++ b/src/libstd/collections/hash/set.rs @@ -459,18 +459,18 @@ impl HashSet /// # Examples /// /// ``` - /// # #![feature(collection_member)] + /// # #![feature(collection_keyed)] /// use std::collections::HashSet; /// /// let mut set = HashSet::new(); /// /// assert_eq!(set.insert(2), true); - /// assert_eq!(set.get_member(&2), Some(&2)); + /// assert_eq!(set.get(&2), Some(&2)); /// ``` - #[unstable(feature = "collection_member", - reason="member stuff is unclear")] - pub fn get_member(&mut self, value: &T) -> Option<&T> { - self.map.get_member(value).map(|x| x.0) + #[unstable(feature = "collection_keyed", + reason="keyed was recently added")] + pub fn get(&mut self, value: &T) -> Option<&T> { + self.map.keyed_get(value).map(|x| x.0) } /// Returns `true` if the set has no elements in common with `other`. @@ -564,19 +564,19 @@ impl HashSet /// # Examples /// /// ``` - /// # #![feature(collection_member)] + /// # #![feature(collection_keyed)] /// use std::collections::HashSet; /// /// let mut set = HashSet::new(); /// - /// assert_eq!(set.insert_member(2), None); - /// assert_eq!(set.insert_member(2), Some(2)); + /// assert_eq!(set.insert_item(2), None); + /// assert_eq!(set.insert_item(2), Some(2)); /// assert_eq!(set.len(), 1); /// ``` - #[unstable(feature = "collection_member", - reason="member stuff is unclear")] - pub fn insert_member(&mut self, value: T) -> Option { - self.map.insert_member(value, ()).map(|x| x.0) + #[unstable(feature = "collection_keyed", + reason="keyed was recently added")] + pub fn insert_item(&mut self, value: T) -> Option { + self.map.keyed_insert(value, ()).map(|x| x.0) } /// Removes a value from the set. Returns `true` if the value was @@ -614,21 +614,21 @@ impl HashSet /// # Examples /// /// ``` - /// # #![feature(collection_member)] + /// # #![feature(collection_keyed)] /// use std::collections::HashSet; /// /// let mut set = HashSet::new(); /// /// set.insert(2); - /// assert_eq!(set.remove_member(&2), Some(2)); - /// assert_eq!(set.remove_member(&2), None); + /// assert_eq!(set.remove_item(&2), Some(2)); + /// assert_eq!(set.remove_item(&2), None); /// ``` - #[unstable(feature = "collection_member", - reason="member stuff is unclear")] - pub fn remove_member(&mut self, value: &Q) -> Option + #[unstable(feature = "collection_keyed", + reason="keyed was recently added")] + pub fn remove_item(&mut self, value: &Q) -> Option where T: Borrow, Q: Hash + Eq { - self.map.remove_member(value).map(|x| x.0) + self.map.keyed_remove(value).map(|x| x.0) } } From f56b704689fca0c57d05ebdec0e028dd67f84b04 Mon Sep 17 00:00:00 2001 From: Sebastian Waisbrot Date: Wed, 24 Jun 2015 00:37:30 -0700 Subject: [PATCH 5/5] Break down long line --- src/libcollections/btree/map.rs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/libcollections/btree/map.rs b/src/libcollections/btree/map.rs index f9a197acaaaac..bbf632d97fbdf 100644 --- a/src/libcollections/btree/map.rs +++ b/src/libcollections/btree/map.rs @@ -315,7 +315,8 @@ impl BTreeMap { // See `keyed_get` for implementation notes, this is basically a copy-paste with mut's added #[unstable(feature = "collection_keyed", reason="keyed was recently added")] - pub fn keyed_get_mut(&mut self, key: &Q) -> Option<(&K, &mut V)> where K: Borrow, Q: Ord { + pub fn keyed_get_mut(&mut self, key: &Q) -> Option<(&K, &mut V)> where + K: Borrow, Q: Ord { // temp_node is a Borrowck hack for having a mutable value outlive a loop iteration let mut temp_node = &mut self.root; loop {