]> git.proxmox.com Git - rustc.git/blobdiff - src/libcollections/linked_list.rs
Imported Upstream version 1.8.0+dfsg1
[rustc.git] / src / libcollections / linked_list.rs
index deb1476c23f096375fce6fd7cfeb919e5e322ed4..cb669a9bf9ef8863c5ba5a6d714e0bbf5aadbf3d 100644 (file)
 
 #![stable(feature = "rust1", since = "1.0.0")]
 
-use core::prelude::*;
-
-use alloc::boxed::Box;
+use alloc::boxed::{Box, IntermediateBox};
 use core::cmp::Ordering;
 use core::fmt;
 use core::hash::{Hasher, Hash};
-use core::iter::{self, FromIterator};
+use core::iter::FromIterator;
 use core::mem;
-use core::ptr;
+use core::ops::{BoxPlace, InPlace, Place, Placer};
+use core::ptr::{self, Shared};
 
 /// A doubly-linked list.
 #[stable(feature = "rust1", since = "1.0.0")]
@@ -42,12 +41,12 @@ pub struct LinkedList<T> {
 type Link<T> = Option<Box<Node<T>>>;
 
 struct Rawlink<T> {
-    p: *mut T,
+    p: Option<Shared<T>>,
 }
 
 impl<T> Copy for Rawlink<T> {}
-unsafe impl<T:Send> Send for Rawlink<T> {}
-unsafe impl<T:Sync> Sync for Rawlink<T> {}
+unsafe impl<T: Send> Send for Rawlink<T> {}
+unsafe impl<T: Sync> Sync for Rawlink<T> {}
 
 struct Node<T> {
     next: Link<T>,
@@ -57,7 +56,7 @@ struct Node<T> {
 
 /// An iterator over references to the items of a `LinkedList`.
 #[stable(feature = "rust1", since = "1.0.0")]
-pub struct Iter<'a, T:'a> {
+pub struct Iter<'a, T: 'a> {
     head: &'a Link<T>,
     tail: Rawlink<Node<T>>,
     nelem: usize,
@@ -77,46 +76,50 @@ impl<'a, T> Clone for Iter<'a, T> {
 
 /// An iterator over mutable references to the items of a `LinkedList`.
 #[stable(feature = "rust1", since = "1.0.0")]
-pub struct IterMut<'a, T:'a> {
+pub struct IterMut<'a, T: 'a> {
     list: &'a mut LinkedList<T>,
     head: Rawlink<Node<T>>,
     tail: Rawlink<Node<T>>,
     nelem: usize,
 }
 
-/// An iterator over mutable references to the items of a `LinkedList`.
+/// An iterator over the items of a `LinkedList`.
 #[derive(Clone)]
 #[stable(feature = "rust1", since = "1.0.0")]
 pub struct IntoIter<T> {
-    list: LinkedList<T>
+    list: LinkedList<T>,
 }
 
 /// Rawlink is a type like Option<T> but for holding a raw pointer
 impl<T> Rawlink<T> {
     /// Like Option::None for Rawlink
     fn none() -> Rawlink<T> {
-        Rawlink{p: ptr::null_mut()}
+        Rawlink { p: None }
     }
 
     /// Like Option::Some for Rawlink
     fn some(n: &mut T) -> Rawlink<T> {
-        Rawlink{p: n}
+        unsafe { Rawlink { p: Some(Shared::new(n)) } }
     }
 
     /// Convert the `Rawlink` into an Option value
-    fn resolve_immut<'a>(&self) -> Option<&'a T> {
-        unsafe {
-            mem::transmute(self.p.as_ref())
-        }
+    ///
+    /// **unsafe** because:
+    ///
+    /// - Dereference of raw pointer.
+    /// - Returns reference of arbitrary lifetime.
+    unsafe fn resolve<'a>(&self) -> Option<&'a T> {
+        self.p.map(|p| &**p)
     }
 
     /// Convert the `Rawlink` into an Option value
-    fn resolve<'a>(&mut self) -> Option<&'a mut T> {
-        if self.p.is_null() {
-            None
-        } else {
-            Some(unsafe { mem::transmute(self.p) })
-        }
+    ///
+    /// **unsafe** because:
+    ///
+    /// - Dereference of raw pointer.
+    /// - Returns reference of arbitrary lifetime.
+    unsafe fn resolve_mut<'a>(&mut self) -> Option<&'a mut T> {
+        self.p.map(|p| &mut **p)
     }
 
     /// Return the `Rawlink` and replace with `Rawlink::none()`
@@ -125,23 +128,45 @@ impl<T> Rawlink<T> {
     }
 }
 
+impl<'a, T> From<&'a mut Link<T>> for Rawlink<Node<T>> {
+    fn from(node: &'a mut Link<T>) -> Self {
+        match node.as_mut() {
+            None => Rawlink::none(),
+            Some(ptr) => Rawlink::some(ptr),
+        }
+    }
+}
+
 impl<T> Clone for Rawlink<T> {
     #[inline]
     fn clone(&self) -> Rawlink<T> {
-        Rawlink{p: self.p}
+        Rawlink { p: self.p }
     }
 }
 
 impl<T> Node<T> {
     fn new(v: T) -> Node<T> {
-        Node{value: v, next: None, prev: Rawlink::none()}
+        Node {
+            value: v,
+            next: None,
+            prev: Rawlink::none(),
+        }
+    }
+
+    /// Update the `prev` link on `next`, then set self's next pointer.
+    ///
+    /// `self.next` should be `None` when you call this
+    /// (otherwise a Node is probably being dropped by mistake).
+    fn set_next(&mut self, mut next: Box<Node<T>>) {
+        debug_assert!(self.next.is_none());
+        next.prev = Rawlink::some(self);
+        self.next = Some(next);
     }
 }
 
-/// Set the .prev field on `next`, then return `Some(next)`
-fn link_with_prev<T>(mut next: Box<Node<T>>, prev: Rawlink<Node<T>>)
-                  -> Link<T> {
-    next.prev = prev;
+/// Clear the .prev field on `next`, then return `Some(next)`
+fn link_no_prev<T>(mut next: Box<Node<T>>) -> Link<T> {
+    next.prev = Rawlink::none();
     Some(next)
 }
 
@@ -152,8 +177,8 @@ impl<T> LinkedList<T> {
     fn push_front_node(&mut self, mut new_head: Box<Node<T>>) {
         match self.list_head {
             None => {
-                self.list_tail = Rawlink::some(&mut *new_head);
-                self.list_head = link_with_prev(new_head, Rawlink::none());
+                self.list_head = link_no_prev(new_head);
+                self.list_tail = Rawlink::from(&mut self.list_head);
             }
             Some(ref mut head) => {
                 new_head.prev = Rawlink::none();
@@ -171,8 +196,8 @@ impl<T> LinkedList<T> {
         self.list_head.take().map(|mut front_node| {
             self.length -= 1;
             match front_node.next.take() {
-                Some(node) => self.list_head = link_with_prev(node, Rawlink::none()),
-                None => self.list_tail = Rawlink::none()
+                Some(node) => self.list_head = link_no_prev(node),
+                None => self.list_tail = Rawlink::none(),
             }
             front_node
         })
@@ -180,12 +205,12 @@ impl<T> LinkedList<T> {
 
     /// Add a Node last in the list
     #[inline]
-    fn push_back_node(&mut self, mut new_tail: Box<Node<T>>) {
-        match self.list_tail.resolve() {
+    fn push_back_node(&mut self, new_tail: Box<Node<T>>) {
+        match unsafe { self.list_tail.resolve_mut() } {
             None => return self.push_front_node(new_tail),
             Some(tail) => {
-                self.list_tail = Rawlink::some(&mut *new_tail);
-                tail.next = link_with_prev(new_tail, Rawlink::some(tail));
+                tail.set_next(new_tail);
+                self.list_tail = Rawlink::from(&mut tail.next);
             }
         }
         self.length += 1;
@@ -194,22 +219,25 @@ impl<T> LinkedList<T> {
     /// Remove the last Node and return it, or None if the list is empty
     #[inline]
     fn pop_back_node(&mut self) -> Option<Box<Node<T>>> {
-        self.list_tail.resolve().map_or(None, |tail| {
-            self.length -= 1;
-            self.list_tail = tail.prev;
-            match tail.prev.resolve() {
-                None => self.list_head.take(),
-                Some(tail_prev) => tail_prev.next.take()
-            }
-        })
+        unsafe {
+            self.list_tail.resolve_mut().and_then(|tail| {
+                self.length -= 1;
+                self.list_tail = tail.prev;
+                match tail.prev.resolve_mut() {
+                    None => self.list_head.take(),
+                    Some(tail_prev) => tail_prev.next.take(),
+                }
+            })
+        }
     }
 }
 
 #[stable(feature = "rust1", since = "1.0.0")]
 impl<T> Default for LinkedList<T> {
     #[inline]
-    #[stable(feature = "rust1", since = "1.0.0")]
-    fn default() -> LinkedList<T> { LinkedList::new() }
+    fn default() -> LinkedList<T> {
+        LinkedList::new()
+    }
 }
 
 impl<T> LinkedList<T> {
@@ -217,7 +245,11 @@ impl<T> LinkedList<T> {
     #[inline]
     #[stable(feature = "rust1", since = "1.0.0")]
     pub fn new() -> LinkedList<T> {
-        LinkedList{list_head: None, list_tail: Rawlink::none(), length: 0}
+        LinkedList {
+            list_head: None,
+            list_tail: Rawlink::none(),
+            length: 0,
+        }
     }
 
     /// Moves all elements from `other` to the end of the list.
@@ -230,7 +262,6 @@ impl<T> LinkedList<T> {
     /// # Examples
     ///
     /// ```
-    /// # #![feature(collections)]
     /// use std::collections::LinkedList;
     ///
     /// let mut a = LinkedList::new();
@@ -242,19 +273,19 @@ impl<T> LinkedList<T> {
     ///
     /// a.append(&mut b);
     ///
-    /// for e in a.iter() {
+    /// for e in &a {
     ///     println!("{}", e); // prints 1, then 2, then 3, then 4
     /// }
     /// println!("{}", b.len()); // prints 0
     /// ```
     #[stable(feature = "rust1", since = "1.0.0")]
     pub fn append(&mut self, other: &mut LinkedList<T>) {
-        match self.list_tail.resolve() {
+        match unsafe { self.list_tail.resolve_mut() } {
             None => {
                 self.length = other.length;
                 self.list_head = other.list_head.take();
                 self.list_tail = other.list_tail.take();
-            },
+            }
             Some(tail) => {
                 // Carefully empty `other`.
                 let o_tail = other.list_tail.take();
@@ -262,7 +293,7 @@ impl<T> LinkedList<T> {
                 match other.list_head.take() {
                     None => return,
                     Some(node) => {
-                        tail.next = link_with_prev(node, self.list_tail);
+                        tail.set_next(node);
                         self.list_tail = o_tail;
                         self.length += o_length;
                     }
@@ -276,22 +307,22 @@ impl<T> LinkedList<T> {
     #[inline]
     #[stable(feature = "rust1", since = "1.0.0")]
     pub fn iter(&self) -> Iter<T> {
-        Iter{nelem: self.len(), head: &self.list_head, tail: self.list_tail}
+        Iter {
+            nelem: self.len(),
+            head: &self.list_head,
+            tail: self.list_tail,
+        }
     }
 
     /// Provides a forward iterator with mutable references.
     #[inline]
     #[stable(feature = "rust1", since = "1.0.0")]
     pub fn iter_mut(&mut self) -> IterMut<T> {
-        let head_raw = match self.list_head {
-            Some(ref mut h) => Rawlink::some(&mut **h),
-            None => Rawlink::none(),
-        };
-        IterMut{
+        IterMut {
             nelem: self.len(),
-            head: head_raw,
+            head: Rawlink::from(&mut self.list_head),
             tail: self.list_tail,
-            list: self
+            list: self,
         }
     }
 
@@ -436,7 +467,7 @@ impl<T> LinkedList<T> {
     #[inline]
     #[stable(feature = "rust1", since = "1.0.0")]
     pub fn back(&self) -> Option<&T> {
-        self.list_tail.resolve_immut().as_ref().map(|tail| &tail.value)
+        unsafe { self.list_tail.resolve().map(|tail| &tail.value) }
     }
 
     /// Provides a mutable reference to the back element, or `None` if the list
@@ -463,7 +494,7 @@ impl<T> LinkedList<T> {
     #[inline]
     #[stable(feature = "rust1", since = "1.0.0")]
     pub fn back_mut(&mut self) -> Option<&mut T> {
-        self.list_tail.resolve().map(|tail| &mut tail.value)
+        unsafe { self.list_tail.resolve_mut().map(|tail| &mut tail.value) }
     }
 
     /// Adds an element first in the list.
@@ -473,7 +504,6 @@ impl<T> LinkedList<T> {
     /// # Examples
     ///
     /// ```
-    /// # #![feature(collections)]
     /// use std::collections::LinkedList;
     ///
     /// let mut dl = LinkedList::new();
@@ -513,7 +543,7 @@ impl<T> LinkedList<T> {
     ///
     #[stable(feature = "rust1", since = "1.0.0")]
     pub fn pop_front(&mut self) -> Option<T> {
-        self.pop_front_node().map(|box Node{value, ..}| value)
+        self.pop_front_node().map(|box Node { value, .. }| value)
     }
 
     /// Appends an element to the back of a list
@@ -521,7 +551,6 @@ impl<T> LinkedList<T> {
     /// # Examples
     ///
     /// ```
-    /// # #![feature(collections)]
     /// use std::collections::LinkedList;
     ///
     /// let mut d = LinkedList::new();
@@ -540,7 +569,6 @@ impl<T> LinkedList<T> {
     /// # Examples
     ///
     /// ```
-    /// # #![feature(collections)]
     /// use std::collections::LinkedList;
     ///
     /// let mut d = LinkedList::new();
@@ -551,7 +579,7 @@ impl<T> LinkedList<T> {
     /// ```
     #[stable(feature = "rust1", since = "1.0.0")]
     pub fn pop_back(&mut self) -> Option<T> {
-        self.pop_back_node().map(|box Node{value, ..}| value)
+        self.pop_back_node().map(|box Node { value, .. }| value)
     }
 
     /// Splits the list into two at the given index. Returns everything after the given index,
@@ -566,7 +594,6 @@ impl<T> LinkedList<T> {
     /// # Examples
     ///
     /// ```
-    /// # #![feature(collections)]
     /// use std::collections::LinkedList;
     ///
     /// let mut d = LinkedList::new();
@@ -601,7 +628,7 @@ impl<T> LinkedList<T> {
                 iter.next();
             }
             iter.head
-        }  else {
+        } else {
             // better off starting from the end
             let mut iter = self.iter_mut();
             for _ in 0..len - 1 - (at - 1) {
@@ -610,39 +637,93 @@ impl<T> LinkedList<T> {
             iter.tail
         };
 
-        let mut splitted_list = LinkedList {
-            list_head: None,
+        // The split node is the new tail node of the first part and owns
+        // the head of the second part.
+        let mut second_part_head;
+
+        unsafe {
+            second_part_head = split_node.resolve_mut().unwrap().next.take();
+            match second_part_head {
+                None => {}
+                Some(ref mut head) => head.prev = Rawlink::none(),
+            }
+        }
+
+        let second_part = LinkedList {
+            list_head: second_part_head,
             list_tail: self.list_tail,
-            length: len - at
+            length: len - at,
         };
 
-        mem::swap(&mut split_node.resolve().unwrap().next, &mut splitted_list.list_head);
+        // Fix the tail ptr of the first part
         self.list_tail = split_node;
         self.length = at;
 
-        splitted_list
+        second_part
+    }
+
+    /// Returns a place for insertion at the front of the list.
+    ///
+    /// Using this method with placement syntax is equivalent to [`push_front`]
+    /// (#method.push_front), but may be more efficient.
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// #![feature(collection_placement)]
+    /// #![feature(placement_in_syntax)]
+    ///
+    /// use std::collections::LinkedList;
+    ///
+    /// let mut list = LinkedList::new();
+    /// list.front_place() <- 2;
+    /// list.front_place() <- 4;
+    /// assert!(list.iter().eq(&[4, 2]));
+    /// ```
+    #[unstable(feature = "collection_placement",
+               reason = "method name and placement protocol are subject to change",
+               issue = "30172")]
+    pub fn front_place(&mut self) -> FrontPlace<T> {
+        FrontPlace { list: self, node: IntermediateBox::make_place() }
+    }
+
+    /// Returns a place for insertion at the back of the list.
+    ///
+    /// Using this method with placement syntax is equivalent to [`push_back`](#method.push_back),
+    /// but may be more efficient.
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// #![feature(collection_placement)]
+    /// #![feature(placement_in_syntax)]
+    ///
+    /// use std::collections::LinkedList;
+    ///
+    /// let mut list = LinkedList::new();
+    /// list.back_place() <- 2;
+    /// list.back_place() <- 4;
+    /// assert!(list.iter().eq(&[2, 4]));
+    /// ```
+    #[unstable(feature = "collection_placement",
+               reason = "method name and placement protocol are subject to change",
+               issue = "30172")]
+    pub fn back_place(&mut self) -> BackPlace<T> {
+        BackPlace { list: self, node: IntermediateBox::make_place() }
     }
 }
 
-#[unsafe_destructor]
 #[stable(feature = "rust1", since = "1.0.0")]
 impl<T> Drop for LinkedList<T> {
+    #[unsafe_destructor_blind_to_params]
     fn drop(&mut self) {
-        // Dissolve the linked_list in backwards direction
+        // Dissolve the linked_list in a loop.
         // Just dropping the list_head can lead to stack exhaustion
         // when length is >> 1_000_000
-        let mut tail = self.list_tail;
-        loop {
-            match tail.resolve() {
-                None => break,
-                Some(prev) => {
-                    prev.next.take(); // release Box<Node<T>>
-                    tail = prev.prev;
-                }
-            }
+        while let Some(mut head_) = self.list_head.take() {
+            self.list_head = head_.next.take();
         }
         self.length = 0;
-        self.list_head = None;
         self.list_tail = Rawlink::none();
     }
 }
@@ -676,11 +757,13 @@ impl<'a, A> DoubleEndedIterator for Iter<'a, A> {
         if self.nelem == 0 {
             return None;
         }
-        self.tail.resolve_immut().as_ref().map(|prev| {
-            self.nelem -= 1;
-            self.tail = prev.prev;
-            &prev.value
-        })
+        unsafe {
+            self.tail.resolve().map(|prev| {
+                self.nelem -= 1;
+                self.tail = prev.prev;
+                &prev.value
+            })
+        }
     }
 }
 
@@ -695,14 +778,13 @@ impl<'a, A> Iterator for IterMut<'a, A> {
         if self.nelem == 0 {
             return None;
         }
-        self.head.resolve().map(|next| {
-            self.nelem -= 1;
-            self.head = match next.next {
-                Some(ref mut node) => Rawlink::some(&mut **node),
-                None => Rawlink::none(),
-            };
-            &mut next.value
-        })
+        unsafe {
+            self.head.resolve_mut().map(|next| {
+                self.nelem -= 1;
+                self.head = Rawlink::from(&mut next.next);
+                &mut next.value
+            })
+        }
     }
 
     #[inline]
@@ -718,11 +800,13 @@ impl<'a, A> DoubleEndedIterator for IterMut<'a, A> {
         if self.nelem == 0 {
             return None;
         }
-        self.tail.resolve().map(|prev| {
-            self.nelem -= 1;
-            self.tail = prev.prev;
-            &mut prev.value
-        })
+        unsafe {
+            self.tail.resolve_mut().map(|prev| {
+                self.nelem -= 1;
+                self.tail = prev.prev;
+                &mut prev.value
+            })
+        }
     }
 }
 
@@ -736,16 +820,18 @@ impl<'a, A> IterMut<'a, A> {
         // previously yielded element and self.head.
         //
         // The inserted node will not appear in further iteration.
-        match self.head.resolve() {
-            None => { self.list.push_back_node(ins_node); }
+        match unsafe { self.head.resolve_mut() } {
+            None => {
+                self.list.push_back_node(ins_node);
+            }
             Some(node) => {
-                let prev_node = match node.prev.resolve() {
+                let prev_node = match unsafe { node.prev.resolve_mut() } {
                     None => return self.list.push_front_node(ins_node),
                     Some(prev) => prev,
                 };
                 let node_own = prev_node.next.take().unwrap();
-                ins_node.next = link_with_prev(node_own, Rawlink::some(&mut *ins_node));
-                prev_node.next = link_with_prev(ins_node, Rawlink::some(prev_node));
+                ins_node.set_next(node_own);
+                prev_node.set_next(ins_node);
                 self.list.length += 1;
             }
         }
@@ -759,7 +845,8 @@ impl<'a, A> IterMut<'a, A> {
     /// # Examples
     ///
     /// ```
-    /// # #![feature(collections)]
+    /// #![feature(linked_list_extras)]
+    ///
     /// use std::collections::LinkedList;
     ///
     /// let mut list: LinkedList<_> = vec![1, 3, 4].into_iter().collect();
@@ -776,8 +863,9 @@ impl<'a, A> IterMut<'a, A> {
     /// }
     /// ```
     #[inline]
-    #[unstable(feature = "collections",
-               reason = "this is probably better handled by a cursor type -- we'll see")]
+    #[unstable(feature = "linked_list_extras",
+               reason = "this is probably better handled by a cursor type -- we'll see",
+               issue = "27794")]
     pub fn insert_next(&mut self, elt: A) {
         self.insert_next_node(box Node::new(elt))
     }
@@ -787,7 +875,8 @@ impl<'a, A> IterMut<'a, A> {
     /// # Examples
     ///
     /// ```
-    /// # #![feature(collections)]
+    /// #![feature(linked_list_extras)]
+    ///
     /// use std::collections::LinkedList;
     ///
     /// let mut list: LinkedList<_> = vec![1, 2, 3].into_iter().collect();
@@ -799,13 +888,14 @@ impl<'a, A> IterMut<'a, A> {
     /// assert_eq!(it.next().unwrap(), &2);
     /// ```
     #[inline]
-    #[unstable(feature = "collections",
-               reason = "this is probably better handled by a cursor type -- we'll see")]
+    #[unstable(feature = "linked_list_extras",
+               reason = "this is probably better handled by a cursor type -- we'll see",
+               issue = "27794")]
     pub fn peek_next(&mut self) -> Option<&mut A> {
         if self.nelem == 0 {
-            return None
+            return None;
         }
-        self.head.resolve().map(|head| &mut head.value)
+        unsafe { self.head.resolve_mut().map(|head| &mut head.value) }
     }
 }
 
@@ -814,7 +904,9 @@ impl<A> Iterator for IntoIter<A> {
     type Item = A;
 
     #[inline]
-    fn next(&mut self) -> Option<A> { self.list.pop_front() }
+    fn next(&mut self) -> Option<A> {
+        self.list.pop_front()
+    }
 
     #[inline]
     fn size_hint(&self) -> (usize, Option<usize>) {
@@ -825,14 +917,17 @@ impl<A> Iterator for IntoIter<A> {
 #[stable(feature = "rust1", since = "1.0.0")]
 impl<A> DoubleEndedIterator for IntoIter<A> {
     #[inline]
-    fn next_back(&mut self) -> Option<A> { self.list.pop_back() }
+    fn next_back(&mut self) -> Option<A> {
+        self.list.pop_back()
+    }
 }
 
+#[stable(feature = "rust1", since = "1.0.0")]
 impl<A> ExactSizeIterator for IntoIter<A> {}
 
 #[stable(feature = "rust1", since = "1.0.0")]
 impl<A> FromIterator<A> for LinkedList<A> {
-    fn from_iter<T: IntoIterator<Item=A>>(iter: T) -> LinkedList<A> {
+    fn from_iter<T: IntoIterator<Item = A>>(iter: T) -> LinkedList<A> {
         let mut ret = LinkedList::new();
         ret.extend(iter);
         ret
@@ -847,7 +942,7 @@ impl<T> IntoIterator for LinkedList<T> {
     /// Consumes the list into an iterator yielding elements by value.
     #[inline]
     fn into_iter(self) -> IntoIter<T> {
-        IntoIter{list: self}
+        IntoIter { list: self }
     }
 }
 
@@ -861,6 +956,7 @@ impl<'a, T> IntoIterator for &'a LinkedList<T> {
     }
 }
 
+#[stable(feature = "rust1", since = "1.0.0")]
 impl<'a, T> IntoIterator for &'a mut LinkedList<T> {
     type Item = &'a mut T;
     type IntoIter = IterMut<'a, T>;
@@ -872,21 +968,28 @@ impl<'a, T> IntoIterator for &'a mut LinkedList<T> {
 
 #[stable(feature = "rust1", since = "1.0.0")]
 impl<A> Extend<A> for LinkedList<A> {
-    fn extend<T: IntoIterator<Item=A>>(&mut self, iter: T) {
-        for elt in iter { self.push_back(elt); }
+    fn extend<T: IntoIterator<Item = A>>(&mut self, iter: T) {
+        for elt in iter {
+            self.push_back(elt);
+        }
+    }
+}
+
+#[stable(feature = "extend_ref", since = "1.2.0")]
+impl<'a, T: 'a + Copy> Extend<&'a T> for LinkedList<T> {
+    fn extend<I: IntoIterator<Item = &'a T>>(&mut self, iter: I) {
+        self.extend(iter.into_iter().cloned());
     }
 }
 
 #[stable(feature = "rust1", since = "1.0.0")]
 impl<A: PartialEq> PartialEq for LinkedList<A> {
     fn eq(&self, other: &LinkedList<A>) -> bool {
-        self.len() == other.len() &&
-            iter::order::eq(self.iter(), other.iter())
+        self.len() == other.len() && self.iter().eq(other.iter())
     }
 
     fn ne(&self, other: &LinkedList<A>) -> bool {
-        self.len() != other.len() ||
-            iter::order::ne(self.iter(), other.iter())
+        self.len() != other.len() || self.iter().ne(other.iter())
     }
 }
 
@@ -896,7 +999,7 @@ impl<A: Eq> Eq for LinkedList<A> {}
 #[stable(feature = "rust1", since = "1.0.0")]
 impl<A: PartialOrd> PartialOrd for LinkedList<A> {
     fn partial_cmp(&self, other: &LinkedList<A>) -> Option<Ordering> {
-        iter::order::partial_cmp(self.iter(), other.iter())
+        self.iter().partial_cmp(other.iter())
     }
 }
 
@@ -904,7 +1007,7 @@ impl<A: PartialOrd> PartialOrd for LinkedList<A> {
 impl<A: Ord> Ord for LinkedList<A> {
     #[inline]
     fn cmp(&self, other: &LinkedList<A>) -> Ordering {
-        iter::order::cmp(self.iter(), other.iter())
+        self.iter().cmp(other.iter())
     }
 }
 
@@ -918,7 +1021,7 @@ impl<A: Clone> Clone for LinkedList<A> {
 #[stable(feature = "rust1", since = "1.0.0")]
 impl<A: fmt::Debug> fmt::Debug for LinkedList<A> {
     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
-        self.iter().fold(f.debug_list(), |b, e| b.entry(e)).finish()
+        f.debug_list().entries(self.iter()).finish()
     }
 }
 
@@ -932,11 +1035,114 @@ impl<A: Hash> Hash for LinkedList<A> {
     }
 }
 
+unsafe fn finalize<T>(node: IntermediateBox<Node<T>>) -> Box<Node<T>> {
+    let mut node = node.finalize();
+    ptr::write(&mut node.next, None);
+    ptr::write(&mut node.prev, Rawlink::none());
+    node
+}
+
+/// A place for insertion at the front of a `LinkedList`.
+///
+/// See [`LinkedList::front_place`](struct.LinkedList.html#method.front_place) for details.
+#[must_use = "places do nothing unless written to with `<-` syntax"]
+#[unstable(feature = "collection_placement",
+           reason = "struct name and placement protocol are subject to change",
+           issue = "30172")]
+pub struct FrontPlace<'a, T: 'a> {
+    list: &'a mut LinkedList<T>,
+    node: IntermediateBox<Node<T>>,
+}
+
+#[unstable(feature = "collection_placement",
+           reason = "placement protocol is subject to change",
+           issue = "30172")]
+impl<'a, T> Placer<T> for FrontPlace<'a, T> {
+    type Place = Self;
+
+    fn make_place(self) -> Self {
+        self
+    }
+}
+
+#[unstable(feature = "collection_placement",
+           reason = "placement protocol is subject to change",
+           issue = "30172")]
+impl<'a, T> Place<T> for FrontPlace<'a, T> {
+    fn pointer(&mut self) -> *mut T {
+        unsafe { &mut (*self.node.pointer()).value }
+    }
+}
+
+#[unstable(feature = "collection_placement",
+           reason = "placement protocol is subject to change",
+           issue = "30172")]
+impl<'a, T> InPlace<T> for FrontPlace<'a, T> {
+    type Owner = ();
+
+    unsafe fn finalize(self) {
+        let FrontPlace { list, node } = self;
+        list.push_front_node(finalize(node));
+    }
+}
+
+/// A place for insertion at the back of a `LinkedList`.
+///
+/// See [`LinkedList::back_place`](struct.LinkedList.html#method.back_place) for details.
+#[must_use = "places do nothing unless written to with `<-` syntax"]
+#[unstable(feature = "collection_placement",
+           reason = "struct name and placement protocol are subject to change",
+           issue = "30172")]
+pub struct BackPlace<'a, T: 'a> {
+    list: &'a mut LinkedList<T>,
+    node: IntermediateBox<Node<T>>,
+}
+
+#[unstable(feature = "collection_placement",
+           reason = "placement protocol is subject to change",
+           issue = "30172")]
+impl<'a, T> Placer<T> for BackPlace<'a, T> {
+    type Place = Self;
+
+    fn make_place(self) -> Self {
+        self
+    }
+}
+
+#[unstable(feature = "collection_placement",
+           reason = "placement protocol is subject to change",
+           issue = "30172")]
+impl<'a, T> Place<T> for BackPlace<'a, T> {
+    fn pointer(&mut self) -> *mut T {
+        unsafe { &mut (*self.node.pointer()).value }
+    }
+}
+
+#[unstable(feature = "collection_placement",
+           reason = "placement protocol is subject to change",
+           issue = "30172")]
+impl<'a, T> InPlace<T> for BackPlace<'a, T> {
+    type Owner = ();
+
+    unsafe fn finalize(self) {
+        let BackPlace { list, node } = self;
+        list.push_back_node(finalize(node));
+    }
+}
+
+// Ensure that `LinkedList` and its read-only iterators are covariant in their type parameters.
+#[allow(dead_code)]
+fn assert_covariance() {
+    fn a<'a>(x: LinkedList<&'static str>) -> LinkedList<&'a str> { x }
+    fn b<'i, 'a>(x: Iter<'i, &'static str>) -> Iter<'i, &'a str> { x }
+    fn c<'a>(x: IntoIter<&'static str>) -> IntoIter<&'a str> { x }
+}
+
 #[cfg(test)]
-mod test {
+mod tests {
     use std::clone::Clone;
-    use std::iter::{Iterator, IntoIterator};
-    use std::option::Option::{Some, None, self};
+    use std::iter::{Iterator, IntoIterator, Extend};
+    use std::option::Option::{self, Some, None};
     use std::__rand::{thread_rng, Rng};
     use std::thread;
     use std::vec::Vec;
@@ -953,13 +1159,16 @@ mod test {
         let mut last_ptr: Option<&Node<T>> = None;
         let mut node_ptr: &Node<T>;
         match list.list_head {
-            None => { assert_eq!(0, list.length); return }
+            None => {
+                assert_eq!(0, list.length);
+                return;
+            }
             Some(ref node) => node_ptr = &**node,
         }
         loop {
-            match (last_ptr, node_ptr.prev.resolve_immut()) {
-                (None   , None      ) => {}
-                (None   , _         ) => panic!("prev link for list_head"),
+            match unsafe { (last_ptr, node_ptr.prev.resolve()) } {
+                (None, None) => {}
+                (None, _) => panic!("prev link for list_head"),
                 (Some(p), Some(pptr)) => {
                     assert_eq!(p as *const Node<T>, pptr as *const Node<T>);
                 }
@@ -1016,8 +1225,8 @@ mod test {
         }
 
         // Non-empty to non-empty
-        let v = vec![1,2,3,4,5];
-        let u = vec![9,8,1,2,3,4,5];
+        let v = vec![1, 2, 3, 4, 5];
+        let u = vec![9, 8, 1, 2, 3, 4, 5];
         let mut m = list_from(&v);
         let mut n = list_from(&u);
         m.append(&mut n);
@@ -1039,7 +1248,7 @@ mod test {
 
     #[test]
     fn test_insert_prev() {
-        let mut m = list_from(&[0,2,4,6,8]);
+        let mut m = list_from(&[0, 2, 4, 6, 8]);
         let len = m.len();
         {
             let mut it = m.iter_mut();
@@ -1061,17 +1270,21 @@ mod test {
         }
         check_links(&m);
         assert_eq!(m.len(), 3 + len * 2);
-        assert_eq!(m.into_iter().collect::<Vec<_>>(), [-2,0,1,2,3,4,5,6,7,8,9,0,1]);
+        assert_eq!(m.into_iter().collect::<Vec<_>>(),
+                   [-2, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1]);
     }
 
     #[test]
     fn test_send() {
-        let n = list_from(&[1,2,3]);
+        let n = list_from(&[1, 2, 3]);
         thread::spawn(move || {
             check_links(&n);
-            let a: &[_] = &[&1,&2,&3];
+            let a: &[_] = &[&1, &2, &3];
             assert_eq!(a, &n.iter().collect::<Vec<_>>()[..]);
-        }).join().ok().unwrap();
+        })
+            .join()
+            .ok()
+            .unwrap();
     }
 
     #[test]
@@ -1083,6 +1296,46 @@ mod test {
         }
     }
 
+    #[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);
+    }
+
+    #[test]
+    fn test_split_off() {
+        let mut v1 = LinkedList::new();
+        v1.push_front(1u8);
+        v1.push_front(1u8);
+        v1.push_front(1u8);
+        v1.push_front(1u8);
+
+        // test all splits
+        for ix in 0..1 + v1.len() {
+            let mut a = v1.clone();
+            let b = a.split_off(ix);
+            check_links(&a);
+            check_links(&b);
+            a.extend(b);
+            assert_eq!(v1, a);
+        }
+    }
+
+
     #[cfg(test)]
     fn fuzz_test(sz: i32) {
         let mut m: LinkedList<_> = LinkedList::new();
@@ -1101,7 +1354,7 @@ mod test {
                         v.remove(0);
                     }
                 }
-                2 | 4 =>  {
+                2 | 4 => {
                     m.push_front(-i);
                     v.insert(0, -i);
                 }
@@ -1115,7 +1368,7 @@ mod test {
         check_links(&m);
 
         let mut i = 0;
-        for (a, &b) in m.into_iter().zip(v.iter()) {
+        for (a, &b) in m.into_iter().zip(&v) {
             i += 1;
             assert_eq!(a, b);
         }