about summary refs log tree commit diff
path: root/src/libstd/collections
diff options
context:
space:
mode:
authorAlexis Beingessner <a.beingessner@gmail.com>2018-05-17 00:27:19 -0400
committerJonathan Behrens <fintelia@gmail.com>2018-09-05 12:10:09 -0400
commit6af55a7c61be881bfb56c79dcea9a56b21dad413 (patch)
tree18d8cc96813e06580be3cfad25cc43030f618a6a /src/libstd/collections
parentb0297f3043e4ed592c63c0bcc11df3655ec8cf46 (diff)
downloadrust-6af55a7c61be881bfb56c79dcea9a56b21dad413.tar.gz
rust-6af55a7c61be881bfb56c79dcea9a56b21dad413.zip
WIP: add raw_entry API to HashMap
Diffstat (limited to 'src/libstd/collections')
-rw-r--r--src/libstd/collections/hash/map.rs740
1 files changed, 703 insertions, 37 deletions
diff --git a/src/libstd/collections/hash/map.rs b/src/libstd/collections/hash/map.rs
index 91912e5f241..82bd2c695b1 100644
--- a/src/libstd/collections/hash/map.rs
+++ b/src/libstd/collections/hash/map.rs
@@ -20,7 +20,7 @@ use fmt::{self, Debug};
 use hash::{Hash, Hasher, BuildHasher, SipHasher13};
 use iter::{FromIterator, FusedIterator};
 use mem::{self, replace};
-use ops::{Deref, Index};
+use ops::{Deref, DerefMut, Index};
 use sys;
 
 use super::table::{self, Bucket, EmptyBucket, Fallibility, FullBucket, FullBucketMut, RawTable,
@@ -438,6 +438,23 @@ fn search_hashed<K, V, M, F>(table: M, hash: SafeHash, is_match: F) -> InternalE
     search_hashed_nonempty(table, hash, is_match)
 }
 
+/// Search for a pre-hashed key.
+/// If you don't already know the hash, use search or search_mut instead
+#[inline]
+fn search_hashed_mut<K, V, M, F>(table: M, hash: SafeHash, is_match: F) -> InternalEntry<K, V, M>
+    where M: DerefMut<Target = RawTable<K, V>>,
+          F: FnMut(&mut K) -> bool
+{
+    // This is the only function where capacity can be zero. To avoid
+    // undefined behavior when Bucket::new gets the raw bucket in this
+    // case, immediately return the appropriate search result.
+    if table.capacity() == 0 {
+        return InternalEntry::TableIsEmpty;
+    }
+
+    search_hashed_nonempty_mut(table, hash, is_match)
+}
+
 /// Search for a pre-hashed key when the hash map is known to be non-empty.
 #[inline]
 fn search_hashed_nonempty<K, V, M, F>(table: M, hash: SafeHash, mut is_match: F)
@@ -488,6 +505,56 @@ fn search_hashed_nonempty<K, V, M, F>(table: M, hash: SafeHash, mut is_match: F)
     }
 }
 
+/// Search for a pre-hashed key when the hash map is known to be non-empty.
+#[inline]
+fn search_hashed_nonempty_mut<K, V, M, F>(table: M, hash: SafeHash, mut is_match: F)
+    -> InternalEntry<K, V, M>
+    where M: DerefMut<Target = RawTable<K, V>>,
+          F: FnMut(&mut K) -> bool
+{
+    // Do not check the capacity as an extra branch could slow the lookup.
+
+    let size = table.size();
+    let mut probe = Bucket::new(table, hash);
+    let mut displacement = 0;
+
+    loop {
+        let mut full = match probe.peek() {
+            Empty(bucket) => {
+                // Found a hole!
+                return InternalEntry::Vacant {
+                    hash,
+                    elem: NoElem(bucket, displacement),
+                };
+            }
+            Full(bucket) => bucket,
+        };
+
+        let probe_displacement = full.displacement();
+
+        if probe_displacement < displacement {
+            // Found a luckier bucket than me.
+            // We can finish the search early if we hit any bucket
+            // with a lower distance to initial bucket than we've probed.
+            return InternalEntry::Vacant {
+                hash,
+                elem: NeqElem(full, probe_displacement),
+            };
+        }
+
+        // If the hash doesn't match, it can't be this one..
+        if hash == full.hash() {
+            // If the key doesn't match, it can't be this one..
+            if is_match(full.read_mut().0) {
+                return InternalEntry::Occupied { elem: full };
+            }
+        }
+        displacement += 1;
+        probe = full.next();
+        debug_assert!(displacement <= size);
+    }
+}
+
 fn pop_internal<K, V>(starting_bucket: FullBucketMut<K, V>)
     -> (K, V, &mut RawTable<K, V>)
 {
@@ -1484,6 +1551,47 @@ impl<K, V, S> HashMap<K, V, S>
     }
 }
 
+impl<K, V, S> HashMap<K, V, S>
+    where K: Eq + Hash,
+          S: BuildHasher
+{
+    /// Creates a raw entry builder for the HashMap.
+    ///
+    /// Raw entries provide the lowest level of control for searching and
+    /// manipulating a map. They must be manually initialized with hash and
+    /// then manually searched. After this, insertions into the entry also
+    /// still require an owned key to be provided.
+    ///
+    /// Raw entries are useful for such exotic situations as:
+    ///
+    /// * Hash memoization
+    /// * Deferring the creation of an owned key until it is known to be required
+    /// * Using a HashMap where the key type can't or shouldn't be hashed and/or compared
+    ///
+    /// Unless you are in such a situation, higher-level and more foolproof APIs like
+    /// `entry` should be preferred.
+    #[unstable(feature = "raw_entry", issue = "42069")]
+    pub fn raw_entry(&mut self) -> RawEntryBuilder<K, V, S> {
+        self.reserve(1);
+        RawEntryBuilder { map: self }
+    }
+
+    /// Creates a raw immutable entry builder for the HashMap.
+    ///
+    /// This is useful for
+    /// * Hash memoization
+    /// * Querying a HashMap where the key type can't or shouldn't be hashed and/or compared
+    ///
+    /// Unless you are in such a situation, higher-level and more foolproof APIs like
+    /// `entry` should be preferred.
+    ///
+    /// Immutable raw entries have very limited use; you might instead want `raw_entry`.
+    #[unstable(feature = "raw_entry", issue = "42069")]
+    pub fn raw_entry_immut(&self) -> RawImmutableEntryBuilder<K, V, S> {
+        RawImmutableEntryBuilder { map: self }
+    }
+}
+
 #[stable(feature = "rust1", since = "1.0.0")]
 impl<K, V, S> PartialEq for HashMap<K, V, S>
     where K: Eq + Hash,
@@ -1709,14 +1817,13 @@ impl<'a, K, V> InternalEntry<K, V, &'a mut RawTable<K, V>> {
             InternalEntry::Occupied { elem } => {
                 Some(Occupied(OccupiedEntry {
                     key: Some(key),
-                    elem,
+                    entry: RawOccupiedEntry { elem },
                 }))
             }
             InternalEntry::Vacant { hash, elem } => {
                 Some(Vacant(VacantEntry {
-                    hash,
                     key,
-                    elem,
+                    entry: RawVacantEntry { hash, elem }
                 }))
             }
             InternalEntry::TableIsEmpty => None,
@@ -1724,6 +1831,584 @@ impl<'a, K, V> InternalEntry<K, V, &'a mut RawTable<K, V>> {
     }
 }
 
+/// WIP
+#[unstable(feature = "raw_entry", issue = "42069")]
+pub struct RawEntryBuilder<'a, K: 'a, V: 'a, S: 'a> {
+    map: &'a mut HashMap<K, V, S>,
+}
+
+/// WIP
+#[unstable(feature = "raw_entry", issue = "42069")]
+pub struct RawEntryBuilderHashed<'a, K: 'a, V: 'a> {
+    map: &'a mut RawTable<K, V>,
+    hash: SafeHash,
+}
+
+/// WIP
+#[unstable(feature = "raw_entry", issue = "42069")]
+pub enum RawEntry<'a, K: 'a, V: 'a> {
+    /// WIP
+    Occupied(RawOccupiedEntry<'a, K, V>),
+    /// WIP
+    Vacant(RawVacantEntry<'a, K, V>),
+}
+
+/// WIP
+#[unstable(feature = "raw_entry", issue = "42069")]
+pub struct RawOccupiedEntry<'a, K: 'a, V: 'a> {
+    elem: FullBucket<K, V, &'a mut RawTable<K, V>>,
+}
+
+/// WIP
+#[unstable(feature = "raw_entry", issue = "42069")]
+pub struct RawVacantEntry<'a, K: 'a, V: 'a> {
+    hash: SafeHash,
+    elem: VacantEntryState<K, V, &'a mut RawTable<K, V>>,
+}
+
+/// WIP
+#[unstable(feature = "raw_entry", issue = "42069")]
+pub struct RawImmutableEntryBuilder<'a, K: 'a, V: 'a, S: 'a> {
+    map: &'a HashMap<K, V, S>,
+}
+
+/// WIP
+#[unstable(feature = "raw_entry", issue = "42069")]
+pub struct RawImmutableEntryBuilderHashed<'a, K: 'a, V: 'a> {
+    map: &'a RawTable<K, V>,
+    hash: SafeHash,
+}
+
+impl<'a, K, V, S> RawEntryBuilder<'a, K, V, S>
+    where S: BuildHasher,
+{
+    /// Initializes the raw entry builder with the hash of the given query value.
+    #[unstable(feature = "raw_entry", issue = "42069")]
+    pub fn hash_by<Q: ?Sized>(self, k: &Q) -> RawEntryBuilderHashed<'a, K, V>
+        where Q: Hash
+    {
+        self.hash_with(|mut hasher| {
+            k.hash(&mut hasher);
+            hasher.finish()
+        })
+    }
+
+    /// Initializes the raw entry builder with the hash yielded by the given function.
+    #[unstable(feature = "raw_entry", issue = "42069")]
+    pub fn hash_with<F>(self, func: F) -> RawEntryBuilderHashed<'a, K, V>
+        where F: FnOnce(S::Hasher) -> u64
+    {
+        let hasher = self.map.hash_builder.build_hasher();
+        let hash = SafeHash::new(func(hasher));
+
+        RawEntryBuilderHashed { map: &mut self.map.table, hash }
+    }
+
+    /// Searches for the location of the raw entry with the given query value.
+    #[unstable(feature = "raw_entry", issue = "42069")]
+    pub fn search_by<Q: ?Sized>(self, k: &Q) -> RawEntry<'a, K, V>
+        where K: Borrow<Q>,
+              Q: Eq + Hash
+    {
+        self.hash_by(k).search_by(k)
+    }
+}
+
+impl<'a, K, V> RawEntryBuilderHashed<'a, K, V>
+{
+    /// Searches for the location of the raw entry with the given query value.
+    ///
+    /// Note that it isn't required that the query value be hashable, as the
+    /// builder's hash is used.
+    #[unstable(feature = "raw_entry", issue = "42069")]
+    pub fn search_by<Q: ?Sized>(self, k: &Q) -> RawEntry<'a, K, V>
+        where K: Borrow<Q>,
+              Q: Eq,
+    {
+        // I don't know why we need this `&mut -> &` transform to resolve Borrow, but we do
+        self.search_with(|key| (&*key).borrow() == k)
+    }
+
+    /// Searches for the location of the raw entry with the given comparison function.
+    ///
+    /// Note that mutable access is given to each key that is visited, because
+    /// this land is truly godless, and *someone* might have a use for this.
+    #[unstable(feature = "raw_entry", issue = "42069")]
+    pub fn search_with<F>(self, func: F) -> RawEntry<'a, K, V>
+        where F: FnMut(&mut K) -> bool,
+    {
+        match search_hashed_mut(self.map, self.hash, func) {
+            InternalEntry::Occupied { elem } => {
+                RawEntry::Occupied(RawOccupiedEntry { elem })
+            }
+            InternalEntry::Vacant { hash, elem } => {
+                RawEntry::Vacant(RawVacantEntry { hash, elem })
+            }
+            InternalEntry::TableIsEmpty => {
+                unreachable!()
+            }
+        }
+    }
+}
+
+impl<'a, K, V, S> RawImmutableEntryBuilder<'a, K, V, S>
+    where S: BuildHasher,
+{
+    /// Initializes the raw entry builder with the hash of the given query value.
+    #[unstable(feature = "raw_entry", issue = "42069")]
+    pub fn hash_by<Q: ?Sized>(self, k: &Q) -> RawImmutableEntryBuilderHashed<'a, K, V>
+        where Q: Hash
+    {
+        self.hash_with(|mut hasher| {
+            k.hash(&mut hasher);
+            hasher.finish()
+        })
+    }
+
+    /// Initializes the raw entry builder with the hash yielded by the given function.
+    #[unstable(feature = "raw_entry", issue = "42069")]
+    pub fn hash_with<F>(self, func: F) -> RawImmutableEntryBuilderHashed<'a, K, V>
+        where F: FnOnce(S::Hasher) -> u64
+    {
+        let hasher = self.map.hash_builder.build_hasher();
+        let hash = SafeHash::new(func(hasher));
+
+        RawImmutableEntryBuilderHashed { map: &self.map.table, hash }
+    }
+
+    /// Searches for the location of the raw entry with the given query value.
+    #[unstable(feature = "raw_entry", issue = "42069")]
+    pub fn search_by<Q: ?Sized>(self, k: &Q) -> Option<(&'a K, &'a V)>
+        where K: Borrow<Q>,
+              Q: Eq + Hash
+    {
+        self.hash_by(k).search_by(k)
+    }
+}
+
+impl<'a, K, V> RawImmutableEntryBuilderHashed<'a, K, V>
+{
+    /// Searches for the location of the raw entry with the given query value.
+    ///
+    /// Note that it isn't required that the query value be hashable, as the
+    /// builder's hash is used.
+    #[unstable(feature = "raw_entry", issue = "42069")]
+    pub fn search_by<Q: ?Sized>(self, k: &Q) -> Option<(&'a K, &'a V)>
+        where K: Borrow<Q>,
+              Q: Eq,
+    {
+        self.search_with(|key| key.borrow() == k)
+    }
+
+    /// Searches for the location of the raw entry with the given comparison function.
+    ///
+    /// Note that mutable access is given to each key that is visited, because
+    /// this land is truly godless, and *someone* might have a use for this.
+    #[unstable(feature = "raw_entry", issue = "42069")]
+    pub fn search_with<F>(self, func: F) -> Option<(&'a K, &'a V)>
+        where F: FnMut(&K) -> bool,
+    {
+        match search_hashed(self.map, self.hash, func) {
+            InternalEntry::Occupied { elem } => {
+                Some(elem.into_refs())
+            }
+            InternalEntry::Vacant { .. } | InternalEntry::TableIsEmpty  => {
+                None
+            }
+        }
+    }
+}
+
+impl<'a, K, V> RawEntry<'a, K, V> {
+    /// Ensures a value is in the entry by inserting the default if empty, and returns
+    /// a mutable reference to the value in the entry.
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// use std::collections::HashMap;
+    ///
+    /// let mut map: HashMap<&str, u32> = HashMap::new();
+    /// map.entry("poneyland").or_insert(12);
+    ///
+    /// assert_eq!(map["poneyland"], 12);
+    ///
+    /// *map.entry("poneyland").or_insert(12) += 10;
+    /// assert_eq!(map["poneyland"], 22);
+    /// ```
+    #[unstable(feature = "raw_entry", issue = "42069")]
+    pub fn or_insert(self, default_key: K, default_val: V) -> (&'a mut K, &'a mut V) {
+        match self {
+            RawEntry::Occupied(entry) => entry.into_kv(),
+            RawEntry::Vacant(entry) => entry.insert(default_key, default_val),
+        }
+    }
+
+    /// Ensures a value is in the entry by inserting the result of the default function if empty,
+    /// and returns a mutable reference to the value in the entry.
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// use std::collections::HashMap;
+    ///
+    /// let mut map: HashMap<&str, String> = HashMap::new();
+    /// let s = "hoho".to_string();
+    ///
+    /// map.entry("poneyland").or_insert_with(|| s);
+    ///
+    /// assert_eq!(map["poneyland"], "hoho".to_string());
+    /// ```
+    #[unstable(feature = "raw_entry", issue = "42069")]
+    pub fn or_insert_with<F>(self, default: F) -> (&'a mut K, &'a mut V)
+        where F: FnOnce() -> (K, V),
+    {
+        match self {
+            RawEntry::Occupied(entry) => entry.into_kv(),
+            RawEntry::Vacant(entry) => {
+                let (k, v) = default();
+                entry.insert(k, v)
+            }
+        }
+    }
+
+    /// Provides in-place mutable access to an occupied entry before any
+    /// potential inserts into the map.
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// use std::collections::HashMap;
+    ///
+    /// let mut map: HashMap<&str, u32> = HashMap::new();
+    ///
+    /// map.entry("poneyland")
+    ///    .and_modify(|e| { *e += 1 })
+    ///    .or_insert(42);
+    /// assert_eq!(map["poneyland"], 42);
+    ///
+    /// map.entry("poneyland")
+    ///    .and_modify(|e| { *e += 1 })
+    ///    .or_insert(42);
+    /// assert_eq!(map["poneyland"], 43);
+    /// ```
+    #[unstable(feature = "raw_entry", issue = "42069")]
+    pub fn and_modify<F>(self, f: F) -> Self
+        where F: FnOnce(&mut K, &mut V)
+    {
+        match self {
+            RawEntry::Occupied(mut entry) => {
+                {
+                    let (k, v) = entry.kv_mut();
+                    f(k, v);
+                }
+                RawEntry::Occupied(entry)
+            },
+            RawEntry::Vacant(entry) => RawEntry::Vacant(entry),
+        }
+    }
+}
+
+impl<'a, K, V> RawOccupiedEntry<'a, K, V> {
+    /// Gets a reference to the key in the entry.
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// use std::collections::HashMap;
+    ///
+    /// let mut map: HashMap<&str, u32> = HashMap::new();
+    /// map.entry("poneyland").or_insert(12);
+    /// assert_eq!(map.entry("poneyland").key(), &"poneyland");
+    /// ```
+    #[unstable(feature = "raw_entry", issue = "42069")]
+    pub fn key(&self) -> &K {
+        self.elem.read().0
+    }
+
+    /// Gets a mutable reference to the key in the entry.
+    #[unstable(feature = "raw_entry", issue = "42069")]
+    pub fn key_mut(&mut self) -> &mut K {
+        self.elem.read_mut().0
+    }
+
+    /// Converts the entry into a mutable reference to the key in the entry
+    /// with a lifetime bound to the map itself.
+    #[unstable(feature = "raw_entry", issue = "42069")]
+    pub fn into_key(self) -> &'a mut K {
+        self.elem.into_mut_refs().0
+    }
+
+    /// Gets a reference to the value in the entry.
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// use std::collections::HashMap;
+    /// use std::collections::hash_map::Entry;
+    ///
+    /// let mut map: HashMap<&str, u32> = HashMap::new();
+    /// map.entry("poneyland").or_insert(12);
+    ///
+    /// if let Entry::Occupied(o) = map.entry("poneyland") {
+    ///     assert_eq!(o.get(), &12);
+    /// }
+    /// ```
+    #[unstable(feature = "raw_entry", issue = "42069")]
+    pub fn get(&self) -> &V {
+        self.elem.read().1
+    }
+
+    /// Converts the OccupiedEntry into a mutable reference to the value in the entry
+    /// with a lifetime bound to the map itself.
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// use std::collections::HashMap;
+    /// use std::collections::hash_map::Entry;
+    ///
+    /// let mut map: HashMap<&str, u32> = HashMap::new();
+    /// map.entry("poneyland").or_insert(12);
+    ///
+    /// assert_eq!(map["poneyland"], 12);
+    /// if let Entry::Occupied(o) = map.entry("poneyland") {
+    ///     *o.into_mut() += 10;
+    /// }
+    ///
+    /// assert_eq!(map["poneyland"], 22);
+    /// ```
+    #[unstable(feature = "raw_entry", issue = "42069")]
+    pub fn into_mut(self) -> &'a mut V {
+        self.elem.into_mut_refs().1
+    }
+
+    /// Gets a mutable reference to the value in the entry.
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// use std::collections::HashMap;
+    /// use std::collections::hash_map::Entry;
+    ///
+    /// let mut map: HashMap<&str, u32> = HashMap::new();
+    /// map.entry("poneyland").or_insert(12);
+    ///
+    /// assert_eq!(map["poneyland"], 12);
+    /// if let Entry::Occupied(mut o) = map.entry("poneyland") {
+    ///      *o.get_mut() += 10;
+    /// }
+    ///
+    /// assert_eq!(map["poneyland"], 22);
+    /// ```
+    #[unstable(feature = "raw_entry", issue = "42069")]
+    pub fn get_mut(&mut self) -> &mut V {
+        self.elem.read_mut().1
+    }
+
+    /// Gets a reference to the key and value in the entry.
+    #[unstable(feature = "raw_entry", issue = "42069")]
+    pub fn kv(&mut self) -> (&K, &V) {
+        self.elem.read()
+    }
+
+    /// Gets a mutable reference to the key and value in the entry.
+    #[unstable(feature = "raw_entry", issue = "42069")]
+    pub fn kv_mut(&mut self) -> (&mut K, &mut V) {
+        self.elem.read_mut()
+    }
+
+    /// Converts the OccupiedEntry into a mutable reference to the key and value in the entry
+    /// with a lifetime bound to the map itself.
+    #[unstable(feature = "raw_entry", issue = "42069")]
+    pub fn into_kv(self) -> (&'a mut K, &'a mut V) {
+        self.elem.into_mut_refs()
+    }
+
+    /// Sets the value of the entry, and returns the entry's old value.
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// use std::collections::HashMap;
+    /// use std::collections::hash_map::Entry;
+    ///
+    /// let mut map: HashMap<&str, u32> = HashMap::new();
+    /// map.entry("poneyland").or_insert(12);
+    ///
+    /// if let Entry::Occupied(mut o) = map.entry("poneyland") {
+    ///     assert_eq!(o.insert(15), 12);
+    /// }
+    ///
+    /// assert_eq!(map["poneyland"], 15);
+    /// ```
+    #[unstable(feature = "raw_entry", issue = "42069")]
+    pub fn insert(&mut self, value: V) -> V {
+        mem::replace(self.get_mut(), value)
+    }
+
+    /// Sets the value of the entry, and returns the entry's old value.
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// use std::collections::HashMap;
+    /// use std::collections::hash_map::Entry;
+    ///
+    /// let mut map: HashMap<&str, u32> = HashMap::new();
+    /// map.entry("poneyland").or_insert(12);
+    ///
+    /// if let Entry::Occupied(mut o) = map.entry("poneyland") {
+    ///     assert_eq!(o.insert(15), 12);
+    /// }
+    ///
+    /// assert_eq!(map["poneyland"], 15);
+    /// ```
+    #[unstable(feature = "raw_entry", issue = "42069")]
+    pub fn insert_key(&mut self, key: K) -> K {
+        mem::replace(self.key_mut(), key)
+    }
+
+    /// Takes the value out of the entry, and returns it.
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// use std::collections::HashMap;
+    /// use std::collections::hash_map::Entry;
+    ///
+    /// let mut map: HashMap<&str, u32> = HashMap::new();
+    /// map.entry("poneyland").or_insert(12);
+    ///
+    /// if let Entry::Occupied(o) = map.entry("poneyland") {
+    ///     assert_eq!(o.remove(), 12);
+    /// }
+    ///
+    /// assert_eq!(map.contains_key("poneyland"), false);
+    /// ```
+    #[unstable(feature = "raw_entry", issue = "42069")]
+    pub fn remove(self) -> V {
+        pop_internal(self.elem).1
+    }
+
+
+    /// Take the ownership of the key and value from the map.
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// use std::collections::HashMap;
+    /// use std::collections::hash_map::Entry;
+    ///
+    /// let mut map: HashMap<&str, u32> = HashMap::new();
+    /// map.entry("poneyland").or_insert(12);
+    ///
+    /// if let Entry::Occupied(o) = map.entry("poneyland") {
+    ///     // We delete the entry from the map.
+    ///     o.remove_entry();
+    /// }
+    ///
+    /// assert_eq!(map.contains_key("poneyland"), false);
+    /// ```
+    #[unstable(feature = "raw_entry", issue = "42069")]
+    pub fn remove_entry(self) -> (K, V) {
+        let (k, v, _) = pop_internal(self.elem);
+        (k, v)
+    }
+}
+
+impl<'a, K, V> RawVacantEntry<'a, K, V> {
+    /// Sets the value of the entry with the VacantEntry's key,
+    /// and returns a mutable reference to it.
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// use std::collections::HashMap;
+    /// use std::collections::hash_map::Entry;
+    ///
+    /// let mut map: HashMap<&str, u32> = HashMap::new();
+    ///
+    /// if let Entry::Vacant(o) = map.entry("poneyland") {
+    ///     o.insert(37);
+    /// }
+    /// assert_eq!(map["poneyland"], 37);
+    /// ```
+    #[unstable(feature = "raw_entry", issue = "42069")]
+    pub fn insert(self, key: K, value: V) -> (&'a mut K, &'a mut V) {
+        let b = match self.elem {
+            NeqElem(mut bucket, disp) => {
+                if disp >= DISPLACEMENT_THRESHOLD {
+                    bucket.table_mut().set_tag(true);
+                }
+                robin_hood(bucket, disp, self.hash, key, value)
+            },
+            NoElem(mut bucket, disp) => {
+                if disp >= DISPLACEMENT_THRESHOLD {
+                    bucket.table_mut().set_tag(true);
+                }
+                bucket.put(self.hash, key, value)
+            },
+        };
+        b.into_mut_refs()
+    }
+}
+
+#[unstable(feature = "raw_entry", issue = "42069")]
+impl<'a, K, V, S> Debug for RawEntryBuilder<'a, K, V, S> {
+    fn fmt(&self, _f: &mut fmt::Formatter) -> fmt::Result {
+        unimplemented!()
+    }
+}
+
+/// WIP
+#[unstable(feature = "raw_entry", issue = "42069")]
+impl<'a, K, V> Debug for RawEntryBuilderHashed<'a, K, V> {
+    fn fmt(&self, _f: &mut fmt::Formatter) -> fmt::Result {
+        unimplemented!()
+    }
+}
+
+/// WIP
+#[unstable(feature = "raw_entry", issue = "42069")]
+impl<'a, K, V> Debug for RawEntry<'a, K, V> {
+    fn fmt(&self, _f: &mut fmt::Formatter) -> fmt::Result {
+        unimplemented!()
+    }
+}
+
+/// WIP
+#[unstable(feature = "raw_entry", issue = "42069")]
+impl<'a, K, V> Debug for RawOccupiedEntry<'a, K, V> {
+    fn fmt(&self, _f: &mut fmt::Formatter) -> fmt::Result {
+        unimplemented!()
+    }
+}
+
+/// WIP
+#[unstable(feature = "raw_entry", issue = "42069")]
+impl<'a, K, V> Debug for RawVacantEntry<'a, K, V> {
+    fn fmt(&self, _f: &mut fmt::Formatter) -> fmt::Result {
+        unimplemented!()
+    }
+}
+
+/// WIP
+#[unstable(feature = "raw_entry", issue = "42069")]
+impl<'a, K, V, S> Debug for RawImmutableEntryBuilder<'a, K, V, S> {
+    fn fmt(&self, _f: &mut fmt::Formatter) -> fmt::Result {
+        unimplemented!()
+    }
+}
+
+/// WIP
+#[unstable(feature = "raw_entry", issue = "42069")]
+impl<'a, K, V> Debug for RawImmutableEntryBuilderHashed<'a, K, V> {
+    fn fmt(&self, _f: &mut fmt::Formatter) -> fmt::Result {
+        unimplemented!()
+    }
+}
+
 /// A view into a single entry in a map, which may either be vacant or occupied.
 ///
 /// This `enum` is constructed from the [`entry`] method on [`HashMap`].
@@ -1768,7 +2453,7 @@ impl<'a, K: 'a + Debug, V: 'a + Debug> Debug for Entry<'a, K, V> {
 #[stable(feature = "rust1", since = "1.0.0")]
 pub struct OccupiedEntry<'a, K: 'a, V: 'a> {
     key: Option<K>,
-    elem: FullBucket<K, V, &'a mut RawTable<K, V>>,
+    entry: RawOccupiedEntry<'a, K, V>,
 }
 
 #[stable(feature= "debug_hash_map", since = "1.12.0")]
@@ -1787,9 +2472,8 @@ impl<'a, K: 'a + Debug, V: 'a + Debug> Debug for OccupiedEntry<'a, K, V> {
 /// [`Entry`]: enum.Entry.html
 #[stable(feature = "rust1", since = "1.0.0")]
 pub struct VacantEntry<'a, K: 'a, V: 'a> {
-    hash: SafeHash,
     key: K,
-    elem: VacantEntryState<K, V, &'a mut RawTable<K, V>>,
+    entry: RawVacantEntry<'a, K, V>,
 }
 
 #[stable(feature= "debug_hash_map", since = "1.12.0")]
@@ -2213,7 +2897,7 @@ impl<'a, K, V> OccupiedEntry<'a, K, V> {
     /// ```
     #[stable(feature = "map_entry_keys", since = "1.10.0")]
     pub fn key(&self) -> &K {
-        self.elem.read().0
+        self.entry.key()
     }
 
     /// Take the ownership of the key and value from the map.
@@ -2236,8 +2920,7 @@ impl<'a, K, V> OccupiedEntry<'a, K, V> {
     /// ```
     #[stable(feature = "map_entry_recover_keys2", since = "1.12.0")]
     pub fn remove_entry(self) -> (K, V) {
-        let (k, v, _) = pop_internal(self.elem);
-        (k, v)
+        self.entry.remove_entry()
     }
 
     /// Gets a reference to the value in the entry.
@@ -2257,7 +2940,7 @@ impl<'a, K, V> OccupiedEntry<'a, K, V> {
     /// ```
     #[stable(feature = "rust1", since = "1.0.0")]
     pub fn get(&self) -> &V {
-        self.elem.read().1
+        self.entry.get()
     }
 
     /// Gets a mutable reference to the value in the entry.
@@ -2289,7 +2972,7 @@ impl<'a, K, V> OccupiedEntry<'a, K, V> {
     /// ```
     #[stable(feature = "rust1", since = "1.0.0")]
     pub fn get_mut(&mut self) -> &mut V {
-        self.elem.read_mut().1
+        self.entry.get_mut()
     }
 
     /// Converts the OccupiedEntry into a mutable reference to the value in the entry
@@ -2317,7 +3000,7 @@ impl<'a, K, V> OccupiedEntry<'a, K, V> {
     /// ```
     #[stable(feature = "rust1", since = "1.0.0")]
     pub fn into_mut(self) -> &'a mut V {
-        self.elem.into_mut_refs().1
+        self.entry.into_mut()
     }
 
     /// Sets the value of the entry, and returns the entry's old value.
@@ -2338,10 +3021,8 @@ impl<'a, K, V> OccupiedEntry<'a, K, V> {
     /// assert_eq!(map["poneyland"], 15);
     /// ```
     #[stable(feature = "rust1", since = "1.0.0")]
-    pub fn insert(&mut self, mut value: V) -> V {
-        let old_value = self.get_mut();
-        mem::swap(&mut value, old_value);
-        value
+    pub fn insert(&mut self, value: V) -> V {
+        self.entry.insert(value)
     }
 
     /// Takes the value out of the entry, and returns it.
@@ -2363,7 +3044,7 @@ impl<'a, K, V> OccupiedEntry<'a, K, V> {
     /// ```
     #[stable(feature = "rust1", since = "1.0.0")]
     pub fn remove(self) -> V {
-        pop_internal(self.elem).1
+        self.entry.remove()
     }
 
     /// Returns a key that was used for search.
@@ -2396,7 +3077,7 @@ impl<'a, K, V> OccupiedEntry<'a, K, V> {
     /// ```
     #[unstable(feature = "map_entry_replace", issue = "44286")]
     pub fn replace_entry(mut self, value: V) -> (K, V) {
-        let (old_key, old_value) = self.elem.read_mut();
+        let (old_key, old_value) = self.entry.kv_mut();
 
         let old_key = mem::replace(old_key, self.key.unwrap());
         let old_value = mem::replace(old_value, value);
@@ -2431,8 +3112,7 @@ impl<'a, K, V> OccupiedEntry<'a, K, V> {
     /// ```
     #[unstable(feature = "map_entry_replace", issue = "44286")]
     pub fn replace_key(mut self) -> K {
-        let (old_key, _) = self.elem.read_mut();
-        mem::replace(old_key, self.key.unwrap())
+        mem::replace(self.entry.key_mut(), self.key.unwrap())
     }
 }
 
@@ -2490,21 +3170,7 @@ impl<'a, K: 'a, V: 'a> VacantEntry<'a, K, V> {
     /// ```
     #[stable(feature = "rust1", since = "1.0.0")]
     pub fn insert(self, value: V) -> &'a mut V {
-        let b = match self.elem {
-            NeqElem(mut bucket, disp) => {
-                if disp >= DISPLACEMENT_THRESHOLD {
-                    bucket.table_mut().set_tag(true);
-                }
-                robin_hood(bucket, disp, self.hash, self.key, value)
-            },
-            NoElem(mut bucket, disp) => {
-                if disp >= DISPLACEMENT_THRESHOLD {
-                    bucket.table_mut().set_tag(true);
-                }
-                bucket.put(self.hash, self.key, value)
-            },
-        };
-        b.into_mut_refs().1
+        self.entry.insert(self.key, value).1
     }
 }
 
@@ -2715,7 +3381,7 @@ impl<K, S, Q: ?Sized> super::Recover<Q> for HashMap<K, (), S>
         match self.entry(key) {
             Occupied(mut occupied) => {
                 let key = occupied.take_key().unwrap();
-                Some(mem::replace(occupied.elem.read_mut().0, key))
+                Some(mem::replace(occupied.entry.key_mut(), key))
             }
             Vacant(vacant) => {
                 vacant.insert(());