]> git.lizzy.rs Git - rust.git/commitdiff
auto merge of #19782 : gereeter/rust/cleanup-btree-node, r=Gankro
authorbors <bors@rust-lang.org>
Tue, 16 Dec 2014 11:02:56 +0000 (11:02 +0000)
committerbors <bors@rust-lang.org>
Tue, 16 Dec 2014 11:02:56 +0000 (11:02 +0000)
Before:
```
test btree::map::bench::find_rand_100                      ... bench:        12 ns/iter (+/- 0)
test btree::map::bench::find_rand_10_000                   ... bench:        13 ns/iter (+/- 1)
test btree::map::bench::find_seq_100                       ... bench:        11 ns/iter (+/- 0)
test btree::map::bench::find_seq_10_000                    ... bench:        11 ns/iter (+/- 1)
test btree::map::bench::insert_rand_100                    ... bench:       106 ns/iter (+/- 1)
test btree::map::bench::insert_rand_10_000                 ... bench:       326 ns/iter (+/- 8)
test btree::map::bench::insert_seq_100                     ... bench:       198 ns/iter (+/- 1)
test btree::map::bench::insert_seq_10_000                  ... bench:       312 ns/iter (+/- 3)
test btree::map::bench::iter_1000                          ... bench:     16563 ns/iter (+/- 173)
test btree::map::bench::iter_100000                        ... bench:   1686508 ns/iter (+/- 108592)
test btree::map::bench::iter_20                            ... bench:       365 ns/iter (+/- 25)
```

After:
```
test btree::map::bench::find_rand_100                      ... bench:        12 ns/iter (+/- 0)
test btree::map::bench::find_rand_10_000                   ... bench:        12 ns/iter (+/- 0)
test btree::map::bench::find_seq_100                       ... bench:        11 ns/iter (+/- 0)
test btree::map::bench::find_seq_10_000                    ... bench:        11 ns/iter (+/- 0)
test btree::map::bench::insert_rand_100                    ... bench:        89 ns/iter (+/- 1)
test btree::map::bench::insert_rand_10_000                 ... bench:       121 ns/iter (+/- 3)
test btree::map::bench::insert_seq_100                     ... bench:       149 ns/iter (+/- 0)
test btree::map::bench::insert_seq_10_000                  ... bench:       228 ns/iter (+/- 1)
test btree::map::bench::iter_1000                          ... bench:     16965 ns/iter (+/- 220)
test btree::map::bench::iter_100000                        ... bench:   1687836 ns/iter (+/- 18746)
test btree::map::bench::iter_20                            ... bench:       366 ns/iter (+/- 21)
```

src/libcollections/btree/map.rs
src/libcollections/btree/node.rs

index 00f4eac2858e21204c90eeeb76d36fbf3fe52425..94dc1650a2171ae8aa12a17c020a1a8fe5719668 100644 (file)
 use core::prelude::*;
 
 use self::StackOp::*;
-use super::node::*;
+use super::node::{mod, Node, Found, GoDown};
+use super::node::{Traversal, MutTraversal, MoveTraversal};
+use super::node::TraversalItem::{mod, Elem, Edge};
+use super::node::ForceResult::{Leaf, Internal};
 use core::borrow::BorrowFrom;
 use std::hash::{Writer, Hash};
 use core::default::Default;
@@ -125,12 +128,12 @@ pub enum Entry<'a, K:'a, V:'a> {
 /// A vacant Entry.
 pub struct VacantEntry<'a, K:'a, V:'a> {
     key: K,
-    stack: stack::VacantSearchStack<'a, K, V>,
+    stack: stack::SearchStack<'a, K, V, node::Edge, node::Leaf>,
 }
 
 /// An occupied Entry.
 pub struct OccupiedEntry<'a, K:'a, V:'a> {
-    stack: stack::OccupiedSearchStack<'a, K, V>,
+    stack: stack::SearchStack<'a, K, V, node::KV, node::LeafOrInternal>,
 }
 
 impl<K: Ord, V> BTreeMap<K, V> {
@@ -208,10 +211,10 @@ pub fn get<Sized? Q>(&self, key: &Q) -> Option<&V> where Q: BorrowFrom<K> + Ord
         loop {
             match Node::search(cur_node, key) {
                 Found(handle) => return Some(handle.into_kv().1),
-                GoDown(handle) => match handle.into_edge() {
-                    None => return None,
-                    Some(next_node) => {
-                        cur_node = next_node;
+                GoDown(handle) => match handle.force() {
+                    Leaf(_) => return None,
+                    Internal(internal_handle) => {
+                        cur_node = internal_handle.into_edge();
                         continue;
                     }
                 }
@@ -272,10 +275,10 @@ pub fn get_mut<Sized? Q>(&mut self, key: &Q) -> Option<&mut V> where Q: BorrowFr
             let cur_node = temp_node;
             match Node::search(cur_node, key) {
                 Found(handle) => return Some(handle.into_kv_mut().1),
-                GoDown(handle) => match handle.into_edge_mut() {
-                    None => return None,
-                    Some(next_node) => {
-                        temp_node = next_node;
+                GoDown(handle) => match handle.force() {
+                    Leaf(_) => return None,
+                    Internal(internal_handle) => {
+                        temp_node = internal_handle.into_edge_mut();
                         continue;
                     }
                 }
@@ -354,27 +357,27 @@ pub fn insert(&mut self, mut key: K, mut value: V) -> Option<V> {
             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) {
+                return 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);
-                        return Finished(Some(value));
+                        Finished(Some(value))
                     },
                     GoDown(handle) => {
                         // We need to keep searching, try to get the search stack
                         // to go down further
-                        match pusher.push(handle) {
-                            stack::Done(new_stack) => {
+                        match handle.force() {
+                            Leaf(leaf_handle) => {
                                 // We've reached a leaf, perform the insertion here
-                                new_stack.insert(key, value);
-                                return Finished(None);
+                                pusher.seal(leaf_handle).insert(key, value);
+                                Finished(None)
                             }
-                            stack::Grew(new_stack) => {
+                            Internal(internal_handle) => {
                                 // We've found the subtree to insert this key/value pair in,
                                 // keep searching
-                                return Continue((new_stack, key, value));
+                                Continue((pusher.push(internal_handle), key, value))
                             }
-                        };
+                        }
                     }
                 }
             });
@@ -452,18 +455,18 @@ pub fn remove<Sized? Q>(&mut self, key: &Q) -> Option<V> where Q: BorrowFrom<K>
         let mut stack = stack::PartialSearchStack::new(self);
         loop {
             let result = stack.with(move |pusher, node| {
-                match Node::search(node, key) {
+                return match Node::search(node, key) {
                     Found(handle) => {
                         // Perfect match. Terminate the stack here, and remove the entry
-                        return Finished(Some(pusher.seal(handle).remove()));
+                        Finished(Some(pusher.seal(handle).remove()))
                     },
                     GoDown(handle) => {
                         // We need to keep searching, try to go down the next edge
-                        match pusher.push(handle) {
+                        match handle.force() {
                             // We're at a leaf; the key isn't in here
-                            stack::Done(_) => return Finished(None),
-                            stack::Grew(new_stack) => return Continue(new_stack)
-                        };
+                            Leaf(_) => Finished(None),
+                            Internal(internal_handle) => Continue(pusher.push(internal_handle))
+                        }
                     }
                 }
             });
@@ -486,12 +489,11 @@ enum Continuation<A, B> {
 /// to nodes. By using this module much better safety guarantees can be made, and more search
 /// boilerplate gets cut out.
 mod stack {
-    pub use self::PushResult::*;
     use core::prelude::*;
     use core::kinds::marker;
     use core::mem;
     use super::BTreeMap;
-    use super::super::node::*;
+    use super::super::node::{mod, Node, Fit, Split, KV, Edge, Internal, Leaf, LeafOrInternal};
     use vec::Vec;
 
     /// A generic mutable reference, identical to `&mut` except for the fact that its lifetime
@@ -515,30 +517,23 @@ fn deref_mut(&mut self) -> &mut T {
         }
     }
 
-    type StackItem<K, V> = EdgeNodeHandle<*mut Node<K, V>>;
+    type StackItem<K, V> = node::Handle<*mut Node<K, V>, Edge, Internal>;
     type Stack<K, V> = Vec<StackItem<K, V>>;
 
-    /// A PartialSearchStack handles the construction of a search stack.
+    /// A `PartialSearchStack` handles the construction of a search stack.
     pub struct PartialSearchStack<'a, K:'a, V:'a> {
         map: &'a mut BTreeMap<K, V>,
         stack: Stack<K, V>,
         next: *mut Node<K, V>,
     }
 
-    /// An OccupiedSearchStack represents a full path to an element of interest. It provides methods
-    /// for manipulating the element at the top of its stack.
-    pub struct OccupiedSearchStack<'a, K:'a, V:'a> {
+    /// A `SearchStack` represents a full path to an element or an edge of interest. It provides
+    /// methods depending on the type of what the path points to for removing an element, inserting
+    /// a new element, and manipulating to element at the top of the stack.
+    pub struct SearchStack<'a, K:'a, V:'a, Type, NodeType> {
         map: &'a mut BTreeMap<K, V>,
         stack: Stack<K, V>,
-        top: KVNodeHandle<*mut Node<K, V>>,
-    }
-
-    /// A VacantSearchStack represents a full path to a spot for a new element of interest. It
-    /// provides a method inserting an element at the top of its stack.
-    pub struct VacantSearchStack<'a, K:'a, V:'a> {
-        map: &'a mut BTreeMap<K, V>,
-        stack: Stack<K, V>,
-        top: EdgeNodeHandle<*mut Node<K, V>>,
+        top: node::Handle<*mut Node<K, V>, Type, NodeType>,
     }
 
     /// A `PartialSearchStack` that doesn't hold a a reference to the next node, and is just
@@ -550,14 +545,6 @@ pub struct Pusher<'id, 'a, K:'a, V:'a> {
         marker: marker::InvariantLifetime<'id>
     }
 
-    /// The result of asking a PartialSearchStack to push another node onto itself. Either it
-    /// Grew, in which case it's still Partial, or it found its last node was actually a leaf, in
-    /// which case it seals itself and yields a complete SearchStack.
-    pub enum PushResult<'a, K:'a, V:'a> {
-        Grew(PartialSearchStack<'a, K, V>),
-        Done(VacantSearchStack<'a, K, V>),
-    }
-
     impl<'a, K, V> PartialSearchStack<'a, K, V> {
         /// Creates a new PartialSearchStack from a BTreeMap by initializing the stack with the
         /// root of the tree.
@@ -605,40 +592,29 @@ impl<'id, 'a, K, V> Pusher<'id, 'a, K, V> {
         /// Pushes the requested child of the stack's current top on top of the stack. If the child
         /// exists, then a new PartialSearchStack is yielded. Otherwise, a VacantSearchStack is
         /// yielded.
-        pub fn push(mut self, mut edge: EdgeNodeHandle<IdRef<'id, Node<K, V>>>)
-                    -> PushResult<'a, K, V> {
-            let to_insert = edge.as_raw();
-            match edge.edge_mut() {
-                None => {
-                    Done(VacantSearchStack {
-                        map: self.map,
-                        stack: self.stack,
-                        top: to_insert,
-                    })
-                },
-                Some(node) => {
-                    self.stack.push(to_insert);
-                    Grew(PartialSearchStack {
-                        map: self.map,
-                        stack: self.stack,
-                        next: node as *mut _,
-                    })
-                },
+        pub fn push(mut self, mut edge: node::Handle<IdRef<'id, Node<K, V>>, Edge, Internal>)
+                    -> PartialSearchStack<'a, K, V> {
+            self.stack.push(edge.as_raw());
+            PartialSearchStack {
+                map: self.map,
+                stack: self.stack,
+                next: edge.edge_mut() as *mut _,
             }
         }
 
-        /// Converts the PartialSearchStack into an OccupiedSearchStack.
-        pub fn seal(self, mut node: KVNodeHandle<IdRef<'id, Node<K, V>>>)
-                    -> OccupiedSearchStack<'a, K, V> {
-            OccupiedSearchStack {
+        /// Converts the PartialSearchStack into a SearchStack.
+        pub fn seal<Type, NodeType>
+                   (self, mut handle: node::Handle<IdRef<'id, Node<K, V>>, Type, NodeType>)
+                    -> SearchStack<'a, K, V, Type, NodeType> {
+            SearchStack {
                 map: self.map,
                 stack: self.stack,
-                top: node.as_raw(),
+                top: handle.as_raw(),
             }
         }
     }
 
-    impl<'a, K, V> OccupiedSearchStack<'a, K, V> {
+    impl<'a, K, V, NodeType> SearchStack<'a, K, V, KV, NodeType> {
         /// Gets a reference to the value the stack points to.
         pub fn peek(&self) -> &V {
             unsafe { self.top.from_raw().into_kv().1 }
@@ -659,20 +635,13 @@ pub fn into_top(mut self) -> &'a mut V {
                 )
             }
         }
+    }
 
+    impl<'a, K, V> SearchStack<'a, K, V, KV, Leaf> {
         /// 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(mut 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 leafify's comments), but this is immediately fixed by the
-            // removing the value we want to remove
-            self.leafify();
-
-            let map = self.map;
-            map.length -= 1;
-
-            let mut stack = self.stack;
+        fn remove_leaf(mut self) -> 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
@@ -684,16 +653,16 @@ pub fn remove(mut self) -> V {
             };
 
             loop {
-                match stack.pop() {
+                match self.stack.pop() {
                     None => {
                         // We've reached the root, so no matter what, we're done. We manually
                         // access the root via the tree itself to avoid creating any dangling
                         // pointers.
-                        if map.root.len() == 0 && !map.root.is_leaf() {
+                        if self.map.root.len() == 0 && !self.map.root.is_leaf() {
                             // We've emptied out the root, so make its only child the new root.
                             // If it's a leaf, we just let it become empty.
-                            map.depth -= 1;
-                            map.root.into_edge();
+                            self.map.depth -= 1;
+                            self.map.root.hoist_lone_child();
                         }
                         return value;
                     }
@@ -712,6 +681,18 @@ pub fn remove(mut self) -> V {
                 }
             }
         }
+    }
+
+    impl<'a, K, V> SearchStack<'a, K, V, KV, LeafOrInternal> {
+        /// 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()
+        }
 
         /// Subroutine for removal. Takes a search stack for a key that might terminate at an
         /// internal node, and mutates the tree and search stack to *make* it a search stack
@@ -719,7 +700,7 @@ pub fn remove(mut self) -> V {
         /// leaves the tree in an inconsistent state that must be repaired by the caller by
         /// removing the entry in question. Specifically the key-value pair and its successor will
         /// become swapped.
-        fn leafify(&mut self) {
+        fn into_leaf(mut self) -> SearchStack<'a, K, V, KV, Leaf> {
             unsafe {
                 let mut top_raw = self.top;
                 let mut top = top_raw.from_raw_mut();
@@ -728,31 +709,43 @@ fn leafify(&mut self) {
                 let val_ptr = top.val_mut() as *mut _;
 
                 // Try to go into the right subtree of the found key to find its successor
-                let mut right_edge = top.right_edge();
-                let right_edge_raw = right_edge.as_raw();
-                match right_edge.edge_mut() {
-                    None => {
+                match top.force() {
+                    Leaf(mut leaf_handle) => {
                         // We're a proper leaf stack, nothing to do
+                        return SearchStack {
+                            map: self.map,
+                            stack: self.stack,
+                            top: leaf_handle.as_raw()
+                        }
                     }
-                    Some(mut temp_node) => {
+                    Internal(mut internal_handle) => {
+                        let mut right_handle = internal_handle.right_edge();
+
                         //We're not a proper leaf stack, let's get to work.
-                        self.stack.push(right_edge_raw);
+                        self.stack.push(right_handle.as_raw());
+
+                        let mut temp_node = right_handle.edge_mut();
                         loop {
                             // Walk into the smallest subtree of this node
                             let node = temp_node;
 
-                            if node.is_leaf() {
-                                // This node is a leaf, do the swap and return
-                                let mut handle = node.kv_handle(0);
-                                self.top = handle.as_raw();
-                                mem::swap(handle.key_mut(), &mut *key_ptr);
-                                mem::swap(handle.val_mut(), &mut *val_ptr);
-                                break;
-                            } else {
-                                // This node is internal, go deeper
-                                let mut handle = node.edge_handle(0);
-                                self.stack.push(handle.as_raw());
-                                temp_node = handle.into_edge_mut().unwrap();
+                            match node.kv_handle(0).force() {
+                                Leaf(mut handle) => {
+                                    // This node is a leaf, do the swap and return
+                                    mem::swap(handle.key_mut(), &mut *key_ptr);
+                                    mem::swap(handle.val_mut(), &mut *val_ptr);
+                                    return SearchStack {
+                                        map: self.map,
+                                        stack: self.stack,
+                                        top: handle.as_raw()
+                                    }
+                                },
+                                Internal(kv_handle) => {
+                                    // This node is internal, go deeper
+                                    let mut handle = kv_handle.into_left_edge();
+                                    self.stack.push(handle.as_raw());
+                                    temp_node = handle.into_edge_mut();
+                                }
                             }
                         }
                     }
@@ -761,7 +754,7 @@ fn leafify(&mut self) {
         }
     }
 
-    impl<'a, K, V> VacantSearchStack<'a, K, V> {
+    impl<'a, K, V> SearchStack<'a, K, V, Edge, Leaf> {
         /// Inserts the key and value into the top element in the stack, and if that node has to
         /// split recursively inserts the split contents into the next element stack until
         /// splits stop.
@@ -1273,27 +1266,28 @@ pub fn entry<'a>(&'a mut self, mut key: K) -> Entry<'a, K, V> {
         let mut stack = stack::PartialSearchStack::new(self);
         loop {
             let result = stack.with(move |pusher, node| {
-                match Node::search(node, &key) {
+                return match Node::search(node, &key) {
                     Found(handle) => {
                         // Perfect match
-                        return Finished(Occupied(OccupiedEntry {
+                        Finished(Occupied(OccupiedEntry {
                             stack: pusher.seal(handle)
-                        }));
+                        }))
                     },
                     GoDown(handle) => {
-                        match pusher.push(handle) {
-                            stack::Done(new_stack) => {
-                                // Not in the tree, but we've found where it goes
-                                return Finished(Vacant(VacantEntry {
-                                    stack: new_stack,
+                        match handle.force() {
+                            Leaf(leaf_handle) => {
+                                Finished(Vacant(VacantEntry {
+                                    stack: pusher.seal(leaf_handle),
                                     key: key,
-                                }));
+                                }))
+                            },
+                            Internal(internal_handle) => {
+                                Continue((
+                                    pusher.push(internal_handle),
+                                    key
+                                ))
                             }
-                            stack::Grew(new_stack) => {
-                                // We've found the subtree this key must go in
-                                return Continue((new_stack, key));
-                            }
-                        };
+                        }
                     }
                 }
             });
index ae23f38c92913ef1e6a378cdb72de863f86da5c8..3718dd516b21a977c54e78cd29d112d1ee0b2260 100644 (file)
@@ -13,6 +13,7 @@
 
 pub use self::InsertionResult::*;
 pub use self::SearchResult::*;
+pub use self::ForceResult::*;
 pub use self::TraversalItem::*;
 
 use core::prelude::*;
@@ -34,9 +35,9 @@ pub enum InsertionResult<K, V> {
 /// Represents the result of a search for a key in a single node
 pub enum SearchResult<NodeRef> {
     /// The element was found at the given index
-    Found(KVNodeHandle<NodeRef>),
+    Found(Handle<NodeRef, KV, LeafOrInternal>),
     /// The element wasn't found, but if it's anywhere, it must be beyond this edge
-    GoDown(EdgeNodeHandle<NodeRef>),
+    GoDown(Handle<NodeRef, Edge, LeafOrInternal>),
 }
 
 /// A B-Tree Node. We keep keys/edges/values separate to optimize searching for keys.
@@ -428,8 +429,10 @@ fn clone(&self) -> Node<K, V> {
     }
 }
 
-/// A reference to a key/value pair in the middle of a `Node`. Methods are provided for removing
-/// the pair and accessing the pair and the adjacent edges.
+/// A reference to something in the middle of a `Node`. There are two `Type`s of `Handle`s,
+/// namely `KV` handles, which point to key/value pairs, and `Edge` handles, which point to edges
+/// before or after key/value pairs. Methods are provided for removing pairs, inserting into edges,
+/// accessing the stored values, and moving around the `Node`.
 ///
 /// This handle is generic, and can take any sort of reference to a `Node`. The reason for this is
 /// two-fold. First of all, it reduces the amount of repetitive code, implementing functions that
@@ -490,20 +493,17 @@ fn clone(&self) -> Node<K, V> {
 /// }
 /// ```
 #[deriving(Copy)]
-pub struct KVNodeHandle<NodeRef> {
+pub struct Handle<NodeRef, Type, NodeType> {
     node: NodeRef,
     index: uint
 }
 
-/// A reference to an edge in the middle of a `Node`. Methods are provided for inserting stuff into
-/// the space, handling underflow, and accessing the pointed-to edge.
-///
-/// Please see the notes on `KVNodeHandle` about the generic parameter and safety concerns.
-#[deriving(Copy)]
-pub struct EdgeNodeHandle<NodeRef> {
-    node: NodeRef,
-    index: uint
-}
+pub enum KV {}
+pub enum Edge {}
+
+pub enum LeafOrInternal {}
+pub enum Leaf {}
+pub enum Internal {}
 
 impl<K: Ord, V> Node<K, V> {
     /// Searches for the given key in the node. If it finds an exact match,
@@ -516,12 +516,12 @@ pub fn search<Sized? Q, NodeRef: Deref<Node<K, V>>>(node: NodeRef, key: &Q)
         // worse for uints.
         let (found, index) = node.search_linear(key);
         if found {
-            Found(KVNodeHandle {
+            Found(Handle {
                 node: node,
                 index: index
             })
         } else {
-            GoDown(EdgeNodeHandle {
+            GoDown(Handle {
                 node: node,
                 index: index
             })
@@ -586,70 +586,104 @@ pub fn is_full(&self) -> bool {
     }
 }
 
-impl<'a, K: 'a, V: 'a> EdgeNodeHandle<&'a Node<K, V>> {
+impl<K, V, NodeRef: Deref<Node<K, V>>, Type, NodeType> Handle<NodeRef, Type, NodeType> {
+    /// Returns a reference to the node that contains the pointed-to edge or key/value pair. This
+    /// is very different from `edge` and `edge_mut` because those return children of the node
+    /// returned by `node`.
+    pub fn node(&self) -> &Node<K, V> {
+        &*self.node
+    }
+}
+
+impl<K, V, NodeRef: DerefMut<Node<K, V>>, Type, NodeType> Handle<NodeRef, Type, NodeType> {
+    /// Converts a handle into one that stores the same information using a raw pointer. This can
+    /// be useful in conjunction with `from_raw` when the type system is insufficient for
+    /// determining the lifetimes of the nodes.
+    pub fn as_raw(&mut self) -> Handle<*mut Node<K, V>, Type, NodeType> {
+        Handle {
+            node: &mut *self.node as *mut _,
+            index: self.index
+        }
+    }
+}
+
+impl<K, V, Type, NodeType> Handle<*mut Node<K, V>, Type, NodeType> {
+    /// Converts from a handle stored with a raw pointer, which isn't directly usable, to a handle
+    /// stored with a reference. This is an unsafe inverse of `as_raw`, and together they allow
+    /// unsafely extending the lifetime of the reference to the `Node`.
+    pub unsafe fn from_raw<'a>(&'a self) -> Handle<&'a Node<K, V>, Type, NodeType> {
+        Handle {
+            node: &*self.node,
+            index: self.index
+        }
+    }
+
+    /// Converts from a handle stored with a raw pointer, which isn't directly usable, to a handle
+    /// stored with a mutable reference. This is an unsafe inverse of `as_raw`, and together they
+    /// allow unsafely extending the lifetime of the reference to the `Node`.
+    pub unsafe fn from_raw_mut<'a>(&'a mut self) -> Handle<&'a mut Node<K, V>, Type, NodeType> {
+        Handle {
+            node: &mut *self.node,
+            index: self.index
+        }
+    }
+}
+
+impl<'a, K: 'a, V: 'a> Handle<&'a Node<K, V>, Edge, Internal> {
     /// Turns the handle into a reference to the edge it points at. This is necessary because the
     /// returned pointer has a larger lifetime than what would be returned by `edge` or `edge_mut`,
     /// making it more suitable for moving down a chain of nodes.
-    ///
-    /// Returns `None` if called on an edge in a leaf node.
-    pub fn into_edge(self) -> Option<&'a Node<K, V>> {
-        if self.node.is_leaf() {
-            None
-        } else {
-            unsafe {
-                Some(self.node.edges().unsafe_get(self.index))
-            }
+    pub fn into_edge(self) -> &'a Node<K, V> {
+        unsafe {
+            self.node.edges().unsafe_get(self.index)
         }
     }
 }
 
-impl<'a, K: 'a, V: 'a> EdgeNodeHandle<&'a mut Node<K, V>> {
+impl<'a, K: 'a, V: 'a> Handle<&'a mut Node<K, V>, Edge, Internal> {
     /// Turns the handle into a mutable reference to the edge it points at. This is necessary
     /// because the returned pointer has a larger lifetime than what would be returned by
     /// `edge_mut`, making it more suitable for moving down a chain of nodes.
-    ///
-    /// Returns `None` if called on an edge in a leaf node.
-    pub fn into_edge_mut(self) -> Option<&'a mut Node<K, V>> {
-        if self.node.is_leaf() {
-            None
-        } else {
-            unsafe {
-                Some(self.node.edges_mut().unsafe_mut(self.index))
-            }
+    pub fn into_edge_mut(self) -> &'a mut Node<K, V> {
+        unsafe {
+            self.node.edges_mut().unsafe_mut(self.index)
         }
     }
 }
 
-impl<K, V, NodeRef: Deref<Node<K, V>>> EdgeNodeHandle<NodeRef> {
-    /// Returns a reference to the node that contains the pointed-to edge. This is very different
-    /// from `edge` and `edge_mut` because those return children of the node returned by `node`.
-    pub fn node(&self) -> &Node<K, V> {
-        &*self.node
-    }
-
+impl<K, V, NodeRef: Deref<Node<K, V>>> Handle<NodeRef, Edge, Internal> {
     // This doesn't exist because there are no uses for it,
     // but is fine to add, analagous to edge_mut.
     //
     // /// Returns a reference to the edge pointed-to by this handle. This should not be
     // /// confused with `node`, which references the parent node of what is returned here.
-    // ///
-    // /// Returns `None` when called on an edge in a leaf node.
-    // pub fn edge(&self) -> Option<&Node<K, V>>
+    // pub fn edge(&self) -> &Node<K, V>
 }
 
-impl<K, V, NodeRef: DerefMut<Node<K, V>>> EdgeNodeHandle<NodeRef> {
-    /// Returns a mutable reference to the edge pointed-to by this handle. This should not be
-    /// confused with `node`, which references the parent node of what is returned here.
-    ///
-    /// Returns `None` when called on an edge in a leaf node.
-    pub fn edge_mut(&mut self) -> Option<&mut Node<K, V>> {
+pub enum ForceResult<NodeRef, Type> {
+    Leaf(Handle<NodeRef, Type, Leaf>),
+    Internal(Handle<NodeRef, Type, Internal>)
+}
+
+impl<K, V, NodeRef: Deref<Node<K, V>>, Type> Handle<NodeRef, Type, LeafOrInternal> {
+    /// Figure out whether this handle is pointing to something in a leaf node or to something in
+    /// an internal node, clarifying the type according to the result.
+    pub fn force(self) -> ForceResult<NodeRef, Type> {
         if self.node.is_leaf() {
-            None
+            Leaf(Handle {
+                node: self.node,
+                index: self.index
+            })
         } else {
-            unsafe { Some(self.node.edges_mut().unsafe_mut(self.index)) }
+            Internal(Handle {
+                node: self.node,
+                index: self.index
+            })
         }
     }
+}
 
+impl<K, V, NodeRef: DerefMut<Node<K, V>>> Handle<NodeRef, Edge, Leaf> {
     /// Tries to insert this key-value pair at the given index in this leaf node
     /// If the node is full, we have to split it.
     ///
@@ -657,10 +691,6 @@ pub fn edge_mut(&mut self) -> Option<&mut Node<K, V>> {
     /// they're done mutating the tree, but we don't want to borrow anything for now.
     pub fn insert_as_leaf(mut self, key: K, value: V) ->
             (InsertionResult<K, V>, *mut V) {
-        // Necessary for correctness, but in a private module
-        debug_assert!(self.node.is_leaf(),
-                      "insert_as_leaf must only be called on leaf nodes");
-
         if !self.node.is_full() {
             // The element can fit, just insert it
             (Fit, unsafe { self.node.insert_kv(self.index, key, value) as *mut _ })
@@ -683,15 +713,21 @@ pub fn insert_as_leaf(mut self, key: K, value: V) ->
             (Split(new_key, new_val, new_right), ptr)
         }
     }
+}
+
+impl<K, V, NodeRef: DerefMut<Node<K, V>>> Handle<NodeRef, Edge, Internal> {
+    /// Returns a mutable reference to the edge pointed-to by this handle. This should not be
+    /// confused with `node`, which references the parent node of what is returned here.
+    pub fn edge_mut(&mut self) -> &mut Node<K, V> {
+        unsafe {
+            self.node.edges_mut().unsafe_mut(self.index)
+        }
+    }
 
     /// Tries to insert this key-value pair at the given index in this internal node
     /// If the node is full, we have to split it.
     pub fn insert_as_internal(mut self, key: K, value: V, right: Node<K, V>)
             -> InsertionResult<K, V> {
-        // Necessary for correctness, but in a private module
-        debug_assert!(!self.node.is_leaf(),
-                      "insert_as_internal must only be called on internal nodes");
-
         if !self.node.is_full() {
             // The element can fit, just insert it
             unsafe {
@@ -739,26 +775,6 @@ pub fn handle_underflow(mut self) {
         }
     }
 
-    /// Gets the handle pointing to the key/value pair just to the left of the pointed-to edge.
-    /// This is unsafe because the handle might point to the first edge in the node, which has no
-    /// pair to its left.
-    unsafe fn left_kv<'a>(&'a mut self) -> KVNodeHandle<&'a mut Node<K, V>> {
-        KVNodeHandle {
-            node: &mut *self.node,
-            index: self.index - 1
-        }
-    }
-
-    /// Gets the handle pointing to the key/value pair just to the right of the pointed-to edge.
-    /// This is unsafe because the handle might point to the last edge in the node, which has no
-    /// pair to its right.
-    unsafe fn right_kv<'a>(&'a mut self) -> KVNodeHandle<&'a mut Node<K, V>> {
-        KVNodeHandle {
-            node: &mut *self.node,
-            index: self.index
-        }
-    }
-
     /// Right is underflowed. Tries to steal from left,
     /// but merges left and right if left is low too.
     unsafe fn handle_underflow_to_left(&mut self) {
@@ -780,41 +796,31 @@ unsafe fn handle_underflow_to_right(&mut self) {
             self.right_kv().merge_children();
         }
     }
-
-    /// Converts a handle into one that stores the same information using a raw pointer. This can
-    /// be useful in conjunction with `from_raw` in the cases in which the type system is
-    /// insufficient for determining the lifetimes of the nodes.
-    pub fn as_raw(&mut self) -> EdgeNodeHandle<*mut Node<K, V>> {
-        EdgeNodeHandle {
-            node: &mut *self.node as *mut _,
-            index: self.index
-        }
-    }
 }
 
-impl<K, V> EdgeNodeHandle<*mut Node<K, V>> {
-    /// Converts from a handle stored with a raw pointer, which isn't directly usable, to a handle
-    /// stored with a reference. This is an unsafe inverse of `as_raw`, and together they allow
-    /// unsafely extending the lifetime of the reference to the `Node`.
-    pub unsafe fn from_raw<'a>(&'a self) -> EdgeNodeHandle<&'a Node<K, V>> {
-        EdgeNodeHandle {
-            node: &*self.node,
-            index: self.index
+impl<K, V, NodeRef: DerefMut<Node<K, V>>, NodeType> Handle<NodeRef, Edge, NodeType> {
+    /// Gets the handle pointing to the key/value pair just to the left of the pointed-to edge.
+    /// This is unsafe because the handle might point to the first edge in the node, which has no
+    /// pair to its left.
+    unsafe fn left_kv<'a>(&'a mut self) -> Handle<&'a mut Node<K, V>, KV, NodeType> {
+        Handle {
+            node: &mut *self.node,
+            index: self.index - 1
         }
     }
 
-    /// Converts from a handle stored with a raw pointer, which isn't directly usable, to a handle
-    /// stored with a mutable reference. This is an unsafe inverse of `as_raw`, and together they
-    /// allow unsafely extending the lifetime of the reference to the `Node`.
-    pub unsafe fn from_raw_mut<'a>(&'a mut self) -> EdgeNodeHandle<&'a mut Node<K, V>> {
-        EdgeNodeHandle {
+    /// Gets the handle pointing to the key/value pair just to the right of the pointed-to edge.
+    /// This is unsafe because the handle might point to the last edge in the node, which has no
+    /// pair to its right.
+    unsafe fn right_kv<'a>(&'a mut self) -> Handle<&'a mut Node<K, V>, KV, NodeType> {
+        Handle {
             node: &mut *self.node,
             index: self.index
         }
     }
 }
 
-impl<'a, K: 'a, V: 'a> KVNodeHandle<&'a Node<K, V>> {
+impl<'a, K: 'a, V: 'a, NodeType> Handle<&'a Node<K, V>, KV, NodeType> {
     /// Turns the handle into references to the key and value it points at. This is necessary
     /// because the returned pointers have larger lifetimes than what would be returned by `key`
     /// or `val`.
@@ -829,7 +835,7 @@ pub fn into_kv(self) -> (&'a K, &'a V) {
     }
 }
 
-impl<'a, K: 'a, V: 'a> KVNodeHandle<&'a mut Node<K, V>> {
+impl<'a, K: 'a, V: 'a, NodeType> Handle<&'a mut Node<K, V>, KV, NodeType> {
     /// Turns the handle into mutable references to the key and value it points at. This is
     /// necessary because the returned pointers have larger lifetimes than what would be returned
     /// by `key_mut` or `val_mut`.
@@ -842,14 +848,19 @@ pub fn into_kv_mut(self) -> (&'a mut K, &'a mut V) {
             )
         }
     }
-}
 
-impl<'a, K: 'a, V: 'a, NodeRef: Deref<Node<K, V>> + 'a> KVNodeHandle<NodeRef> {
-    /// Returns a reference to the node that contains the pointed-to key/value pair.
-    pub fn node(&'a self) -> &'a Node<K, V> {
-        &*self.node
+    /// Convert this handle into one pointing at the edge immediately to the left of the key/value
+    /// pair pointed-to by this handle. This is useful because it returns a reference with larger
+    /// lifetime than `left_edge`.
+    pub fn into_left_edge(self) -> Handle<&'a mut Node<K, V>, Edge, NodeType> {
+        Handle {
+            node: &mut *self.node,
+            index: self.index
+        }
     }
+}
 
+impl<'a, K: 'a, V: 'a, NodeRef: Deref<Node<K, V>> + 'a, NodeType> Handle<NodeRef, KV, NodeType> {
     // These are fine to include, but are currently unneeded.
     //
     // /// Returns a reference to the key pointed-to by this handle. This doesn't return a
@@ -867,7 +878,7 @@ pub fn node(&'a self) -> &'a Node<K, V> {
     // }
 }
 
-impl<'a, K: 'a, V: 'a, NodeRef: DerefMut<Node<K, V>> + 'a> KVNodeHandle<NodeRef> {
+impl<'a, K: 'a, V: 'a, NodeRef: DerefMut<Node<K, V>> + 'a, NodeType> Handle<NodeRef, KV, NodeType> {
     /// Returns a mutable reference to the key pointed-to by this handle. This doesn't return a
     /// reference with a lifetime as large as `into_kv_mut`, but it also does not consume the
     /// handle.
@@ -883,11 +894,11 @@ pub fn val_mut(&'a mut self) -> &'a mut V {
     }
 }
 
-impl<K, V, NodeRef: DerefMut<Node<K, V>>> KVNodeHandle<NodeRef> {
+impl<K, V, NodeRef: DerefMut<Node<K, V>>, NodeType> Handle<NodeRef, KV, NodeType> {
     /// Gets the handle pointing to the edge immediately to the left of the key/value pair pointed
     /// to by this handle.
-    pub fn left_edge<'a>(&'a mut self) -> EdgeNodeHandle<&'a mut Node<K, V>> {
-        EdgeNodeHandle {
+    pub fn left_edge<'a>(&'a mut self) -> Handle<&'a mut Node<K, V>, Edge, NodeType> {
+        Handle {
             node: &mut *self.node,
             index: self.index
         }
@@ -895,41 +906,33 @@ pub fn left_edge<'a>(&'a mut self) -> EdgeNodeHandle<&'a mut Node<K, V>> {
 
     /// Gets the handle pointing to the edge immediately to the right of the key/value pair pointed
     /// to by this handle.
-    pub fn right_edge<'a>(&'a mut self) -> EdgeNodeHandle<&'a mut Node<K, V>> {
-        EdgeNodeHandle {
+    pub fn right_edge<'a>(&'a mut self) -> Handle<&'a mut Node<K, V>, Edge, NodeType> {
+        Handle {
             node: &mut *self.node,
             index: self.index + 1
         }
     }
+}
 
+impl<K, V, NodeRef: DerefMut<Node<K, V>>> Handle<NodeRef, KV, Leaf> {
     /// Removes the key/value pair at the handle's location.
     ///
     /// # Panics (in debug build)
     ///
     /// Panics if the node containing the pair is not a leaf node.
     pub fn remove_as_leaf(mut self) -> (K, V) {
-        // Necessary for correctness, but in a private module
-        debug_assert!(self.node.is_leaf(), "remove_as_leaf must only be called on leaf nodes");
         unsafe { self.node.remove_kv(self.index) }
     }
+}
 
-    /// Converts a handle into one that stores the same information using a raw pointer. This can
-    /// be useful in conjunction with `from_raw` in the cases in which the type system is
-    /// insufficient for determining the lifetimes of the nodes.
-    pub fn as_raw(&mut self) -> KVNodeHandle<*mut Node<K, V>> {
-        KVNodeHandle {
-            node: &mut *self.node as *mut _,
-            index: self.index
-        }
-    }
-
+impl<K, V, NodeRef: DerefMut<Node<K, V>>> Handle<NodeRef, KV, Internal> {
     /// Steal! Stealing is roughly analogous to a binary tree rotation.
     /// In this case, we're "rotating" right.
     unsafe fn steal_rightward(&mut self) {
         // Take the biggest stuff off left
         let (mut key, mut val, edge) = {
             let mut left_handle = self.left_edge();
-            let left = left_handle.edge_mut().unwrap();
+            let left = left_handle.edge_mut();
             let (key, val) = left.pop_kv();
             let edge = if left.is_leaf() {
                 None
@@ -946,7 +949,7 @@ unsafe fn steal_rightward(&mut self) {
 
         // Put them at the start of right
         let mut right_handle = self.right_edge();
-        let right = right_handle.edge_mut().unwrap();
+        let right = right_handle.edge_mut();
         right.insert_kv(0, key, val);
         match edge {
             Some(edge) => right.insert_edge(0, edge),
@@ -960,7 +963,7 @@ unsafe fn steal_leftward(&mut self) {
         // Take the smallest stuff off right
         let (mut key, mut val, edge) = {
             let mut right_handle = self.right_edge();
-            let right = right_handle.edge_mut().unwrap();
+            let right = right_handle.edge_mut();
             let (key, val) = right.remove_kv(0);
             let edge = if right.is_leaf() {
                 None
@@ -977,7 +980,7 @@ unsafe fn steal_leftward(&mut self) {
 
         // Put them at the end of left
         let mut left_handle = self.left_edge();
-        let left = left_handle.edge_mut().unwrap();
+        let left = left_handle.edge_mut();
         left.push_kv(key, val);
         match edge {
             Some(edge) => left.push_edge(edge),
@@ -994,57 +997,21 @@ unsafe fn merge_children(mut self) {
         let right = self.node.remove_edge(self.index + 1);
 
         // Give left right's stuff.
-        self.left_edge().edge_mut().unwrap()
+        self.left_edge().edge_mut()
             .absorb(key, val, right);
     }
 }
 
-impl<K, V> KVNodeHandle<*mut Node<K, V>> {
-    /// Converts from a handle stored with a raw pointer, which isn't directly usable, to a handle
-    /// stored with a reference. This is an unsafe inverse of `as_raw`, and together they allow
-    /// unsafely extending the lifetime of the reference to the `Node`.
-    pub unsafe fn from_raw<'a>(&'a self) -> KVNodeHandle<&'a Node<K, V>> {
-        KVNodeHandle {
-            node: &*self.node,
-            index: self.index
-        }
-    }
-
-    /// Converts from a handle stored with a raw pointer, which isn't directly usable, to a handle
-    /// stored with a mutable reference. This is an unsafe inverse of `as_raw`, and together they
-    /// allow unsafely extending the lifetime of the reference to the `Node`.
-    pub unsafe fn from_raw_mut<'a>(&'a mut self) -> KVNodeHandle<&'a mut Node<K, V>> {
-        KVNodeHandle {
-            node: &mut *self.node,
-            index: self.index
-        }
-    }
-}
-
 impl<K, V> Node<K, V> {
     /// Returns the mutable handle pointing to the key/value pair at a given index.
     ///
     /// # Panics (in debug build)
     ///
     /// Panics if the given index is out of bounds.
-    pub fn kv_handle(&mut self, index: uint) -> KVNodeHandle<&mut Node<K, V>> {
+    pub fn kv_handle(&mut self, index: uint) -> Handle<&mut Node<K, V>, KV, LeafOrInternal> {
         // Necessary for correctness, but in a private module
         debug_assert!(index < self.len(), "kv_handle index out of bounds");
-        KVNodeHandle {
-            node: self,
-            index: index
-        }
-    }
-
-    /// Returns the mutable handle pointing to the edge at a given index.
-    ///
-    /// # Panics (in debug build)
-    ///
-    /// Panics if the given index is out of bounds.
-    pub fn edge_handle(&mut self, index: uint) -> EdgeNodeHandle<&mut Node<K, V>> {
-        // Necessary for correctness, but in a private module
-        debug_assert!(index <= self.len(), "edge_handle index out of bounds");
-        EdgeNodeHandle {
+        Handle {
             node: self,
             index: index
         }
@@ -1100,7 +1067,7 @@ pub fn into_iter(self) -> MoveTraversal<K, V> {
     }
 
     /// When a node has no keys or values and only a single edge, extract that edge.
-    pub fn into_edge(&mut self) {
+    pub fn hoist_lone_child(&mut self) {
         // Necessary for correctness, but in a private module
         debug_assert!(self.len() == 0);
         debug_assert!(!self.is_leaf());