about summary refs log tree commit diff
path: root/src
diff options
context:
space:
mode:
authorbors <bors@rust-lang.org>2015-06-05 01:10:59 +0000
committerbors <bors@rust-lang.org>2015-06-05 01:10:59 +0000
commitda0d45243bbb04ea7efec686162d0b9ce2ec4734 (patch)
tree758483d29e055e1722d719c220365910268d9960 /src
parente0ca6b1a314f949827fda499ee29dcbf6ef18acd (diff)
parente12d3869e3c5f7ee3e49fbccb668edabd9cdb643 (diff)
downloadrust-da0d45243bbb04ea7efec686162d0b9ce2ec4734.tar.gz
rust-da0d45243bbb04ea7efec686162d0b9ce2ec4734.zip
Auto merge of #26022 - Gankro:fix-linked-list, r=huonw
Still running tests...
Diffstat (limited to 'src')
-rw-r--r--src/libcollections/linked_list.rs26
1 files changed, 26 insertions, 0 deletions
diff --git a/src/libcollections/linked_list.rs b/src/libcollections/linked_list.rs
index 7c045c45376..0bfbfd73377 100644
--- a/src/libcollections/linked_list.rs
+++ b/src/libcollections/linked_list.rs
@@ -609,7 +609,13 @@ impl<T> LinkedList<T> {
             length: len - at
         };
 
+        // Swap split_node.next with list_head (which is None), nulling out split_node.next,
+        // as it is the new tail.
         mem::swap(&mut split_node.resolve().unwrap().next, &mut splitted_list.list_head);
+        // Null out list_head.prev. Note this `unwrap` won't fail because if at == len
+        // we already branched out at the top of the fn to return the empty list.
+        splitted_list.list_head.as_mut().unwrap().prev = Rawlink::none();
+        // Fix the tail ptr
         self.list_tail = split_node;
         self.length = at;
 
@@ -1075,6 +1081,26 @@ mod tests {
         }
     }
 
+    #[test]
+    fn test_26021() {
+        use std::iter::ExactSizeIterator;
+        // There was a bug in split_off that failed to null out the RHS's head's prev ptr.
+        // This caused the RHS's dtor to walk up into the LHS at drop and delete all of
+        // its nodes.
+        //
+        // https://github.com/rust-lang/rust/issues/26021
+        let mut v1 = LinkedList::new();
+        v1.push_front(1u8);
+        v1.push_front(1u8);
+        v1.push_front(1u8);
+        v1.push_front(1u8);
+        let _ = v1.split_off(3); // Dropping this now should not cause laundry consumption
+        assert_eq!(v1.len(), 3);
+
+        assert_eq!(v1.iter().len(), 3);
+        assert_eq!(v1.iter().collect::<Vec<_>>().len(), 3);
+    }
+
     #[cfg(test)]
     fn fuzz_test(sz: i32) {
         let mut m: LinkedList<_> = LinkedList::new();