From c6f29b3f36c5c9acd153735de6d3788f508cfcb9 Mon Sep 17 00:00:00 2001 From: Amanieu d'Antras Date: Mon, 26 Nov 2018 16:40:37 +0100 Subject: [PATCH] Change Entry<'a, K, V, S> back to Entry<'a, K, V> This fixes a breaking change. --- src/libstd/collections/hash/map.rs | 76 ++++++++++---------------- src/libstd/collections/hash/raw/mod.rs | 9 +++ 2 files changed, 39 insertions(+), 46 deletions(-) diff --git a/src/libstd/collections/hash/map.rs b/src/libstd/collections/hash/map.rs index 3054bfa2b16f8..60ecf9090a4b9 100644 --- a/src/libstd/collections/hash/map.rs +++ b/src/libstd/collections/hash/map.rs @@ -619,19 +619,24 @@ impl HashMap /// assert_eq!(letters.get(&'y'), None); /// ``` #[stable(feature = "rust1", since = "1.0.0")] - pub fn entry(&mut self, key: K) -> Entry { + pub fn entry(&mut self, key: K) -> Entry { + // Ideally we would put this in VacantEntry::insert, but Entry is not + // generic over the BuildHasher and adding a generic parameter would be + // a breaking change. + self.reserve(1); + let hash = make_hash(&self.hash_builder, &key); if let Some(elem) = self.table.find(hash, |q| q.0.eq(&key)) { Entry::Occupied(OccupiedEntry { key: Some(key), elem, - table: self, + table: &mut self.table, }) } else { Entry::Vacant(VacantEntry { hash, key, - table: self, + table: &mut self.table, }) } } @@ -1734,20 +1739,20 @@ impl<'a, K, V, S> Debug for RawEntryBuilder<'a, K, V, S> { /// [`HashMap`]: struct.HashMap.html /// [`entry`]: struct.HashMap.html#method.entry #[stable(feature = "rust1", since = "1.0.0")] -pub enum Entry<'a, K: 'a, V: 'a, S: 'a> { +pub enum Entry<'a, K: 'a, V: 'a> { /// An occupied entry. #[stable(feature = "rust1", since = "1.0.0")] Occupied(#[stable(feature = "rust1", since = "1.0.0")] - OccupiedEntry<'a, K, V, S>), + OccupiedEntry<'a, K, V>), /// A vacant entry. #[stable(feature = "rust1", since = "1.0.0")] Vacant(#[stable(feature = "rust1", since = "1.0.0")] - VacantEntry<'a, K, V, S>), + VacantEntry<'a, K, V>), } #[stable(feature= "debug_hash_map", since = "1.12.0")] -impl<'a, K: 'a + Debug, V: 'a + Debug, S: BuildHasher> Debug for Entry<'a, K, V, S> { +impl<'a, K: 'a + Debug, V: 'a + Debug> Debug for Entry<'a, K, V> { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { match *self { Vacant(ref v) => { @@ -1769,31 +1774,29 @@ impl<'a, K: 'a + Debug, V: 'a + Debug, S: BuildHasher> Debug for Entry<'a, K, V, /// /// [`Entry`]: enum.Entry.html #[stable(feature = "rust1", since = "1.0.0")] -pub struct OccupiedEntry<'a, K: 'a, V: 'a, S: 'a> { +pub struct OccupiedEntry<'a, K: 'a, V: 'a> { key: Option, elem: Bucket<(K, V)>, - table: &'a mut HashMap, + table: &'a mut RawTable<(K, V)>, } #[stable(feature = "rust1", since = "1.0.0")] -unsafe impl<'a, K, V, S> Send for OccupiedEntry<'a, K, V, S> +unsafe impl<'a, K, V> Send for OccupiedEntry<'a, K, V> where K: Send, V: Send, - S: Send, { } #[stable(feature = "rust1", since = "1.0.0")] -unsafe impl<'a, K, V, S> Sync for OccupiedEntry<'a, K, V, S> +unsafe impl<'a, K, V> Sync for OccupiedEntry<'a, K, V> where K: Sync, V: Sync, - S: Sync, { } #[stable(feature= "debug_hash_map", since = "1.12.0")] -impl<'a, K: 'a + Debug, V: 'a + Debug, S> Debug for OccupiedEntry<'a, K, V, S> { +impl<'a, K: 'a + Debug, V: 'a + Debug> Debug for OccupiedEntry<'a, K, V> { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { f.debug_struct("OccupiedEntry") .field("key", self.key()) @@ -1807,14 +1810,14 @@ impl<'a, K: 'a + Debug, V: 'a + Debug, S> Debug for OccupiedEntry<'a, K, V, S> { /// /// [`Entry`]: enum.Entry.html #[stable(feature = "rust1", since = "1.0.0")] -pub struct VacantEntry<'a, K: 'a, V: 'a, S: 'a> { +pub struct VacantEntry<'a, K: 'a, V: 'a> { hash: u64, key: K, - table: &'a mut HashMap, + table: &'a mut RawTable<(K, V)>, } #[stable(feature= "debug_hash_map", since = "1.12.0")] -impl<'a, K: 'a + Debug, V: 'a, S> Debug for VacantEntry<'a, K, V, S> { +impl<'a, K: 'a + Debug, V: 'a> Debug for VacantEntry<'a, K, V> { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { f.debug_tuple("VacantEntry") .field(self.key()) @@ -2091,7 +2094,7 @@ impl<'a, K, V> fmt::Debug for Drain<'a, K, V> } } -impl<'a, K, V, S> Entry<'a, K, V, S> { +impl<'a, K, V> Entry<'a, K, V> { #[stable(feature = "rust1", since = "1.0.0")] /// Ensures a value is in the entry by inserting the default if empty, and returns /// a mutable reference to the value in the entry. @@ -2109,11 +2112,7 @@ impl<'a, K, V, S> Entry<'a, K, V, S> { /// *map.entry("poneyland").or_insert(10) *= 2; /// assert_eq!(map["poneyland"], 6); /// ``` - pub fn or_insert(self, default: V) -> &'a mut V - where - K: Hash, - S: BuildHasher, - { + pub fn or_insert(self, default: V) -> &'a mut V { match self { Occupied(entry) => entry.into_mut(), Vacant(entry) => entry.insert(default), @@ -2136,11 +2135,7 @@ impl<'a, K, V, S> Entry<'a, K, V, S> { /// /// assert_eq!(map["poneyland"], "hoho".to_string()); /// ``` - pub fn or_insert_with V>(self, default: F) -> &'a mut V - where - K: Hash, - S: BuildHasher, - { + pub fn or_insert_with V>(self, default: F) -> &'a mut V { match self { Occupied(entry) => entry.into_mut(), Vacant(entry) => entry.insert(default()), @@ -2200,7 +2195,7 @@ impl<'a, K, V, S> Entry<'a, K, V, S> { } -impl<'a, K, V: Default, S> Entry<'a, K, V, S> { +impl<'a, K, V: Default> Entry<'a, K, V> { #[stable(feature = "entry_or_default", since = "1.28.0")] /// Ensures a value is in the entry by inserting the default value if empty, /// and returns a mutable reference to the value in the entry. @@ -2217,11 +2212,7 @@ impl<'a, K, V: Default, S> Entry<'a, K, V, S> { /// assert_eq!(map["poneyland"], None); /// # } /// ``` - pub fn or_default(self) -> &'a mut V - where - K: Hash, - S: BuildHasher, - { + pub fn or_default(self) -> &'a mut V { match self { Occupied(entry) => entry.into_mut(), Vacant(entry) => entry.insert(Default::default()), @@ -2229,7 +2220,7 @@ impl<'a, K, V: Default, S> Entry<'a, K, V, S> { } } -impl<'a, K, V, S> OccupiedEntry<'a, K, V, S> { +impl<'a, K, V> OccupiedEntry<'a, K, V> { /// Gets a reference to the key in the entry. /// /// # Examples @@ -2267,7 +2258,7 @@ impl<'a, K, V, S> OccupiedEntry<'a, K, V, S> { #[stable(feature = "map_entry_recover_keys2", since = "1.12.0")] pub fn remove_entry(self) -> (K, V) { unsafe { - self.table.table.erase_no_drop(&self.elem); + self.table.erase_no_drop(&self.elem); self.elem.read() } } @@ -2461,7 +2452,7 @@ impl<'a, K, V, S> OccupiedEntry<'a, K, V, S> { } } -impl<'a, K: 'a, V: 'a, S: 'a> VacantEntry<'a, K, V, S> { +impl<'a, K: 'a, V: 'a> VacantEntry<'a, K, V> { /// Gets a reference to the key that would be used when inserting a value /// through the `VacantEntry`. /// @@ -2514,15 +2505,8 @@ impl<'a, K: 'a, V: 'a, S: 'a> VacantEntry<'a, K, V, S> { /// assert_eq!(map["poneyland"], 37); /// ``` #[stable(feature = "rust1", since = "1.0.0")] - pub fn insert(self, value: V) -> &'a mut V - where - K: Hash, - S: BuildHasher, - { - let hash_builder = &self.table.hash_builder; - let bucket = self.table.table.insert(self.hash, (self.key, value), |x| { - make_hash(hash_builder, &x.0) - }); + pub fn insert(self, value: V) -> &'a mut V { + let bucket = self.table.insert_no_grow(self.hash, (self.key, value)); unsafe { &mut bucket.as_mut().1 } } } diff --git a/src/libstd/collections/hash/raw/mod.rs b/src/libstd/collections/hash/raw/mod.rs index aac5207030d81..d6b614c8cbbcc 100644 --- a/src/libstd/collections/hash/raw/mod.rs +++ b/src/libstd/collections/hash/raw/mod.rs @@ -646,7 +646,16 @@ impl RawTable { #[inline] pub fn insert(&mut self, hash: u64, value: T, hasher: impl Fn(&T) -> u64) -> Bucket { self.reserve(1, hasher); + self.insert_no_grow(hash, value) + } + /// Inserts a new element into the table, without growing the table. + /// + /// There must be enough space in the table to insert the new element. + /// + /// This does not check if the given element already exists in the table. + #[inline] + pub fn insert_no_grow(&mut self, hash: u64, value: T) -> Bucket { unsafe { let index = self.find_insert_slot(hash); let bucket = self.bucket(index);