about summary refs log tree commit diff
path: root/src/liballoc
diff options
context:
space:
mode:
Diffstat (limited to 'src/liballoc')
-rw-r--r--src/liballoc/collections/btree/map.rs81
-rw-r--r--src/liballoc/collections/btree/node.rs5
2 files changed, 40 insertions, 46 deletions
diff --git a/src/liballoc/collections/btree/map.rs b/src/liballoc/collections/btree/map.rs
index f3781db1cf7..d94c9539e6d 100644
--- a/src/liballoc/collections/btree/map.rs
+++ b/src/liballoc/collections/btree/map.rs
@@ -151,7 +151,7 @@ impl<K: Clone, V: Clone> Clone for BTreeMap<K, V> {
                     let mut out_tree = BTreeMap { root: Some(node::Root::new_leaf()), length: 0 };
 
                     {
-                        let root = out_tree.root.as_mut().unwrap();
+                        let root = out_tree.root.as_mut().unwrap(); // unwrap succeeds because we just wrapped
                         let mut out_node = match root.as_mut().force() {
                             Leaf(leaf) => leaf,
                             Internal(_) => unreachable!(),
@@ -171,14 +171,10 @@ impl<K: Clone, V: Clone> Clone for BTreeMap<K, V> {
                 }
                 Internal(internal) => {
                     let mut out_tree = clone_subtree(internal.first_edge().descend());
-                    out_tree.ensure_root_is_owned();
 
                     {
-                        // Ideally we'd use the return of ensure_root_is_owned
-                        // instead of re-unwrapping here but unfortunately that
-                        // borrows all of out_tree and we need access to the
-                        // length below.
-                        let mut out_node = out_tree.root.as_mut().unwrap().push_level();
+                        let out_root = BTreeMap::ensure_is_owned(&mut out_tree.root);
+                        let mut out_node = out_root.push_level();
                         let mut in_edge = internal.first_edge();
                         while let Ok(kv) = in_edge.right_kv() {
                             let (k, v) = kv.into_kv();
@@ -212,7 +208,7 @@ impl<K: Clone, V: Clone> Clone for BTreeMap<K, V> {
             // Ord` constraint, which this method lacks.
             BTreeMap { root: None, length: 0 }
         } else {
-            clone_subtree(self.root.as_ref().unwrap().as_ref())
+            clone_subtree(self.root.as_ref().unwrap().as_ref()) // unwrap succeeds because not empty
         }
     }
 }
@@ -243,8 +239,8 @@ where
     }
 
     fn replace(&mut self, key: K) -> Option<K> {
-        self.ensure_root_is_owned();
-        match search::search_tree::<marker::Mut<'_>, K, (), K>(self.root.as_mut()?.as_mut(), &key) {
+        let root = Self::ensure_is_owned(&mut self.root);
+        match search::search_tree::<marker::Mut<'_>, K, (), K>(root.as_mut(), &key) {
             Found(handle) => Some(mem::replace(handle.into_kv_mut().0, key)),
             GoDown(handle) => {
                 VacantEntry { key, handle, length: &mut self.length, _marker: PhantomData }
@@ -943,7 +939,6 @@ impl<K: Ord, V> BTreeMap<K, V> {
 
         // Second, we build a tree from the sorted sequence in linear time.
         self.from_sorted_iter(iter);
-        self.fix_right_edge();
     }
 
     /// Constructs a double-ended iterator over a sub-range of elements in the map.
@@ -1058,8 +1053,8 @@ impl<K: Ord, V> BTreeMap<K, V> {
     #[stable(feature = "rust1", since = "1.0.0")]
     pub fn entry(&mut self, key: K) -> Entry<'_, K, V> {
         // FIXME(@porglezomp) Avoid allocating if we don't insert
-        self.ensure_root_is_owned();
-        match search::search_tree(self.root.as_mut().unwrap().as_mut(), &key) {
+        let root = Self::ensure_is_owned(&mut self.root);
+        match search::search_tree(root.as_mut(), &key) {
             Found(handle) => {
                 Occupied(OccupiedEntry { handle, length: &mut self.length, _marker: PhantomData })
             }
@@ -1070,8 +1065,8 @@ impl<K: Ord, V> BTreeMap<K, V> {
     }
 
     fn from_sorted_iter<I: Iterator<Item = (K, V)>>(&mut self, iter: I) {
-        self.ensure_root_is_owned();
-        let mut cur_node = self.root.as_mut().unwrap().as_mut().last_leaf_edge().into_node();
+        let root = Self::ensure_is_owned(&mut self.root);
+        let mut cur_node = root.as_mut().last_leaf_edge().into_node();
         // Iterate through all key-value pairs, pushing them into nodes at the right level.
         for (key, value) in iter {
             // Try to push key-value pair into the current leaf node.
@@ -1116,11 +1111,12 @@ impl<K: Ord, V> BTreeMap<K, V> {
 
             self.length += 1;
         }
+        Self::fix_right_edge(root)
     }
 
-    fn fix_right_edge(&mut self) {
+    fn fix_right_edge(root: &mut node::Root<K, V>) {
         // Handle underfull nodes, start from the top.
-        let mut cur_node = self.root.as_mut().unwrap().as_mut();
+        let mut cur_node = root.as_mut();
         while let Internal(internal) = cur_node.force() {
             // Check if right-most child is underfull.
             let mut last_edge = internal.last_edge();
@@ -1179,16 +1175,17 @@ impl<K: Ord, V> BTreeMap<K, V> {
         }
 
         let total_num = self.len();
+        let left_root = self.root.as_mut().unwrap(); // unwrap succeeds because not empty
 
         let mut right = Self::new();
-        let right_root = right.ensure_root_is_owned();
-        for _ in 0..(self.root.as_ref().unwrap().as_ref().height()) {
+        let right_root = Self::ensure_is_owned(&mut right.root);
+        for _ in 0..left_root.height() {
             right_root.push_level();
         }
 
         {
-            let mut left_node = self.root.as_mut().unwrap().as_mut();
-            let mut right_node = right.root.as_mut().unwrap().as_mut();
+            let mut left_node = left_root.as_mut();
+            let mut right_node = right_root.as_mut();
 
             loop {
                 let mut split_edge = match search::search_node(left_node, key) {
@@ -1214,12 +1211,10 @@ impl<K: Ord, V> BTreeMap<K, V> {
             }
         }
 
-        self.fix_right_border();
-        right.fix_left_border();
+        Self::fix_right_border(left_root);
+        Self::fix_left_border(right_root);
 
-        if self.root.as_ref().unwrap().as_ref().height()
-            < right.root.as_ref().unwrap().as_ref().height()
-        {
+        if left_root.height() < right_root.height() {
             self.recalc_length();
             right.length = total_num - self.len();
         } else {
@@ -1303,23 +1298,17 @@ impl<K: Ord, V> BTreeMap<K, V> {
     }
 
     /// Removes empty levels on the top.
-    fn fix_top(&mut self) {
-        loop {
-            {
-                let node = self.root.as_ref().unwrap().as_ref();
-                if node.height() == 0 || node.len() > 0 {
-                    break;
-                }
-            }
-            self.root.as_mut().unwrap().pop_level();
+    fn fix_top(root: &mut node::Root<K, V>) {
+        while root.height() > 0 && root.as_ref().len() == 0 {
+            root.pop_level();
         }
     }
 
-    fn fix_right_border(&mut self) {
-        self.fix_top();
+    fn fix_right_border(root: &mut node::Root<K, V>) {
+        Self::fix_top(root);
 
         {
-            let mut cur_node = self.root.as_mut().unwrap().as_mut();
+            let mut cur_node = root.as_mut();
 
             while let Internal(node) = cur_node.force() {
                 let mut last_kv = node.last_kv();
@@ -1337,15 +1326,15 @@ impl<K: Ord, V> BTreeMap<K, V> {
             }
         }
 
-        self.fix_top();
+        Self::fix_top(root);
     }
 
     /// The symmetric clone of `fix_right_border`.
-    fn fix_left_border(&mut self) {
-        self.fix_top();
+    fn fix_left_border(root: &mut node::Root<K, V>) {
+        Self::fix_top(root);
 
         {
-            let mut cur_node = self.root.as_mut().unwrap().as_mut();
+            let mut cur_node = root.as_mut();
 
             while let Internal(node) = cur_node.force() {
                 let mut first_kv = node.first_kv();
@@ -1362,7 +1351,7 @@ impl<K: Ord, V> BTreeMap<K, V> {
             }
         }
 
-        self.fix_top();
+        Self::fix_top(root);
     }
 }
 
@@ -2321,9 +2310,9 @@ impl<K, V> BTreeMap<K, V> {
     }
 
     /// If the root node is the empty (non-allocated) root node, allocate our
-    /// own node.
-    fn ensure_root_is_owned(&mut self) -> &mut node::Root<K, V> {
-        self.root.get_or_insert_with(node::Root::new_leaf)
+    /// own node. Is an associated function to avoid borrowing the entire BTreeMap.
+    fn ensure_is_owned(root: &mut Option<node::Root<K, V>>) -> &mut node::Root<K, V> {
+        root.get_or_insert_with(node::Root::new_leaf)
     }
 }
 
diff --git a/src/liballoc/collections/btree/node.rs b/src/liballoc/collections/btree/node.rs
index ce74d4f8ee6..f7bd64608d6 100644
--- a/src/liballoc/collections/btree/node.rs
+++ b/src/liballoc/collections/btree/node.rs
@@ -153,6 +153,11 @@ unsafe impl<K: Sync, V: Sync> Sync for Root<K, V> {}
 unsafe impl<K: Send, V: Send> Send for Root<K, V> {}
 
 impl<K, V> Root<K, V> {
+    /// Returns the number of levels below the root.
+    pub fn height(&self) -> usize {
+        self.height
+    }
+
     /// Returns a new owned tree, with its own root node that is initially empty.
     pub fn new_leaf() -> Self {
         Root { node: BoxedNode::from_leaf(Box::new(unsafe { LeafNode::new() })), height: 0 }