diff --git a/src/liballoc/collections/linked_list.rs b/src/liballoc/collections/linked_list.rs index 40a82d6feaa98..21b0eb321e3f7 100644 --- a/src/liballoc/collections/linked_list.rs +++ b/src/liballoc/collections/linked_list.rs @@ -20,6 +20,8 @@ use core::marker::PhantomData; use core::mem; use core::ptr::NonNull; +use crate::abort_adapter::AbortAdapter; +use crate::alloc::{Alloc, Global}; use crate::boxed::Box; use super::SpecExtend; @@ -32,17 +34,19 @@ use super::SpecExtend; /// `LinkedList`. In general, array-based containers are faster, /// more memory efficient and make better use of CPU cache. #[stable(feature = "rust1", since = "1.0.0")] -pub struct LinkedList { - head: Option>>, - tail: Option>>, +pub struct LinkedList> { + head: Option>>, + tail: Option>>, len: usize, - marker: PhantomData>>, + alloc: A, + marker: PhantomData, A>>, } -struct Node { - next: Option>>, - prev: Option>>, +struct Node { + next: Option>>, + prev: Option>>, element: T, + marker: PhantomData, A>>, } /// An iterator over the elements of a `LinkedList`. @@ -53,15 +57,16 @@ struct Node { /// [`iter`]: struct.LinkedList.html#method.iter /// [`LinkedList`]: struct.LinkedList.html #[stable(feature = "rust1", since = "1.0.0")] -pub struct Iter<'a, T: 'a> { - head: Option>>, - tail: Option>>, + +pub struct Iter<'a, T: 'a, A: 'a + Alloc = AbortAdapter > { + head: Option>>, + tail: Option>>, len: usize, - marker: PhantomData<&'a Node>, + marker: PhantomData<&'a Node>, } #[stable(feature = "collection_debug", since = "1.17.0")] -impl fmt::Debug for Iter<'_, T> { +impl<'a, T: fmt::Debug, A: 'a + Alloc> fmt::Debug for Iter<'a, T, A> { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { f.debug_tuple("Iter") .field(&self.len) @@ -71,7 +76,7 @@ impl fmt::Debug for Iter<'_, T> { // FIXME(#26925) Remove in favor of `#[derive(Clone)]` #[stable(feature = "rust1", since = "1.0.0")] -impl Clone for Iter<'_, T> { +impl Clone for Iter<'_, T, A> { fn clone(&self) -> Self { Iter { ..*self } } @@ -85,13 +90,13 @@ impl Clone for Iter<'_, T> { /// [`iter_mut`]: struct.LinkedList.html#method.iter_mut /// [`LinkedList`]: struct.LinkedList.html #[stable(feature = "rust1", since = "1.0.0")] -pub struct IterMut<'a, T: 'a> { +pub struct IterMut<'a, T: 'a, A: Alloc + Clone + 'a = AbortAdapter> { // We do *not* exclusively own the entire list here, references to node's `element` // have been handed out by the iterator! So be careful when using this; the methods // called must be aware that there can be aliasing pointers to `element`. - list: &'a mut LinkedList, - head: Option>>, - tail: Option>>, + list: &'a mut LinkedList, + head: Option>>, + tail: Option>>, len: usize, } @@ -112,10 +117,16 @@ impl fmt::Debug for IterMut<'_, T> { /// /// [`into_iter`]: struct.LinkedList.html#method.into_iter /// [`LinkedList`]: struct.LinkedList.html -#[derive(Clone)] #[stable(feature = "rust1", since = "1.0.0")] -pub struct IntoIter { - list: LinkedList, +pub struct IntoIter> { + list: LinkedList, +} + +#[stable(feature = "rust1", since = "1.0.0")] +impl Clone for IntoIter { + fn clone(&self) -> Self { + IntoIter { list: self.list.clone() } + } } #[stable(feature = "collection_debug", since = "1.17.0")] @@ -127,25 +138,26 @@ impl fmt::Debug for IntoIter { } } -impl Node { +impl Node { fn new(element: T) -> Self { Node { next: None, prev: None, element, + marker: PhantomData } } - fn into_element(self: Box) -> T { + fn into_element(self: Box) -> T { self.element } } // private methods -impl LinkedList { +impl LinkedList { /// Adds the given node to the front of the list. #[inline] - fn push_front_node(&mut self, mut node: Box>) { + fn push_front_node(&mut self, mut node: Box, A>) { // This method takes care not to create mutable references to whole nodes, // to maintain validity of aliasing pointers into `element`. unsafe { @@ -166,11 +178,11 @@ impl LinkedList { /// Removes and returns the node at the front of the list. #[inline] - fn pop_front_node(&mut self) -> Option>> { + fn pop_front_node(&mut self) -> Option, A>> { // This method takes care not to create mutable references to whole nodes, // to maintain validity of aliasing pointers into `element`. self.head.map(|node| unsafe { - let node = Box::from_raw(node.as_ptr()); + let node = Box::from_raw_in(node.as_ptr(), self.alloc.clone()); self.head = node.next; match self.head { @@ -186,7 +198,7 @@ impl LinkedList { /// Adds the given node to the back of the list. #[inline] - fn push_back_node(&mut self, mut node: Box>) { + fn push_back_node(&mut self, mut node: Box, A>) { // This method takes care not to create mutable references to whole nodes, // to maintain validity of aliasing pointers into `element`. unsafe { @@ -207,11 +219,11 @@ impl LinkedList { /// Removes and returns the node at the back of the list. #[inline] - fn pop_back_node(&mut self) -> Option>> { + fn pop_back_node(&mut self) -> Option, A>> { // This method takes care not to create mutable references to whole nodes, // to maintain validity of aliasing pointers into `element`. self.tail.map(|node| unsafe { - let node = Box::from_raw(node.as_ptr()); + let node = Box::from_raw_in(node.as_ptr(), self.alloc.clone()); self.tail = node.prev; match self.tail { @@ -232,7 +244,7 @@ impl LinkedList { /// This method takes care not to create mutable references to `element`, to /// maintain validity of aliasing pointers. #[inline] - unsafe fn unlink_node(&mut self, mut node: NonNull>) { + unsafe fn unlink_node(&mut self, mut node: NonNull>) { let node = node.as_mut(); // this one is ours now, we can create an &mut. // Not creating new mutable (unique!) references overlapping `element`. @@ -274,10 +286,60 @@ impl LinkedList { #[inline] #[stable(feature = "rust1", since = "1.0.0")] pub fn new() -> Self { + Self::new_in(Default::default()) + } + + /// Appends an element to the back of a list + /// + /// # Examples + /// + /// ``` + /// use std::collections::LinkedList; + /// + /// let mut d = LinkedList::new(); + /// d.push_back(1); + /// d.push_back(3); + /// assert_eq!(3, *d.back().unwrap()); + /// ``` + #[stable(feature = "rust1", since = "1.0.0")] + pub fn push_back(&mut self, elt: T) { + let Ok(()) = self.push_back_alloc(elt); + } + + /// Adds an element first in the list. + /// + /// This operation should compute in O(1) time. + /// + /// # Examples + /// + /// ``` + /// use std::collections::LinkedList; + /// + /// let mut dl = LinkedList::new(); + /// + /// dl.push_front(2); + /// assert_eq!(dl.front().unwrap(), &2); + /// + /// dl.push_front(1); + /// assert_eq!(dl.front().unwrap(), &1); + /// ``` + #[stable(feature = "rust1", since = "1.0.0")] + pub fn push_front(&mut self, elt: T) { + let Ok(()) = self.push_front_alloc(elt); + } +} + +impl LinkedList { + /// like `Self::new` but with an explicit allocator rather than the default + /// global one. + #[inline] + #[stable(feature = "rust1", since = "1.0.0")] + pub fn new_in(a: A) -> Self { LinkedList { head: None, tail: None, len: 0, + alloc: a, marker: PhantomData, } } @@ -352,7 +414,7 @@ impl LinkedList { /// ``` #[inline] #[stable(feature = "rust1", since = "1.0.0")] - pub fn iter(&self) -> Iter<'_, T> { + pub fn iter(&self) -> Iter<'_, T, A> { Iter { head: self.head, tail: self.tail, @@ -386,7 +448,7 @@ impl LinkedList { /// ``` #[inline] #[stable(feature = "rust1", since = "1.0.0")] - pub fn iter_mut(&mut self) -> IterMut<'_, T> { + pub fn iter_mut(&mut self) -> IterMut<'_, T, A> { IterMut { head: self.head, tail: self.tail, @@ -465,7 +527,7 @@ impl LinkedList { #[inline] #[stable(feature = "rust1", since = "1.0.0")] pub fn clear(&mut self) { - *self = Self::new(); + *self = Self::new_in(self.alloc.clone()); } /// Returns `true` if the `LinkedList` contains an element equal to the @@ -610,8 +672,10 @@ impl LinkedList { /// assert_eq!(dl.front().unwrap(), &1); /// ``` #[stable(feature = "rust1", since = "1.0.0")] - pub fn push_front(&mut self, elt: T) { - self.push_front_node(box Node::new(elt)); + pub fn push_front_alloc(&mut self, elt: T) -> Result<(), A::Err> { + let alloc = self.alloc.clone(); + self.push_front_node(Box::new_in(Node::new(elt), alloc)?); + Ok(()) } /// Removes the first element and returns it, or `None` if the list is @@ -653,8 +717,10 @@ impl LinkedList { /// assert_eq!(3, *d.back().unwrap()); /// ``` #[stable(feature = "rust1", since = "1.0.0")] - pub fn push_back(&mut self, elt: T) { - self.push_back_node(box Node::new(elt)); + pub fn push_back_alloc(&mut self, elt: T) -> Result<(), A::Err> { + let alloc = self.alloc.clone(); + self.push_back_node(Box::new_in(Node::new(elt), alloc)?); + Ok(()) } /// Removes the last element from a list and returns it, or `None` if @@ -704,13 +770,14 @@ impl LinkedList { /// assert_eq!(splitted.pop_front(), None); /// ``` #[stable(feature = "rust1", since = "1.0.0")] - pub fn split_off(&mut self, at: usize) -> LinkedList { + pub fn split_off(&mut self, at: usize) -> Self { let len = self.len(); assert!(at <= len, "Cannot split off at a nonexistent index"); if at == 0 { - return mem::replace(self, Self::new()); + let alloc = self.alloc.clone(); + return mem::replace(self, Self::new_in(alloc)); } else if at == len { - return Self::new(); + return Self::new_in(self.alloc.clone()); } // Below, we iterate towards the `i-1`th node, either from the start or the end, @@ -748,6 +815,7 @@ impl LinkedList { head: second_part_head, tail: self.tail, len: len - at, + alloc: self.alloc.clone(), marker: PhantomData, }; @@ -785,7 +853,7 @@ impl LinkedList { /// assert_eq!(odds.into_iter().collect::>(), vec![1, 3, 5, 9, 11, 13, 15]); /// ``` #[unstable(feature = "drain_filter", reason = "recently added", issue = "43244")] - pub fn drain_filter(&mut self, filter: F) -> DrainFilter<'_, T, F> + pub fn drain_filter(&mut self, filter: F) -> DrainFilter<'_, T, F, A> where F: FnMut(&mut T) -> bool { // avoid borrow issues. @@ -803,14 +871,14 @@ impl LinkedList { } #[stable(feature = "rust1", since = "1.0.0")] -unsafe impl<#[may_dangle] T> Drop for LinkedList { +unsafe impl<#[may_dangle] T, A: Alloc + Clone> Drop for LinkedList { fn drop(&mut self) { while let Some(_) = self.pop_front_node() {} } } #[stable(feature = "rust1", since = "1.0.0")] -impl<'a, T> Iterator for Iter<'a, T> { +impl<'a, T, A: Alloc> Iterator for Iter<'a, T, A> { type Item = &'a T; #[inline] @@ -835,7 +903,7 @@ impl<'a, T> Iterator for Iter<'a, T> { } #[stable(feature = "rust1", since = "1.0.0")] -impl<'a, T> DoubleEndedIterator for Iter<'a, T> { +impl<'a, T, A: Alloc> DoubleEndedIterator for Iter<'a, T, A> { #[inline] fn next_back(&mut self) -> Option<&'a T> { if self.len == 0 { @@ -853,13 +921,13 @@ impl<'a, T> DoubleEndedIterator for Iter<'a, T> { } #[stable(feature = "rust1", since = "1.0.0")] -impl ExactSizeIterator for Iter<'_, T> {} +impl ExactSizeIterator for Iter<'_, T, A> {} #[stable(feature = "fused", since = "1.26.0")] -impl FusedIterator for Iter<'_, T> {} +impl FusedIterator for Iter<'_, T, A> {} #[stable(feature = "rust1", since = "1.0.0")] -impl<'a, T> Iterator for IterMut<'a, T> { +impl<'a, T, A: Alloc + Clone> Iterator for IterMut<'a, T, A> { type Item = &'a mut T; #[inline] @@ -884,7 +952,7 @@ impl<'a, T> Iterator for IterMut<'a, T> { } #[stable(feature = "rust1", since = "1.0.0")] -impl<'a, T> DoubleEndedIterator for IterMut<'a, T> { +impl<'a, T, A: Alloc + Clone> DoubleEndedIterator for IterMut<'a, T, A> { #[inline] fn next_back(&mut self) -> Option<&'a mut T> { if self.len == 0 { @@ -902,10 +970,10 @@ impl<'a, T> DoubleEndedIterator for IterMut<'a, T> { } #[stable(feature = "rust1", since = "1.0.0")] -impl ExactSizeIterator for IterMut<'_, T> {} +impl ExactSizeIterator for IterMut<'_, T, A> {} #[stable(feature = "fused", since = "1.26.0")] -impl FusedIterator for IterMut<'_, T> {} +impl FusedIterator for IterMut<'_, T, A> {} impl IterMut<'_, T> { /// Inserts the given element just after the element most recently returned by `.next()`. @@ -936,21 +1004,32 @@ impl IterMut<'_, T> { reason = "this is probably better handled by a cursor type -- we'll see", issue = "27794")] pub fn insert_next(&mut self, element: T) { - match self.head { + let Ok(()) = self.insert_next_alloc(element); + } +} + +impl<'a, T, A: Alloc + Clone> IterMut<'a, T, A> { + /// Like `Self::insert_next` but allows non-standard allocators. Might need + /// to be separate for stability reasons. + #[inline] + #[unstable(feature = "allocator_api", issue = "32838")] + pub fn insert_next_alloc(&mut self, element: T) -> Result<(), A::Err> { + Ok(match self.head { // `push_back` is okay with aliasing `element` references - None => self.list.push_back(element), + None => self.list.push_back_alloc(element)?, Some(head) => unsafe { + // `push_front` is okay with aliasing nodes let prev = match head.as_ref().prev { - // `push_front` is okay with aliasing nodes - None => return self.list.push_front(element), + None => return self.list.push_front_alloc(element), Some(prev) => prev, }; - let node = Some(Box::into_raw_non_null(box Node { + let node = Some(NonNull::from(Box::into_unique(Box::new_in(Node { next: Some(head), prev: Some(prev), element, - })); + marker: PhantomData, + }, self.list.alloc.clone())?))); // Not creating references to entire nodes to not invalidate the // reference to `element` we handed to the user. @@ -959,7 +1038,7 @@ impl IterMut<'_, T> { self.list.len += 1; }, - } + }) } /// Provides a reference to the next element, without changing the iterator. @@ -996,18 +1075,18 @@ impl IterMut<'_, T> { /// An iterator produced by calling `drain_filter` on LinkedList. #[unstable(feature = "drain_filter", reason = "recently added", issue = "43244")] -pub struct DrainFilter<'a, T: 'a, F: 'a> - where F: FnMut(&mut T) -> bool, +pub struct DrainFilter<'a, T: 'a, F: 'a, A: 'a = AbortAdapter> + where A: Alloc + Clone, F: FnMut(&mut T) -> bool, { - list: &'a mut LinkedList, - it: Option>>, + list: &'a mut LinkedList, + it: Option>>, pred: F, idx: usize, old_len: usize, } #[unstable(feature = "drain_filter", reason = "recently added", issue = "43244")] -impl Iterator for DrainFilter<'_, T, F> +impl Iterator for DrainFilter<'_, T, F, A> where F: FnMut(&mut T) -> bool, { type Item = T; @@ -1035,7 +1114,7 @@ impl Iterator for DrainFilter<'_, T, F> } #[unstable(feature = "drain_filter", reason = "recently added", issue = "43244")] -impl Drop for DrainFilter<'_, T, F> +impl Drop for DrainFilter<'_, T, F, A> where F: FnMut(&mut T) -> bool, { fn drop(&mut self) { @@ -1044,7 +1123,7 @@ impl Drop for DrainFilter<'_, T, F> } #[unstable(feature = "drain_filter", reason = "recently added", issue = "43244")] -impl fmt::Debug for DrainFilter<'_, T, F> +impl fmt::Debug for DrainFilter<'_, T, F, A> where F: FnMut(&mut T) -> bool { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { @@ -1055,7 +1134,7 @@ impl fmt::Debug for DrainFilter<'_, T, F> } #[stable(feature = "rust1", since = "1.0.0")] -impl Iterator for IntoIter { +impl Iterator for IntoIter { type Item = T; #[inline] @@ -1070,7 +1149,7 @@ impl Iterator for IntoIter { } #[stable(feature = "rust1", since = "1.0.0")] -impl DoubleEndedIterator for IntoIter { +impl DoubleEndedIterator for IntoIter { #[inline] fn next_back(&mut self) -> Option { self.list.pop_back() @@ -1078,10 +1157,10 @@ impl DoubleEndedIterator for IntoIter { } #[stable(feature = "rust1", since = "1.0.0")] -impl ExactSizeIterator for IntoIter {} +impl ExactSizeIterator for IntoIter {} #[stable(feature = "fused", since = "1.26.0")] -impl FusedIterator for IntoIter {} +impl FusedIterator for IntoIter {} #[stable(feature = "rust1", since = "1.0.0")] impl FromIterator for LinkedList { @@ -1093,65 +1172,67 @@ impl FromIterator for LinkedList { } #[stable(feature = "rust1", since = "1.0.0")] -impl IntoIterator for LinkedList { +impl IntoIterator for LinkedList { type Item = T; - type IntoIter = IntoIter; + type IntoIter = IntoIter; /// Consumes the list into an iterator yielding elements by value. #[inline] - fn into_iter(self) -> IntoIter { + fn into_iter(self) -> IntoIter { IntoIter { list: self } } } #[stable(feature = "rust1", since = "1.0.0")] -impl<'a, T> IntoIterator for &'a LinkedList { +impl<'a, T, A: Alloc + Clone> IntoIterator for &'a LinkedList { type Item = &'a T; - type IntoIter = Iter<'a, T>; + type IntoIter = Iter<'a, T, A>; - fn into_iter(self) -> Iter<'a, T> { + fn into_iter(self) -> Iter<'a, T, A> { self.iter() } } #[stable(feature = "rust1", since = "1.0.0")] -impl<'a, T> IntoIterator for &'a mut LinkedList { +impl<'a, T, A: Alloc + Clone> IntoIterator for &'a mut LinkedList { type Item = &'a mut T; - type IntoIter = IterMut<'a, T>; + type IntoIter = IterMut<'a, T, A>; - fn into_iter(self) -> IterMut<'a, T> { + fn into_iter(self) -> IterMut<'a, T, A> { self.iter_mut() } } #[stable(feature = "rust1", since = "1.0.0")] -impl Extend for LinkedList { +impl + Clone> Extend for LinkedList { fn extend>(&mut self, iter: I) { >::spec_extend(self, iter); } } -impl SpecExtend for LinkedList { +impl + Clone> SpecExtend for LinkedList { default fn spec_extend(&mut self, iter: I) { - iter.into_iter().for_each(move |elt| self.push_back(elt)); + iter.into_iter().for_each(move |elt| { + let Ok(()) = self.push_back_alloc(elt); + }); } } -impl SpecExtend> for LinkedList { - fn spec_extend(&mut self, ref mut other: LinkedList) { +impl + Clone> SpecExtend> for LinkedList { + fn spec_extend(&mut self, ref mut other: LinkedList) { self.append(other); } } #[stable(feature = "extend_ref", since = "1.2.0")] -impl<'a, T: 'a + Copy> Extend<&'a T> for LinkedList { +impl<'a, T: 'a + Copy, A: Alloc + Clone> Extend<&'a T> for LinkedList { fn extend>(&mut self, iter: I) { self.extend(iter.into_iter().cloned()); } } #[stable(feature = "rust1", since = "1.0.0")] -impl PartialEq for LinkedList { +impl PartialEq for LinkedList { fn eq(&self, other: &Self) -> bool { self.len() == other.len() && self.iter().eq(other) } @@ -1162,17 +1243,17 @@ impl PartialEq for LinkedList { } #[stable(feature = "rust1", since = "1.0.0")] -impl Eq for LinkedList {} +impl Eq for LinkedList {} #[stable(feature = "rust1", since = "1.0.0")] -impl PartialOrd for LinkedList { +impl PartialOrd for LinkedList { fn partial_cmp(&self, other: &Self) -> Option { self.iter().partial_cmp(other) } } #[stable(feature = "rust1", since = "1.0.0")] -impl Ord for LinkedList { +impl Ord for LinkedList { #[inline] fn cmp(&self, other: &Self) -> Ordering { self.iter().cmp(other) @@ -1187,14 +1268,14 @@ impl Clone for LinkedList { } #[stable(feature = "rust1", since = "1.0.0")] -impl fmt::Debug for LinkedList { +impl fmt::Debug for LinkedList { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { f.debug_list().entries(self).finish() } } #[stable(feature = "rust1", since = "1.0.0")] -impl Hash for LinkedList { +impl Hash for LinkedList { fn hash(&self, state: &mut H) { self.len().hash(state); for elt in self { @@ -1218,10 +1299,10 @@ fn assert_covariance() { } #[stable(feature = "rust1", since = "1.0.0")] -unsafe impl Send for LinkedList {} +unsafe impl Send for LinkedList {} #[stable(feature = "rust1", since = "1.0.0")] -unsafe impl Sync for LinkedList {} +unsafe impl Sync for LinkedList {} #[stable(feature = "rust1", since = "1.0.0")] unsafe impl Send for Iter<'_, T> {} @@ -1244,16 +1325,18 @@ mod tests { use super::{LinkedList, Node}; + type GlobalNode = Node>; + #[cfg(test)] - fn list_from(v: &[T]) -> LinkedList { + fn list_from(v: &[T]) -> LinkedList { v.iter().cloned().collect() } - pub fn check_links(list: &LinkedList) { + pub fn check_links(list: &LinkedList) { unsafe { let mut len = 0; - let mut last_ptr: Option<&Node> = None; - let mut node_ptr: &Node; + let mut last_ptr: Option<&GlobalNode> = None; + let mut node_ptr: &GlobalNode; match list.head { None => { // tail node should also be None. @@ -1268,7 +1351,9 @@ mod tests { (None, None) => {} (None, _) => panic!("prev link for head"), (Some(p), Some(pptr)) => { - assert_eq!(p as *const Node, pptr.as_ptr() as *const Node); + assert_eq!( + p as *const GlobalNode, + pptr.as_ptr() as *const GlobalNode); } _ => panic!("prev link is none, not good"), } @@ -1287,7 +1372,7 @@ mod tests { // verify that the tail node points to the last node. let tail = list.tail.as_ref().expect("some tail node").as_ref(); - assert_eq!(tail as *const Node, node_ptr as *const Node); + assert_eq!(tail as *const GlobalNode, node_ptr as *const GlobalNode); // check that len matches interior links. assert_eq!(len, list.len); }