From 34136ab59859198eb32280a8826fd2b0abe441b8 Mon Sep 17 00:00:00 2001 From: Ryan Lowe Date: Sun, 19 Mar 2023 16:15:26 -0400 Subject: [PATCH] Add support for allocators in LinkedList --- library/alloc/src/collections/linked_list.rs | 427 +++++++++++-------- tests/debuginfo/pretty-std.rs | 4 +- 2 files changed, 260 insertions(+), 171 deletions(-) diff --git a/library/alloc/src/collections/linked_list.rs b/library/alloc/src/collections/linked_list.rs index f2f5dffc25d..9b57a6b6c26 100644 --- a/library/alloc/src/collections/linked_list.rs +++ b/library/alloc/src/collections/linked_list.rs @@ -18,9 +18,10 @@ use core::iter::{FromIterator, FusedIterator}; use core::marker::PhantomData; use core::mem; -use core::ptr::NonNull; +use core::ptr::{NonNull, Unique}; use super::SpecExtend; +use crate::alloc::{Allocator, Global}; use crate::boxed::Box; #[cfg(test)] @@ -47,11 +48,15 @@ #[stable(feature = "rust1", since = "1.0.0")] #[cfg_attr(not(test), rustc_diagnostic_item = "LinkedList")] #[rustc_insignificant_dtor] -pub struct LinkedList { +pub struct LinkedList< + T, + #[unstable(feature = "allocator_api", issue = "32838")] A: Allocator = Global, +> { head: Option>>, tail: Option>>, len: usize, - marker: PhantomData>>, + alloc: A, + marker: PhantomData, A>>, } struct Node { @@ -81,6 +86,7 @@ fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { head: self.head, tail: self.tail, len: self.len, + alloc: Global, marker: PhantomData, })) .field(&self.len) @@ -117,6 +123,7 @@ fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { head: self.head, tail: self.tail, len: self.len, + alloc: Global, marker: PhantomData, })) .field(&self.len) @@ -133,12 +140,15 @@ fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { /// [`IntoIterator`]: core::iter::IntoIterator #[derive(Clone)] #[stable(feature = "rust1", since = "1.0.0")] -pub struct IntoIter { - list: LinkedList, +pub struct IntoIter< + T, + #[unstable(feature = "allocator_api", issue = "32838")] A: Allocator = Global, +> { + list: LinkedList, } #[stable(feature = "collection_debug", since = "1.17.0")] -impl fmt::Debug for IntoIter { +impl fmt::Debug for IntoIter { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { f.debug_tuple("IntoIter").field(&self.list).finish() } @@ -149,22 +159,25 @@ fn new(element: T) -> Self { Node { next: None, prev: None, element } } - 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. + /// + /// # Safety + /// `node` must point to a valid node that was boxed using the list's allocator. #[inline] - fn push_front_node(&mut self, mut node: Box>) { + unsafe fn push_front_node(&mut self, node: Unique>) { // This method takes care not to create mutable references to whole nodes, // to maintain validity of aliasing pointers into `element`. unsafe { - node.next = self.head; - node.prev = None; - let node = Some(Box::leak(node).into()); + (*node.as_ptr()).next = self.head; + (*node.as_ptr()).prev = None; + let node = Some(NonNull::from(node)); match self.head { None => self.tail = node, @@ -179,11 +192,11 @@ fn push_front_node(&mut self, mut node: Box>) { /// 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); self.head = node.next; match self.head { @@ -198,14 +211,17 @@ fn pop_front_node(&mut self) -> Option>> { } /// Adds the given node to the back of the list. + /// + /// # Safety + /// `node` must point to a valid node that was boxed using the list's allocator. #[inline] - fn push_back_node(&mut self, mut node: Box>) { + unsafe fn push_back_node(&mut self, node: Unique>) { // This method takes care not to create mutable references to whole nodes, // to maintain validity of aliasing pointers into `element`. unsafe { - node.next = None; - node.prev = self.tail; - let node = Some(Box::leak(node).into()); + (*node.as_ptr()).next = None; + (*node.as_ptr()).prev = self.tail; + let node = Some(NonNull::from(node)); match self.tail { None => self.head = node, @@ -220,11 +236,11 @@ fn push_back_node(&mut self, mut node: Box>) { /// 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); self.tail = node.prev; match self.tail { @@ -322,7 +338,10 @@ unsafe fn split_off_before_node( &mut self, split_node: Option>>, at: usize, - ) -> Self { + ) -> Self + where + A: Clone, + { // The split node is the new head node of the second part if let Some(mut split_node) = split_node { let first_part_head; @@ -343,6 +362,7 @@ unsafe fn split_off_before_node( head: first_part_head, tail: first_part_tail, len: at, + alloc: self.alloc.clone(), marker: PhantomData, }; @@ -352,7 +372,7 @@ unsafe fn split_off_before_node( first_part } else { - mem::replace(self, LinkedList::new()) + mem::replace(self, LinkedList::new_in(self.alloc.clone())) } } @@ -361,7 +381,10 @@ unsafe fn split_off_after_node( &mut self, split_node: Option>>, at: usize, - ) -> Self { + ) -> Self + where + A: Clone, + { // The split node is the new tail node of the first part and owns // the head of the second part. if let Some(mut split_node) = split_node { @@ -383,6 +406,7 @@ unsafe fn split_off_after_node( head: second_part_head, tail: second_part_tail, len: self.len - at, + alloc: self.alloc.clone(), marker: PhantomData, }; @@ -392,7 +416,7 @@ unsafe fn split_off_after_node( second_part } else { - mem::replace(self, LinkedList::new()) + mem::replace(self, LinkedList::new_in(self.alloc.clone())) } } } @@ -421,7 +445,7 @@ impl LinkedList { #[stable(feature = "rust1", since = "1.0.0")] #[must_use] pub const fn new() -> Self { - LinkedList { head: None, tail: None, len: 0, marker: PhantomData } + LinkedList { head: None, tail: None, len: 0, alloc: Global, marker: PhantomData } } /// Moves all elements from `other` to the end of the list. @@ -472,7 +496,26 @@ pub fn append(&mut self, other: &mut Self) { } } } +} +impl LinkedList { + /// Constructs an empty `LinkedList`. + /// + /// # Examples + /// + /// ``` + /// #![feature(allocator_api)] + /// + /// use std::alloc::System; + /// use std::collections::LinkedList; + /// + /// let list: LinkedList = LinkedList::new_in(System); + /// ``` + #[inline] + #[unstable(feature = "allocator_api", issue = "32838")] + pub const fn new_in(alloc: A) -> Self { + LinkedList { head: None, tail: None, len: 0, alloc, marker: PhantomData } + } /// Provides a forward iterator. /// /// # Examples @@ -533,7 +576,7 @@ pub fn iter_mut(&mut self) -> IterMut<'_, T> { #[inline] #[must_use] #[unstable(feature = "linked_list_cursors", issue = "58533")] - pub fn cursor_front(&self) -> Cursor<'_, T> { + pub fn cursor_front(&self) -> Cursor<'_, T, A> { Cursor { index: 0, current: self.head, list: self } } @@ -543,7 +586,7 @@ pub fn cursor_front(&self) -> Cursor<'_, T> { #[inline] #[must_use] #[unstable(feature = "linked_list_cursors", issue = "58533")] - pub fn cursor_front_mut(&mut self) -> CursorMut<'_, T> { + pub fn cursor_front_mut(&mut self) -> CursorMut<'_, T, A> { CursorMut { index: 0, current: self.head, list: self } } @@ -553,7 +596,7 @@ pub fn cursor_front_mut(&mut self) -> CursorMut<'_, T> { #[inline] #[must_use] #[unstable(feature = "linked_list_cursors", issue = "58533")] - pub fn cursor_back(&self) -> Cursor<'_, T> { + pub fn cursor_back(&self) -> Cursor<'_, T, A> { Cursor { index: self.len.checked_sub(1).unwrap_or(0), current: self.tail, list: self } } @@ -563,7 +606,7 @@ pub fn cursor_back(&self) -> Cursor<'_, T> { #[inline] #[must_use] #[unstable(feature = "linked_list_cursors", issue = "58533")] - pub fn cursor_back_mut(&mut self) -> CursorMut<'_, T> { + pub fn cursor_back_mut(&mut self) -> CursorMut<'_, T, A> { CursorMut { index: self.len.checked_sub(1).unwrap_or(0), current: self.tail, list: self } } @@ -639,7 +682,15 @@ pub fn len(&self) -> usize { #[inline] #[stable(feature = "rust1", since = "1.0.0")] pub fn clear(&mut self) { - *self = Self::new(); + // We need to drop the nodes while keeping self.alloc + // We can do this by moving (head, tail, len) into a new list that borrows self.alloc + drop(LinkedList { + head: self.head.take(), + tail: self.tail.take(), + len: mem::take(&mut self.len), + alloc: &self.alloc, + marker: PhantomData, + }); } /// Returns `true` if the `LinkedList` contains an element equal to the @@ -791,7 +842,12 @@ pub fn back_mut(&mut self) -> Option<&mut T> { /// ``` #[stable(feature = "rust1", since = "1.0.0")] pub fn push_front(&mut self, elt: T) { - self.push_front_node(Box::new(Node::new(elt))); + let node = Box::new_in(Node::new(elt), &self.alloc); + let node_ptr = Unique::from(Box::leak(node)); + // SAFETY: node_ptr is a unique pointer to a node we boxed with self.alloc + unsafe { + self.push_front_node(node_ptr); + } } /// Removes the first element and returns it, or `None` if the list is @@ -834,7 +890,12 @@ pub fn pop_front(&mut self) -> Option { /// ``` #[stable(feature = "rust1", since = "1.0.0")] pub fn push_back(&mut self, elt: T) { - self.push_back_node(Box::new(Node::new(elt))); + let node = Box::new_in(Node::new(elt), &self.alloc); + let node_ptr = Unique::from(Box::leak(node)); + // SAFETY: node_ptr is a unique pointer to a node we boxed with self.alloc + unsafe { + self.push_back_node(node_ptr); + } } /// Removes the last element from a list and returns it, or `None` if @@ -884,13 +945,16 @@ pub fn pop_back(&mut self) -> Option { /// assert_eq!(split.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) -> LinkedList + where + A: Clone, + { let len = self.len(); assert!(at <= len, "Cannot split off at a nonexistent index"); if at == 0 { - return mem::take(self); + return mem::replace(self, Self::new_in(self.alloc.clone())); } 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, @@ -988,7 +1052,7 @@ pub fn remove(&mut self, at: usize) -> T { /// 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, { @@ -1001,11 +1065,11 @@ pub fn drain_filter(&mut self, filter: F) -> DrainFilter<'_, T, F> } #[stable(feature = "rust1", since = "1.0.0")] -unsafe impl<#[may_dangle] T> Drop for LinkedList { +unsafe impl<#[may_dangle] T, A: Allocator> Drop for LinkedList { fn drop(&mut self) { - struct DropGuard<'a, T>(&'a mut LinkedList); + struct DropGuard<'a, T, A: Allocator>(&'a mut LinkedList); - impl<'a, T> Drop for DropGuard<'a, T> { + impl<'a, T, A: Allocator> Drop for DropGuard<'a, T, A> { fn drop(&mut self) { // Continue the same loop we do below. This only runs when a destructor has // panicked. If another one panics this will abort. @@ -1013,11 +1077,10 @@ fn drop(&mut self) { } } - while let Some(node) = self.pop_front_node() { - let guard = DropGuard(self); - drop(node); - mem::forget(guard); - } + // Wrap self so that if a destructor panics, we can try to keep looping + let guard = DropGuard(self); + while guard.0.pop_front_node().is_some() {} + mem::forget(guard); } } @@ -1139,14 +1202,18 @@ impl FusedIterator for IterMut<'_, T> {} /// /// When created, cursors start at the front of the list, or the "ghost" non-element if the list is empty. #[unstable(feature = "linked_list_cursors", issue = "58533")] -pub struct Cursor<'a, T: 'a> { +pub struct Cursor< + 'a, + T: 'a, + #[unstable(feature = "allocator_api", issue = "32838")] A: Allocator = Global, +> { index: usize, current: Option>>, - list: &'a LinkedList, + list: &'a LinkedList, } #[unstable(feature = "linked_list_cursors", issue = "58533")] -impl Clone for Cursor<'_, T> { +impl Clone for Cursor<'_, T, A> { fn clone(&self) -> Self { let Cursor { index, current, list } = *self; Cursor { index, current, list } @@ -1154,7 +1221,7 @@ fn clone(&self) -> Self { } #[unstable(feature = "linked_list_cursors", issue = "58533")] -impl fmt::Debug for Cursor<'_, T> { +impl fmt::Debug for Cursor<'_, T, A> { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { f.debug_tuple("Cursor").field(&self.list).field(&self.index()).finish() } @@ -1171,20 +1238,24 @@ fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { /// To accommodate this, there is a "ghost" non-element that yields `None` between the head and /// tail of the list. #[unstable(feature = "linked_list_cursors", issue = "58533")] -pub struct CursorMut<'a, T: 'a> { +pub struct CursorMut< + 'a, + T: 'a, + #[unstable(feature = "allocator_api", issue = "32838")] A: Allocator = Global, +> { index: usize, current: Option>>, - list: &'a mut LinkedList, + list: &'a mut LinkedList, } #[unstable(feature = "linked_list_cursors", issue = "58533")] -impl fmt::Debug for CursorMut<'_, T> { +impl fmt::Debug for CursorMut<'_, T, A> { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { f.debug_tuple("CursorMut").field(&self.list).field(&self.index()).finish() } } -impl<'a, T> Cursor<'a, T> { +impl<'a, T, A: Allocator> Cursor<'a, T, A> { /// Returns the cursor position index within the `LinkedList`. /// /// This returns `None` if the cursor is currently pointing to the @@ -1301,7 +1372,7 @@ pub fn back(&self) -> Option<&'a T> { } } -impl<'a, T> CursorMut<'a, T> { +impl<'a, T, A: Allocator> CursorMut<'a, T, A> { /// Returns the cursor position index within the `LinkedList`. /// /// This returns `None` if the cursor is currently pointing to the @@ -1406,7 +1477,7 @@ pub fn peek_prev(&mut self) -> Option<&mut T> { /// `CursorMut` is frozen for the lifetime of the `Cursor`. #[must_use] #[unstable(feature = "linked_list_cursors", issue = "58533")] - pub fn as_cursor(&self) -> Cursor<'_, T> { + pub fn as_cursor(&self) -> Cursor<'_, T, A> { Cursor { list: self.list, current: self.current, index: self.index } } } @@ -1414,86 +1485,6 @@ pub fn as_cursor(&self) -> Cursor<'_, T> { // Now the list editing operations impl<'a, T> CursorMut<'a, T> { - /// Inserts a new element into the `LinkedList` after the current one. - /// - /// If the cursor is pointing at the "ghost" non-element then the new element is - /// inserted at the front of the `LinkedList`. - #[unstable(feature = "linked_list_cursors", issue = "58533")] - pub fn insert_after(&mut self, item: T) { - unsafe { - let spliced_node = Box::leak(Box::new(Node::new(item))).into(); - let node_next = match self.current { - None => self.list.head, - Some(node) => node.as_ref().next, - }; - self.list.splice_nodes(self.current, node_next, spliced_node, spliced_node, 1); - if self.current.is_none() { - // The "ghost" non-element's index has changed. - self.index = self.list.len; - } - } - } - - /// Inserts a new element into the `LinkedList` before the current one. - /// - /// If the cursor is pointing at the "ghost" non-element then the new element is - /// inserted at the end of the `LinkedList`. - #[unstable(feature = "linked_list_cursors", issue = "58533")] - pub fn insert_before(&mut self, item: T) { - unsafe { - let spliced_node = Box::leak(Box::new(Node::new(item))).into(); - let node_prev = match self.current { - None => self.list.tail, - Some(node) => node.as_ref().prev, - }; - self.list.splice_nodes(node_prev, self.current, spliced_node, spliced_node, 1); - self.index += 1; - } - } - - /// Removes the current element from the `LinkedList`. - /// - /// The element that was removed is returned, and the cursor is - /// moved to point to the next element in the `LinkedList`. - /// - /// If the cursor is currently pointing to the "ghost" non-element then no element - /// is removed and `None` is returned. - #[unstable(feature = "linked_list_cursors", issue = "58533")] - pub fn remove_current(&mut self) -> Option { - let unlinked_node = self.current?; - unsafe { - self.current = unlinked_node.as_ref().next; - self.list.unlink_node(unlinked_node); - let unlinked_node = Box::from_raw(unlinked_node.as_ptr()); - Some(unlinked_node.element) - } - } - - /// Removes the current element from the `LinkedList` without deallocating the list node. - /// - /// The node that was removed is returned as a new `LinkedList` containing only this node. - /// The cursor is moved to point to the next element in the current `LinkedList`. - /// - /// If the cursor is currently pointing to the "ghost" non-element then no element - /// is removed and `None` is returned. - #[unstable(feature = "linked_list_cursors", issue = "58533")] - pub fn remove_current_as_list(&mut self) -> Option> { - let mut unlinked_node = self.current?; - unsafe { - self.current = unlinked_node.as_ref().next; - self.list.unlink_node(unlinked_node); - - unlinked_node.as_mut().prev = None; - unlinked_node.as_mut().next = None; - Some(LinkedList { - head: Some(unlinked_node), - tail: Some(unlinked_node), - len: 1, - marker: PhantomData, - }) - } - } - /// Inserts the elements from the given `LinkedList` after the current one. /// /// If the cursor is pointing at the "ghost" non-element then the new elements are @@ -1536,6 +1527,92 @@ pub fn splice_before(&mut self, list: LinkedList) { self.index += splice_len; } } +} + +impl<'a, T, A: Allocator> CursorMut<'a, T, A> { + /// Inserts a new element into the `LinkedList` after the current one. + /// + /// If the cursor is pointing at the "ghost" non-element then the new element is + /// inserted at the front of the `LinkedList`. + #[unstable(feature = "linked_list_cursors", issue = "58533")] + pub fn insert_after(&mut self, item: T) { + unsafe { + let spliced_node = Box::leak(Box::new_in(Node::new(item), &self.list.alloc)).into(); + let node_next = match self.current { + None => self.list.head, + Some(node) => node.as_ref().next, + }; + self.list.splice_nodes(self.current, node_next, spliced_node, spliced_node, 1); + if self.current.is_none() { + // The "ghost" non-element's index has changed. + self.index = self.list.len; + } + } + } + + /// Inserts a new element into the `LinkedList` before the current one. + /// + /// If the cursor is pointing at the "ghost" non-element then the new element is + /// inserted at the end of the `LinkedList`. + #[unstable(feature = "linked_list_cursors", issue = "58533")] + pub fn insert_before(&mut self, item: T) { + unsafe { + let spliced_node = Box::leak(Box::new_in(Node::new(item), &self.list.alloc)).into(); + let node_prev = match self.current { + None => self.list.tail, + Some(node) => node.as_ref().prev, + }; + self.list.splice_nodes(node_prev, self.current, spliced_node, spliced_node, 1); + self.index += 1; + } + } + + /// Removes the current element from the `LinkedList`. + /// + /// The element that was removed is returned, and the cursor is + /// moved to point to the next element in the `LinkedList`. + /// + /// If the cursor is currently pointing to the "ghost" non-element then no element + /// is removed and `None` is returned. + #[unstable(feature = "linked_list_cursors", issue = "58533")] + pub fn remove_current(&mut self) -> Option { + let unlinked_node = self.current?; + unsafe { + self.current = unlinked_node.as_ref().next; + self.list.unlink_node(unlinked_node); + let unlinked_node = Box::from_raw(unlinked_node.as_ptr()); + Some(unlinked_node.element) + } + } + + /// Removes the current element from the `LinkedList` without deallocating the list node. + /// + /// The node that was removed is returned as a new `LinkedList` containing only this node. + /// The cursor is moved to point to the next element in the current `LinkedList`. + /// + /// If the cursor is currently pointing to the "ghost" non-element then no element + /// is removed and `None` is returned. + #[unstable(feature = "linked_list_cursors", issue = "58533")] + pub fn remove_current_as_list(&mut self) -> Option> + where + A: Clone, + { + let mut unlinked_node = self.current?; + unsafe { + self.current = unlinked_node.as_ref().next; + self.list.unlink_node(unlinked_node); + + unlinked_node.as_mut().prev = None; + unlinked_node.as_mut().next = None; + Some(LinkedList { + head: Some(unlinked_node), + tail: Some(unlinked_node), + len: 1, + alloc: self.list.alloc.clone(), + marker: PhantomData, + }) + } + } /// Splits the list into two after the current element. This will return a /// new list consisting of everything after the cursor, with the original @@ -1544,7 +1621,10 @@ pub fn splice_before(&mut self, list: LinkedList) { /// If the cursor is pointing at the "ghost" non-element then the entire contents /// of the `LinkedList` are moved. #[unstable(feature = "linked_list_cursors", issue = "58533")] - pub fn split_after(&mut self) -> LinkedList { + pub fn split_after(&mut self) -> LinkedList + where + A: Clone, + { let split_off_idx = if self.index == self.list.len { 0 } else { self.index + 1 }; if self.index == self.list.len { // The "ghost" non-element's index has changed to 0. @@ -1560,7 +1640,10 @@ pub fn split_after(&mut self) -> LinkedList { /// If the cursor is pointing at the "ghost" non-element then the entire contents /// of the `LinkedList` are moved. #[unstable(feature = "linked_list_cursors", issue = "58533")] - pub fn split_before(&mut self) -> LinkedList { + pub fn split_before(&mut self) -> LinkedList + where + A: Clone, + { let split_off_idx = self.index; self.index = 0; unsafe { self.list.split_off_before_node(self.current, split_off_idx) } @@ -1702,11 +1785,15 @@ pub fn back_mut(&mut self) -> Option<&mut 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 +pub struct DrainFilter< + 'a, + T: 'a, + F: 'a, + #[unstable(feature = "allocator_api", issue = "32838")] A: Allocator = Global, +> where F: FnMut(&mut T) -> bool, { - list: &'a mut LinkedList, + list: &'a mut LinkedList, it: Option>>, pred: F, idx: usize, @@ -1714,7 +1801,7 @@ pub struct DrainFilter<'a, T: 'a, F: 'a> } #[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, { @@ -1743,16 +1830,16 @@ fn size_hint(&self) -> (usize, Option) { } #[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) { - struct DropGuard<'r, 'a, T, F>(&'r mut DrainFilter<'a, T, F>) + struct DropGuard<'r, 'a, T, F, A: Allocator>(&'r mut DrainFilter<'a, T, F, A>) where F: FnMut(&mut T) -> bool; - impl<'r, 'a, T, F> Drop for DropGuard<'r, 'a, T, F> + impl<'r, 'a, T, F, A: Allocator> Drop for DropGuard<'r, 'a, T, F, A> where F: FnMut(&mut T) -> bool, { @@ -1780,7 +1867,7 @@ fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { } #[stable(feature = "rust1", since = "1.0.0")] -impl Iterator for IntoIter { +impl Iterator for IntoIter { type Item = T; #[inline] @@ -1795,7 +1882,7 @@ fn size_hint(&self) -> (usize, Option) { } #[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() @@ -1803,10 +1890,10 @@ fn next_back(&mut self) -> Option { } #[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 { @@ -1818,19 +1905,19 @@ fn from_iter>(iter: I) -> Self { } #[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: Allocator> IntoIterator for &'a LinkedList { type Item = &'a T; type IntoIter = Iter<'a, T>; @@ -1840,7 +1927,7 @@ fn into_iter(self) -> Iter<'a, T> { } #[stable(feature = "rust1", since = "1.0.0")] -impl<'a, T> IntoIterator for &'a mut LinkedList { +impl<'a, T, A: Allocator> IntoIterator for &'a mut LinkedList { type Item = &'a mut T; type IntoIter = IterMut<'a, T>; @@ -1850,7 +1937,7 @@ fn into_iter(self) -> IterMut<'a, T> { } #[stable(feature = "rust1", since = "1.0.0")] -impl Extend for LinkedList { +impl Extend for LinkedList { fn extend>(&mut self, iter: I) { >::spec_extend(self, iter); } @@ -1861,7 +1948,7 @@ fn extend_one(&mut self, elem: T) { } } -impl SpecExtend for LinkedList { +impl SpecExtend for LinkedList { default fn spec_extend(&mut self, iter: I) { iter.into_iter().for_each(move |elt| self.push_back(elt)); } @@ -1874,7 +1961,7 @@ fn spec_extend(&mut self, ref mut other: LinkedList) { } #[stable(feature = "extend_ref", since = "1.2.0")] -impl<'a, T: 'a + Copy> Extend<&'a T> for LinkedList { +impl<'a, T: 'a + Copy, A: Allocator> Extend<&'a T> for LinkedList { fn extend>(&mut self, iter: I) { self.extend(iter.into_iter().cloned()); } @@ -1886,7 +1973,7 @@ fn extend_one(&mut self, &elem: &'a T) { } #[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) } @@ -1897,17 +1984,17 @@ fn ne(&self, other: &Self) -> bool { } #[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) @@ -1915,9 +2002,11 @@ fn cmp(&self, other: &Self) -> Ordering { } #[stable(feature = "rust1", since = "1.0.0")] -impl Clone for LinkedList { +impl Clone for LinkedList { fn clone(&self) -> Self { - self.iter().cloned().collect() + let mut list = Self::new_in(self.alloc.clone()); + list.extend(self.iter().cloned()); + list } fn clone_from(&mut self, other: &Self) { @@ -1935,14 +2024,14 @@ fn clone_from(&mut self, other: &Self) { } #[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) { state.write_length_prefix(self.len()); for elt in self { @@ -1982,10 +2071,10 @@ fn c<'a>(x: IntoIter<&'static str>) -> IntoIter<&'a str> { } #[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> {} @@ -2000,13 +2089,13 @@ unsafe impl Send for IterMut<'_, T> {} unsafe impl Sync for IterMut<'_, T> {} #[unstable(feature = "linked_list_cursors", issue = "58533")] -unsafe impl Send for Cursor<'_, T> {} +unsafe impl Send for Cursor<'_, T, A> {} #[unstable(feature = "linked_list_cursors", issue = "58533")] -unsafe impl Sync for Cursor<'_, T> {} +unsafe impl Sync for Cursor<'_, T, A> {} #[unstable(feature = "linked_list_cursors", issue = "58533")] -unsafe impl Send for CursorMut<'_, T> {} +unsafe impl Send for CursorMut<'_, T, A> {} #[unstable(feature = "linked_list_cursors", issue = "58533")] -unsafe impl Sync for CursorMut<'_, T> {} +unsafe impl Sync for CursorMut<'_, T, A> {} diff --git a/tests/debuginfo/pretty-std.rs b/tests/debuginfo/pretty-std.rs index 7bb2810c2b2..c7df7dc3cb3 100644 --- a/tests/debuginfo/pretty-std.rs +++ b/tests/debuginfo/pretty-std.rs @@ -130,8 +130,8 @@ // cdb-check: [+0x000] __0 : "IAMA optional string!" [Type: alloc::string::String] // cdb-command: dx linkedlist -// cdb-check:linkedlist : { len=0x2 } [Type: alloc::collections::linked_list::LinkedList] -// cdb-check: [] [Type: alloc::collections::linked_list::LinkedList] +// cdb-check:linkedlist : { len=0x2 } [Type: alloc::collections::linked_list::LinkedList] +// cdb-check: [] [Type: alloc::collections::linked_list::LinkedList] // cdb-check: [0x0] : 128 [Type: int] // cdb-check: [0x1] : 42 [Type: int]