From 25eada15740fbe12ee2cae7fc6fe8e2c228b699d Mon Sep 17 00:00:00 2001 From: Dylan Ede Date: Tue, 6 Jan 2015 16:36:30 +0000 Subject: [breaking change] Revert Entry behaviour to take keys by value. --- src/libstd/collections/hash/map.rs | 45 +++++++++++++++++--------------------- src/libstd/collections/mod.rs | 4 ++-- 2 files changed, 22 insertions(+), 27 deletions(-) (limited to 'src/libstd') diff --git a/src/libstd/collections/hash/map.rs b/src/libstd/collections/hash/map.rs index a3fc38c34e8..ae53bc61599 100644 --- a/src/libstd/collections/hash/map.rs +++ b/src/libstd/collections/hash/map.rs @@ -14,7 +14,7 @@ use self::Entry::*; use self::SearchResult::*; use self::VacantEntryState::*; -use borrow::{BorrowFrom, ToOwned}; +use borrow::BorrowFrom; use clone::Clone; use cmp::{max, Eq, PartialEq}; use default::Default; @@ -922,14 +922,12 @@ impl, V, S, H: Hasher> HashMap { #[stable] /// Gets the given key's corresponding entry in the map for in-place manipulation. - /// Regardless of whether or not `to_owned()` has been called, the key must hash the same way. - pub fn entry<'a, Q: ?Sized>(&'a mut self, key: &'a Q) -> Entry<'a, Q, K, V> - where Q: Eq + Hash + ToOwned + pub fn entry<'a>(&'a mut self, key: K) -> Entry<'a, K, V> { // Gotta resize now. self.reserve(1); - let hash = self.make_hash(key); + let hash = self.make_hash(&key); search_entry_hashed(&mut self.table, hash, key) } @@ -1142,9 +1140,8 @@ impl, V, S, H: Hasher> HashMap { } } -fn search_entry_hashed<'a, K, V, Q: ?Sized>(table: &'a mut RawTable, hash: SafeHash, k: &'a Q) - -> Entry<'a, Q, K, V> - where Q: Eq + ToOwned +fn search_entry_hashed<'a, K: Eq, V>(table: &'a mut RawTable, hash: SafeHash, k: K) + -> Entry<'a, K, V> { // Worst case, we'll find one empty bucket among `size + 1` buckets. let size = table.size(); @@ -1167,7 +1164,7 @@ fn search_entry_hashed<'a, K, V, Q: ?Sized>(table: &'a mut RawTable, hash: // hash matches? if bucket.hash() == hash { // key matches? - if *k == *BorrowFrom::borrow_from(bucket.read().0) { + if k == *bucket.read().0 { return Occupied(OccupiedEntry{ elem: bucket, }); @@ -1331,19 +1328,19 @@ pub struct OccupiedEntry<'a, K: 'a, V: 'a> { #[stable] /// A view into a single empty location in a HashMap -pub struct VacantEntry<'a, Q: ?Sized + 'a, K: 'a, V: 'a> { +pub struct VacantEntry<'a, K: 'a, V: 'a> { hash: SafeHash, - key: &'a Q, + key: K, elem: VacantEntryState>, } #[stable] /// A view into a single location in a map, which may be vacant or occupied -pub enum Entry<'a, Q: ?Sized + 'a, K: 'a, V: 'a> { +pub enum Entry<'a, K: 'a, V: 'a> { /// An occupied Entry Occupied(OccupiedEntry<'a, K, V>), /// A vacant Entry - Vacant(VacantEntry<'a, Q, K, V>), + Vacant(VacantEntry<'a, K, V>), } /// Possible states of a VacantEntry @@ -1409,10 +1406,10 @@ impl<'a, K: 'a, V: 'a> Iterator for Drain<'a, K, V> { } } -impl<'a, Q: ?Sized, K, V> Entry<'a, Q, K, V> { +impl<'a, K, V> Entry<'a, K, V> { #[unstable = "matches collection reform v2 specification, waiting for dust to settle"] /// Returns a mutable reference to the entry if occupied, or the VacantEntry if vacant - pub fn get(self) -> Result<&'a mut V, VacantEntry<'a, Q, K, V>> { + pub fn get(self) -> Result<&'a mut V, VacantEntry<'a, K, V>> { match self { Occupied(entry) => Ok(entry.into_mut()), Vacant(entry) => Err(entry), @@ -1455,17 +1452,17 @@ impl<'a, K, V> OccupiedEntry<'a, K, V> { } } -impl<'a, Q: ?Sized + 'a + ToOwned, K: 'a, V: 'a> VacantEntry<'a, Q, K, V> { +impl<'a, K: 'a, V: 'a> VacantEntry<'a, K, V> { #[stable] /// Sets the value of the entry with the VacantEntry's key, /// and returns a mutable reference to it pub fn insert(self, value: V) -> &'a mut V { match self.elem { NeqElem(bucket, ib) => { - robin_hood(bucket, ib, self.hash, self.key.to_owned(), value) + robin_hood(bucket, ib, self.hash, self.key, value) } NoElem(bucket) => { - bucket.put(self.hash, self.key.to_owned(), value).into_mut_refs().1 + bucket.put(self.hash, self.key, value).into_mut_refs().1 } } } @@ -1497,8 +1494,6 @@ mod test_map { use super::HashMap; use super::Entry::{Occupied, Vacant}; use iter::{range_inclusive, range_step_inclusive, repeat}; - use borrow::ToOwned; - use hash; use cell::RefCell; use rand::{weak_rng, Rng}; @@ -2092,7 +2087,7 @@ mod test_map { let mut map: HashMap = xs.iter().map(|&x| x).collect(); // Existing key (insert) - match map.entry(&1) { + match map.entry(1) { Vacant(_) => unreachable!(), Occupied(mut view) => { assert_eq!(view.get(), &10); @@ -2104,7 +2099,7 @@ mod test_map { // Existing key (update) - match map.entry(&2) { + match map.entry(2) { Vacant(_) => unreachable!(), Occupied(mut view) => { let v = view.get_mut(); @@ -2116,7 +2111,7 @@ mod test_map { assert_eq!(map.len(), 6); // Existing key (take) - match map.entry(&3) { + match map.entry(3) { Vacant(_) => unreachable!(), Occupied(view) => { assert_eq!(view.remove(), 30); @@ -2127,7 +2122,7 @@ mod test_map { // Inexistent key (insert) - match map.entry(&10) { + match map.entry(10) { Occupied(_) => unreachable!(), Vacant(view) => { assert_eq!(*view.insert(1000), 1000); @@ -2158,7 +2153,7 @@ mod test_map { for i in range(0u, 1000) { let x = rng.gen_range(-10, 10); - match m.entry(&x) { + match m.entry(x) { Vacant(_) => {}, Occupied(e) => { println!("{}: remove {}", i, x); diff --git a/src/libstd/collections/mod.rs b/src/libstd/collections/mod.rs index ef9d28bbbb2..9b2a4926bcb 100644 --- a/src/libstd/collections/mod.rs +++ b/src/libstd/collections/mod.rs @@ -255,7 +255,7 @@ //! let message = "she sells sea shells by the sea shore"; //! //! for c in message.chars() { -//! match count.entry(&c) { +//! match count.entry(c) { //! Vacant(entry) => { entry.insert(1u); }, //! Occupied(mut entry) => *entry.get_mut() += 1, //! } @@ -290,7 +290,7 @@ //! for id in orders.into_iter() { //! // If this is the first time we've seen this customer, initialize them //! // with no blood alcohol. Otherwise, just retrieve them. -//! let person = match blood_alcohol.entry(&id) { +//! let person = match blood_alcohol.entry(id) { //! Vacant(entry) => entry.insert(Person{id: id, blood_alcohol: 0.0}), //! Occupied(entry) => entry.into_mut(), //! }; -- cgit 1.4.1-3-g733a5 From 169fbed25179f223b730e1db5739e4a5a408ef31 Mon Sep 17 00:00:00 2001 From: Alex Crichton Date: Tue, 6 Jan 2015 10:25:12 -0800 Subject: std: Revert stability of Entry-based APIs There's been some debate over the precise form that these APIs should take, and they've undergone some changes recently, so these APIs are going to be left unstable for now to be fleshed out during the next release cycle. --- src/libcollections/btree/map.rs | 20 ++++++++++---------- src/libstd/collections/hash/map.rs | 18 +++++++----------- 2 files changed, 17 insertions(+), 21 deletions(-) (limited to 'src/libstd') diff --git a/src/libcollections/btree/map.rs b/src/libcollections/btree/map.rs index 6e8b1a662ce..0a0bb5b8765 100644 --- a/src/libcollections/btree/map.rs +++ b/src/libcollections/btree/map.rs @@ -128,8 +128,8 @@ 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. +#[unstable = "precise API still under development"] pub enum Entry<'a, K:'a, V:'a> { /// A vacant Entry Vacant(VacantEntry<'a, K, V>), @@ -137,15 +137,15 @@ pub enum Entry<'a, K:'a, V:'a> { Occupied(OccupiedEntry<'a, K, V>), } -#[stable] /// A vacant Entry. +#[unstable = "precise API still under development"] pub struct VacantEntry<'a, K:'a, V:'a> { key: K, stack: stack::SearchStack<'a, K, V, node::handle::Edge, node::handle::Leaf>, } -#[stable] /// An occupied Entry. +#[unstable = "precise API still under development"] pub struct OccupiedEntry<'a, K:'a, V:'a> { stack: stack::SearchStack<'a, K, V, node::handle::KV, node::handle::LeafOrInternal>, } @@ -1123,43 +1123,43 @@ impl<'a, K: Ord, V> Entry<'a, K, V> { } impl<'a, K: Ord, V> VacantEntry<'a, K, V> { - #[stable] /// Sets the value of the entry with the VacantEntry's key, /// and returns a mutable reference to it. + #[unstable = "matches collection reform v2 specification, waiting for dust to settle"] pub fn insert(self, value: V) -> &'a mut V { self.stack.insert(self.key, value) } } impl<'a, K: Ord, V> OccupiedEntry<'a, K, V> { - #[stable] /// Gets a reference to the value in the entry. + #[unstable = "matches collection reform v2 specification, waiting for dust to settle"] pub fn get(&self) -> &V { self.stack.peek() } - #[stable] /// Gets a mutable reference to the value in the entry. + #[unstable = "matches collection reform v2 specification, waiting for dust to settle"] pub fn get_mut(&mut self) -> &mut V { self.stack.peek_mut() } - #[stable] /// Converts the entry into a mutable reference to its value. + #[unstable = "matches collection reform v2 specification, waiting for dust to settle"] pub fn into_mut(self) -> &'a mut V { self.stack.into_top() } - #[stable] /// Sets the value of the entry with the OccupiedEntry's key, /// and returns the entry's old value. + #[unstable = "matches collection reform v2 specification, waiting for dust to settle"] pub fn insert(&mut self, mut value: V) -> V { mem::swap(self.stack.peek_mut(), &mut value); value } - #[stable] /// Takes the value of the entry out of the map, and returns it. + #[unstable = "matches collection reform v2 specification, waiting for dust to settle"] pub fn remove(self) -> V { self.stack.remove() } @@ -1361,7 +1361,7 @@ impl BTreeMap { /// assert_eq!(count["a"], 3u); /// ``` /// The key must have the same ordering before or after `.to_owned()` is called. - #[stable] + #[unstable = "precise API still under development"] pub fn entry<'a>(&'a mut self, mut key: K) -> Entry<'a, K, V> { // same basic logic of `swap` and `pop`, blended together let mut stack = stack::PartialSearchStack::new(self); diff --git a/src/libstd/collections/hash/map.rs b/src/libstd/collections/hash/map.rs index ae53bc61599..a01158fb1ed 100644 --- a/src/libstd/collections/hash/map.rs +++ b/src/libstd/collections/hash/map.rs @@ -920,8 +920,8 @@ impl, V, S, H: Hasher> HashMap { } } - #[stable] /// Gets the given key's corresponding entry in the map for in-place manipulation. + #[unstable = "precise API still being fleshed out"] pub fn entry<'a>(&'a mut self, key: K) -> Entry<'a, K, V> { // Gotta resize now. @@ -1320,22 +1320,22 @@ pub struct Drain<'a, K: 'a, V: 'a> { > } -#[stable] /// A view into a single occupied location in a HashMap +#[unstable = "precise API still being fleshed out"] pub struct OccupiedEntry<'a, K: 'a, V: 'a> { elem: FullBucket>, } -#[stable] /// A view into a single empty location in a HashMap +#[unstable = "precise API still being fleshed out"] pub struct VacantEntry<'a, K: 'a, V: 'a> { hash: SafeHash, key: K, elem: VacantEntryState>, } -#[stable] /// A view into a single location in a map, which may be vacant or occupied +#[unstable = "precise API still being fleshed out"] pub enum Entry<'a, K: 'a, V: 'a> { /// An occupied Entry Occupied(OccupiedEntry<'a, K, V>), @@ -1406,8 +1406,8 @@ impl<'a, K: 'a, V: 'a> Iterator for Drain<'a, K, V> { } } +#[unstable = "matches collection reform v2 specification, waiting for dust to settle"] impl<'a, K, V> Entry<'a, K, V> { - #[unstable = "matches collection reform v2 specification, waiting for dust to settle"] /// Returns a mutable reference to the entry if occupied, or the VacantEntry if vacant pub fn get(self) -> Result<&'a mut V, VacantEntry<'a, K, V>> { match self { @@ -1417,27 +1417,24 @@ impl<'a, K, V> Entry<'a, K, V> { } } +#[unstable = "matches collection reform v2 specification, waiting for dust to settle"] impl<'a, K, V> OccupiedEntry<'a, K, V> { - #[stable] /// Gets a reference to the value in the entry pub fn get(&self) -> &V { self.elem.read().1 } - #[stable] /// Gets a mutable reference to the value in the entry pub fn get_mut(&mut self) -> &mut V { self.elem.read_mut().1 } - #[stable] /// Converts the OccupiedEntry into a mutable reference to the value in the entry /// with a lifetime bound to the map itself pub fn into_mut(self) -> &'a mut V { self.elem.into_mut_refs().1 } - #[stable] /// Sets the value of the entry, and returns the entry's old value pub fn insert(&mut self, mut value: V) -> V { let old_value = self.get_mut(); @@ -1445,15 +1442,14 @@ impl<'a, K, V> OccupiedEntry<'a, K, V> { value } - #[stable] /// Takes the value out of the entry, and returns it pub fn remove(self) -> V { pop_internal(self.elem).1 } } +#[unstable = "matches collection reform v2 specification, waiting for dust to settle"] impl<'a, K: 'a, V: 'a> VacantEntry<'a, K, V> { - #[stable] /// Sets the value of the entry with the VacantEntry's key, /// and returns a mutable reference to it pub fn insert(self, value: V) -> &'a mut V { -- cgit 1.4.1-3-g733a5