From c2de8fe29443d8c9c70da66dee2c99d4c8d04930 Mon Sep 17 00:00:00 2001 From: "Chai T. Rex" Date: Sun, 18 Oct 2020 15:45:09 -0400 Subject: Stabilize or_insert_with_key --- library/alloc/src/collections/btree/map/entry.rs | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) (limited to 'library/alloc/src') diff --git a/library/alloc/src/collections/btree/map/entry.rs b/library/alloc/src/collections/btree/map/entry.rs index 73a0ca21f67..3ff648fe24c 100644 --- a/library/alloc/src/collections/btree/map/entry.rs +++ b/library/alloc/src/collections/btree/map/entry.rs @@ -116,7 +116,6 @@ impl<'a, K: Ord, V> Entry<'a, K, V> { } } - #[unstable(feature = "or_insert_with_key", issue = "71024")] /// Ensures a value is in the entry by inserting, if empty, the result of the default function, /// which takes the key as its argument, and returns a mutable reference to the value in the /// entry. @@ -124,7 +123,6 @@ impl<'a, K: Ord, V> Entry<'a, K, V> { /// # Examples /// /// ``` - /// #![feature(or_insert_with_key)] /// use std::collections::BTreeMap; /// /// let mut map: BTreeMap<&str, usize> = BTreeMap::new(); @@ -134,6 +132,7 @@ impl<'a, K: Ord, V> Entry<'a, K, V> { /// assert_eq!(map["poneyland"], 9); /// ``` #[inline] + #[stable(feature = "or_insert_with_key", since = "1.49.0")] pub fn or_insert_with_key V>(self, default: F) -> &'a mut V { match self { Occupied(entry) => entry.into_mut(), -- cgit 1.4.1-3-g733a5 From 161300d41e7910b50db55b4025c66bc79c716ccd Mon Sep 17 00:00:00 2001 From: Spyros Roum Date: Fri, 13 Nov 2020 18:54:23 +0200 Subject: stabilize deque_range --- library/alloc/src/collections/vec_deque/mod.rs | 8 ++------ library/alloc/tests/lib.rs | 1 - 2 files changed, 2 insertions(+), 7 deletions(-) (limited to 'library/alloc/src') diff --git a/library/alloc/src/collections/vec_deque/mod.rs b/library/alloc/src/collections/vec_deque/mod.rs index 1c183858e7a..15474606054 100644 --- a/library/alloc/src/collections/vec_deque/mod.rs +++ b/library/alloc/src/collections/vec_deque/mod.rs @@ -1080,8 +1080,6 @@ impl VecDeque { /// # Examples /// /// ``` - /// #![feature(deque_range)] - /// /// use std::collections::VecDeque; /// /// let v: VecDeque<_> = vec![1, 2, 3].into_iter().collect(); @@ -1093,7 +1091,7 @@ impl VecDeque { /// assert_eq!(all.len(), 3); /// ``` #[inline] - #[unstable(feature = "deque_range", issue = "74217")] + #[stable(feature = "deque_range", since = "1.50.0")] pub fn range(&self, range: R) -> Iter<'_, T> where R: RangeBounds, @@ -1117,8 +1115,6 @@ impl VecDeque { /// # Examples /// /// ``` - /// #![feature(deque_range)] - /// /// use std::collections::VecDeque; /// /// let mut v: VecDeque<_> = vec![1, 2, 3].into_iter().collect(); @@ -1134,7 +1130,7 @@ impl VecDeque { /// assert_eq!(v, vec![2, 4, 12]); /// ``` #[inline] - #[unstable(feature = "deque_range", issue = "74217")] + #[stable(feature = "deque_range", since = "1.50.0")] pub fn range_mut(&mut self, range: R) -> IterMut<'_, T> where R: RangeBounds, diff --git a/library/alloc/tests/lib.rs b/library/alloc/tests/lib.rs index b7cc03f8eb9..b56437bd188 100644 --- a/library/alloc/tests/lib.rs +++ b/library/alloc/tests/lib.rs @@ -16,7 +16,6 @@ #![feature(slice_ptr_get)] #![feature(split_inclusive)] #![feature(binary_heap_retain)] -#![feature(deque_range)] #![feature(inplace_iteration)] #![feature(iter_map_while)] #![feature(int_bits_const)] -- cgit 1.4.1-3-g733a5 From 866ef87d3f1f368687095b263829ef1182b2727a Mon Sep 17 00:00:00 2001 From: "Chai T. Rex" Date: Tue, 1 Dec 2020 01:06:40 -0500 Subject: Update rustc version that or_insert_with_key landed --- library/alloc/src/collections/btree/map/entry.rs | 2 +- library/std/src/collections/hash/map.rs | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) (limited to 'library/alloc/src') diff --git a/library/alloc/src/collections/btree/map/entry.rs b/library/alloc/src/collections/btree/map/entry.rs index 3ff648fe24c..77c285ef595 100644 --- a/library/alloc/src/collections/btree/map/entry.rs +++ b/library/alloc/src/collections/btree/map/entry.rs @@ -132,7 +132,7 @@ impl<'a, K: Ord, V> Entry<'a, K, V> { /// assert_eq!(map["poneyland"], 9); /// ``` #[inline] - #[stable(feature = "or_insert_with_key", since = "1.49.0")] + #[stable(feature = "or_insert_with_key", since = "1.50.0")] pub fn or_insert_with_key V>(self, default: F) -> &'a mut V { match self { Occupied(entry) => entry.into_mut(), diff --git a/library/std/src/collections/hash/map.rs b/library/std/src/collections/hash/map.rs index 3d130c1628e..323ea5d8244 100644 --- a/library/std/src/collections/hash/map.rs +++ b/library/std/src/collections/hash/map.rs @@ -2238,7 +2238,7 @@ impl<'a, K, V> Entry<'a, K, V> { /// assert_eq!(map["poneyland"], 9); /// ``` #[inline] - #[stable(feature = "or_insert_with_key", since = "1.49.0")] + #[stable(feature = "or_insert_with_key", since = "1.50.0")] pub fn or_insert_with_key V>(self, default: F) -> &'a mut V { match self { Occupied(entry) => entry.into_mut(), -- cgit 1.4.1-3-g733a5 From f1b930d57cd9014a4e97c2b0ac366c8fa51f38c7 Mon Sep 17 00:00:00 2001 From: "Chai T. Rex" Date: Mon, 7 Dec 2020 21:36:01 -0500 Subject: Improved documentation for HashMap/BTreeMap Entry's .or_insert_with_key method --- library/alloc/src/collections/btree/map/entry.rs | 9 ++++++--- library/std/src/collections/hash/map.rs | 9 ++++++--- 2 files changed, 12 insertions(+), 6 deletions(-) (limited to 'library/alloc/src') diff --git a/library/alloc/src/collections/btree/map/entry.rs b/library/alloc/src/collections/btree/map/entry.rs index 77c285ef595..9dd68e27914 100644 --- a/library/alloc/src/collections/btree/map/entry.rs +++ b/library/alloc/src/collections/btree/map/entry.rs @@ -116,9 +116,12 @@ impl<'a, K: Ord, V> Entry<'a, K, V> { } } - /// Ensures a value is in the entry by inserting, if empty, the result of the default function, - /// which takes the key as its argument, and returns a mutable reference to the value in the - /// entry. + /// Ensures a value is in the entry by inserting, if empty, the result of the default function. + /// This method allows for generating key-derived values for insertion by providing the default + /// function a reference to the key that was moved during the `.entry(key)` method call.
+ /// + /// The reference to the moved key is provided so that cloning or copying the key is + /// unnecessary, unlike with `.or_insert_with(|| ... )`. /// /// # Examples /// diff --git a/library/std/src/collections/hash/map.rs b/library/std/src/collections/hash/map.rs index 323ea5d8244..ae48d7fe7ee 100644 --- a/library/std/src/collections/hash/map.rs +++ b/library/std/src/collections/hash/map.rs @@ -2222,9 +2222,12 @@ impl<'a, K, V> Entry<'a, K, V> { } } - /// Ensures a value is in the entry by inserting, if empty, the result of the default function, - /// which takes the key as its argument, and returns a mutable reference to the value in the - /// entry. + /// Ensures a value is in the entry by inserting, if empty, the result of the default function. + /// This method allows for generating key-derived values for insertion by providing the default + /// function a reference to the key that was moved during the `.entry(key)` method call. + /// + /// The reference to the moved key is provided so that cloning or copying the key is + /// unnecessary, unlike with `.or_insert_with(|| ... )`. /// /// # Examples /// -- cgit 1.4.1-3-g733a5 From f115be93abd2634f3d71d91bf1341e9860a87056 Mon Sep 17 00:00:00 2001 From: "Chai T. Rex" Date: Mon, 7 Dec 2020 21:59:52 -0500 Subject: Removed spurious linebreak from new documentation --- library/alloc/src/collections/btree/map/entry.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'library/alloc/src') diff --git a/library/alloc/src/collections/btree/map/entry.rs b/library/alloc/src/collections/btree/map/entry.rs index 9dd68e27914..6626124a34e 100644 --- a/library/alloc/src/collections/btree/map/entry.rs +++ b/library/alloc/src/collections/btree/map/entry.rs @@ -118,7 +118,7 @@ impl<'a, K: Ord, V> Entry<'a, K, V> { /// Ensures a value is in the entry by inserting, if empty, the result of the default function. /// This method allows for generating key-derived values for insertion by providing the default - /// function a reference to the key that was moved during the `.entry(key)` method call.
+ /// function a reference to the key that was moved during the `.entry(key)` method call. /// /// The reference to the moved key is provided so that cloning or copying the key is /// unnecessary, unlike with `.or_insert_with(|| ... )`. -- cgit 1.4.1-3-g733a5 From 76bd14548910a13049b59b14e09a80cfd3a29b77 Mon Sep 17 00:00:00 2001 From: Mike Hommey Date: Wed, 18 Nov 2020 12:57:40 +0900 Subject: Do not inline finish_grow We also change the specialization of `SpecFromIterNested::from_iter` for `TrustedLen` to use `Vec::with_capacity` when the iterator has a proper size hint, instead of `Vec::new`, avoiding calls to `grow_*` and thus `finish_grow` in some fully inlinable cases, which would regress with this change. Fixes #78471. --- library/alloc/src/raw_vec.rs | 1 + library/alloc/src/vec.rs | 5 ++++- 2 files changed, 5 insertions(+), 1 deletion(-) (limited to 'library/alloc/src') diff --git a/library/alloc/src/raw_vec.rs b/library/alloc/src/raw_vec.rs index 522c5bcf5af..fdf6884794a 100644 --- a/library/alloc/src/raw_vec.rs +++ b/library/alloc/src/raw_vec.rs @@ -471,6 +471,7 @@ impl RawVec { // above `RawVec::grow_amortized` for details. (The `A` parameter isn't // significant, because the number of different `A` types seen in practice is // much smaller than the number of `T` types.) +#[inline(never)] fn finish_grow( new_layout: Result, current_memory: Option<(NonNull, Layout)>, diff --git a/library/alloc/src/vec.rs b/library/alloc/src/vec.rs index 2c8bc3d53ef..62398b82607 100644 --- a/library/alloc/src/vec.rs +++ b/library/alloc/src/vec.rs @@ -2103,7 +2103,10 @@ where I: TrustedLen, { fn from_iter(iterator: I) -> Self { - let mut vector = Vec::new(); + let mut vector = match iterator.size_hint() { + (_, Some(upper)) => Vec::with_capacity(upper), + _ => Vec::new(), + }; // must delegate to spec_extend() since extend() itself delegates // to spec_from for empty Vecs vector.spec_extend(iterator); -- cgit 1.4.1-3-g733a5 From 4fb9f1d7846f64beeec749db5933a24c05456ff2 Mon Sep 17 00:00:00 2001 From: Bastian Kauschke Date: Tue, 8 Dec 2020 10:34:31 +0100 Subject: fix unsoundness in `make_contiguous` --- library/alloc/src/collections/vec_deque/mod.rs | 18 +++++++++++++----- library/alloc/src/collections/vec_deque/tests.rs | 14 ++++++++++++++ 2 files changed, 27 insertions(+), 5 deletions(-) (limited to 'library/alloc/src') diff --git a/library/alloc/src/collections/vec_deque/mod.rs b/library/alloc/src/collections/vec_deque/mod.rs index 85c809e0d18..57807bc5453 100644 --- a/library/alloc/src/collections/vec_deque/mod.rs +++ b/library/alloc/src/collections/vec_deque/mod.rs @@ -1469,6 +1469,8 @@ impl VecDeque { #[inline] fn is_contiguous(&self) -> bool { + // FIXME: Should we consider `head == 0` to mean + // that `self` is contiguous? self.tail <= self.head } @@ -2198,7 +2200,7 @@ impl VecDeque { if self.is_contiguous() { let tail = self.tail; let head = self.head; - return unsafe { &mut self.buffer_as_mut_slice()[tail..head] }; + return unsafe { RingSlices::ring_slices(self.buffer_as_mut_slice(), head, tail).0 }; } let buf = self.buf.ptr(); @@ -2224,7 +2226,13 @@ impl VecDeque { self.tail = 0; self.head = len; } - } else if free >= self.head { + } else if free > self.head { + // FIXME: We currently do not consider ....ABCDEFGH + // to be contiguous because `head` would be `0` in this + // case. While we probably want to change this it + // isn't trivial as a few places expect `is_contiguous` + // to mean that we can just slice using `buf[tail..head]`. + // there is enough free space to copy the head in one go, // this means that we first shift the tail forwards, and then // copy the head to the correct position. @@ -2238,7 +2246,7 @@ impl VecDeque { // ...ABCDEFGH. self.tail = self.head; - self.head = self.tail + len; + self.head = self.wrap_add(self.tail, len); } } else { // free is smaller than both head and tail, @@ -2278,7 +2286,7 @@ impl VecDeque { let tail = self.tail; let head = self.head; - unsafe { &mut self.buffer_as_mut_slice()[tail..head] } + unsafe { RingSlices::ring_slices(self.buffer_as_mut_slice(), head, tail).0 } } /// Rotates the double-ended queue `mid` places to the left. @@ -2839,7 +2847,7 @@ impl From> for Vec { let len = other.len(); let cap = other.cap(); - if other.head != 0 { + if other.tail != 0 { ptr::copy(buf.add(other.tail), buf, len); } Vec::from_raw_parts(buf, len, cap) diff --git a/library/alloc/src/collections/vec_deque/tests.rs b/library/alloc/src/collections/vec_deque/tests.rs index d74f91c752c..21f52af056b 100644 --- a/library/alloc/src/collections/vec_deque/tests.rs +++ b/library/alloc/src/collections/vec_deque/tests.rs @@ -210,6 +210,20 @@ fn make_contiguous_small_free() { ); } +#[test] +fn make_contiguous_head_to_end() { + let mut dq = VecDeque::with_capacity(3); + dq.push_front('B'); + dq.push_front('A'); + dq.push_back('C'); + dq.make_contiguous(); + let expected_tail = 0; + let expected_head = 3; + assert_eq!(expected_tail, dq.tail); + assert_eq!(expected_head, dq.head); + assert_eq!((&['A', 'B', 'C'] as &[_], &[] as &[_]), dq.as_slices()); +} + #[test] fn test_remove() { // This test checks that every single combination of tail position, length, and -- cgit 1.4.1-3-g733a5 From 5cab04ea92355ed3a71caf96ac7ffcb638cd37cb Mon Sep 17 00:00:00 2001 From: Mara Bos Date: Tue, 8 Dec 2020 20:52:57 +0100 Subject: Remove deprecated linked_list_extras methods. --- library/alloc/src/collections/linked_list.rs | 62 ---------------------------- 1 file changed, 62 deletions(-) (limited to 'library/alloc/src') diff --git a/library/alloc/src/collections/linked_list.rs b/library/alloc/src/collections/linked_list.rs index 412c65681e6..4707f129401 100644 --- a/library/alloc/src/collections/linked_list.rs +++ b/library/alloc/src/collections/linked_list.rs @@ -1099,68 +1099,6 @@ impl ExactSizeIterator for IterMut<'_, T> {} #[stable(feature = "fused", since = "1.26.0")] impl FusedIterator for IterMut<'_, T> {} -impl IterMut<'_, T> { - /// Inserts the given element just after the element most recently returned by `.next()`. - /// The inserted element does not appear in the iteration. - /// - /// This method will be removed soon. - #[inline] - #[unstable( - feature = "linked_list_extras", - reason = "this is probably better handled by a cursor type -- we'll see", - issue = "27794" - )] - #[rustc_deprecated( - reason = "Deprecated in favor of CursorMut methods. This method will be removed soon.", - since = "1.47.0" - )] - pub fn insert_next(&mut self, element: T) { - match self.head { - // `push_back` is okay with aliasing `element` references - None => self.list.push_back(element), - Some(head) => unsafe { - let prev = match head.as_ref().prev { - // `push_front` is okay with aliasing nodes - None => return self.list.push_front(element), - Some(prev) => prev, - }; - - let node = Some( - Box::leak(box Node { next: Some(head), prev: Some(prev), element }).into(), - ); - - // Not creating references to entire nodes to not invalidate the - // reference to `element` we handed to the user. - (*prev.as_ptr()).next = node; - (*head.as_ptr()).prev = node; - - self.list.len += 1; - }, - } - } - - /// Provides a reference to the next element, without changing the iterator. - /// - /// This method will be removed soon. - #[inline] - #[unstable( - feature = "linked_list_extras", - reason = "this is probably better handled by a cursor type -- we'll see", - issue = "27794" - )] - #[rustc_deprecated( - reason = "Deprecated in favor of CursorMut methods. This method will be removed soon.", - since = "1.47.0" - )] - pub fn peek_next(&mut self) -> Option<&mut T> { - if self.len == 0 { - None - } else { - unsafe { self.head.as_mut().map(|node| &mut node.as_mut().element) } - } - } -} - /// A cursor over a `LinkedList`. /// /// A `Cursor` is like an iterator, except that it can freely seek back-and-forth. -- cgit 1.4.1-3-g733a5 From 33ae62c3d7c5a619595e9faced2450dae27ad702 Mon Sep 17 00:00:00 2001 From: Corey Farwell Date: Wed, 9 Dec 2020 13:17:54 -0500 Subject: Clarify that String::split_at takes a byte index. --- library/alloc/src/string.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'library/alloc/src') diff --git a/library/alloc/src/string.rs b/library/alloc/src/string.rs index ce216e5336e..27b32b69502 100644 --- a/library/alloc/src/string.rs +++ b/library/alloc/src/string.rs @@ -1413,7 +1413,7 @@ impl String { self.len() == 0 } - /// Splits the string into two at the given index. + /// Splits the string into two at the given byte index. /// /// Returns a newly allocated `String`. `self` contains bytes `[0, at)`, and /// the returned `String` contains bytes `[at, len)`. `at` must be on the -- cgit 1.4.1-3-g733a5 From a891f6edfeb4d7b061a215ba160fca0e4804ffd2 Mon Sep 17 00:00:00 2001 From: Clément Renault Date: Thu, 10 Dec 2020 10:16:29 +0100 Subject: Introduce the GroupBy and GroupByMut Iterators --- library/alloc/src/lib.rs | 1 + library/alloc/src/slice.rs | 2 + library/alloc/tests/lib.rs | 1 + library/alloc/tests/slice.rs | 27 +++++++ library/core/src/slice/iter.rs | 180 +++++++++++++++++++++++++++++++++++++++++ library/core/src/slice/mod.rs | 68 ++++++++++++++++ library/core/tests/lib.rs | 1 + 7 files changed, 280 insertions(+) (limited to 'library/alloc/src') diff --git a/library/alloc/src/lib.rs b/library/alloc/src/lib.rs index 3ac34c9ae28..34102d9c403 100644 --- a/library/alloc/src/lib.rs +++ b/library/alloc/src/lib.rs @@ -140,6 +140,7 @@ #![feature(try_trait)] #![feature(type_alias_impl_trait)] #![feature(associated_type_bounds)] +#![feature(slice_group_by)] // Allow testing this library #[cfg(test)] diff --git a/library/alloc/src/slice.rs b/library/alloc/src/slice.rs index 064700fc72c..bfa317ffd73 100644 --- a/library/alloc/src/slice.rs +++ b/library/alloc/src/slice.rs @@ -118,6 +118,8 @@ pub use core::slice::{RChunks, RChunksExact, RChunksExactMut, RChunksMut}; pub use core::slice::{RSplit, RSplitMut}; #[stable(feature = "rust1", since = "1.0.0")] pub use core::slice::{RSplitN, RSplitNMut, SplitN, SplitNMut}; +#[unstable(feature = "slice_group_by", issue = "0")] +pub use core::slice::{GroupBy, GroupByMut}; //////////////////////////////////////////////////////////////////////////////// // Basic slice extension methods diff --git a/library/alloc/tests/lib.rs b/library/alloc/tests/lib.rs index b7cc03f8eb9..268153242c7 100644 --- a/library/alloc/tests/lib.rs +++ b/library/alloc/tests/lib.rs @@ -21,6 +21,7 @@ #![feature(iter_map_while)] #![feature(int_bits_const)] #![feature(vecdeque_binary_search)] +#![feature(slice_group_by)] use std::collections::hash_map::DefaultHasher; use std::hash::{Hash, Hasher}; diff --git a/library/alloc/tests/slice.rs b/library/alloc/tests/slice.rs index a4f0fb415fb..e2fdb5a6b5a 100644 --- a/library/alloc/tests/slice.rs +++ b/library/alloc/tests/slice.rs @@ -1898,3 +1898,30 @@ fn subslice_patterns() { m!(&mut v, [..] => ()); m!(&mut v, [x, .., y] => c!((x, y), (&mut N, &mut N), (&mut N(0), &mut N(4)))); } + +#[test] +fn test_group_by() { + let slice = &[1, 1, 1, 3, 3, 2, 2, 2]; + + let mut iter = slice.group_by(|a, b| a == b); + + assert_eq!(iter.next(), Some(&[1, 1, 1][..])); + + assert_eq!(iter.remaining(), &[3, 3, 2, 2, 2]); + + assert_eq!(iter.next(), Some(&[3, 3][..])); + assert_eq!(iter.next(), Some(&[2, 2, 2][..])); + assert_eq!(iter.next(), None); +} + +#[test] +fn test_group_by_rev() { + let slice = &[1, 1, 1, 3, 3, 2, 2, 2]; + + let mut iter = slice.group_by(|a, b| a == b); + + assert_eq!(iter.next_back(), Some(&[2, 2, 2][..])); + assert_eq!(iter.next_back(), Some(&[3, 3][..])); + assert_eq!(iter.next_back(), Some(&[1, 1, 1][..])); + assert_eq!(iter.next_back(), None); +} diff --git a/library/core/src/slice/iter.rs b/library/core/src/slice/iter.rs index e373936a6c7..917997f902a 100644 --- a/library/core/src/slice/iter.rs +++ b/library/core/src/slice/iter.rs @@ -2967,3 +2967,183 @@ unsafe impl<'a, T> TrustedRandomAccess for IterMut<'a, T> { false } } + +macro_rules! group_by { + (struct $name:ident, $elem:ty, $mkslice:ident) => { + #[unstable(feature = "slice_group_by", issue = "0")] + impl<'a, T: 'a, P> $name<'a, T, P> { + #[inline] + fn is_empty(&self) -> bool { + self.ptr == self.end + } + + #[inline] + fn remaining_len(&self) -> usize { + unsafe { self.end.offset_from(self.ptr) as usize } + } + } + + #[unstable(feature = "slice_group_by", issue = "0")] + impl<'a, T: 'a, P> Iterator for $name<'a, T, P> + where P: FnMut(&T, &T) -> bool, + { + type Item = $elem; + + fn next(&mut self) -> Option { + // we use an unsafe block to avoid bounds checking here. + // this is safe because the only thing we do here is to get + // two elements at `ptr` and `ptr + 1`, bounds checking is done by hand. + unsafe { + if self.is_empty() { return None } + + let mut i = 0; + let mut ptr = self.ptr; + + // we need to get *two* contiguous elements so we check that: + // - the first element is at the `end - 1` position because + // - the second one will be read from `ptr + 1` that must + // be lower or equal to `end` + while ptr != self.end.sub(1) { + let a = &*ptr; + ptr = ptr.add(1); + let b = &*ptr; + + i += 1; + + if !(self.predicate)(a, b) { + let slice = $mkslice(self.ptr, i); + self.ptr = ptr; + return Some(slice) + } + } + + // `i` is either `0` or the slice `length - 1` because either: + // - we have not entered the loop and so `i` is equal to `0` + // the slice length is necessarily `1` because we ensure it is not empty + // - we have entered the loop and we have not early returned + // so `i` is equal to the slice `length - 1` + let slice = $mkslice(self.ptr, i + 1); + self.ptr = self.end; + Some(slice) + } + } + + fn size_hint(&self) -> (usize, Option) { + if self.is_empty() { return (0, Some(0)) } + let len = self.remaining_len(); + (1, Some(len)) + } + + fn last(mut self) -> Option { + self.next_back() + } + } + + #[unstable(feature = "slice_group_by", issue = "0")] + impl<'a, T: 'a, P> DoubleEndedIterator for $name<'a, T, P> + where P: FnMut(&T, &T) -> bool, + { + fn next_back(&mut self) -> Option { + // during the loop we retrieve two elements at `ptr` and `ptr - 1`. + unsafe { + if self.is_empty() { return None } + + let mut i = 0; + // we ensure that the first element that will be read + // is not under `end` because `end` is out of bound. + let mut ptr = self.end.sub(1); + + while ptr != self.ptr { + // we first get `a` that is at the left of `ptr` + // then `b` that is under the `ptr` position. + let a = &*ptr.sub(1); + let b = &*ptr; + + i += 1; + + if !(self.predicate)(a, b) { + // the slice to return starts at the `ptr` position + // and `i` is the length of it. + let slice = $mkslice(ptr, i); + + // because `end` is always an invalid bound + // we use `ptr` as `end` for the future call to `next`. + self.end = ptr; + return Some(slice) + } + + ptr = ptr.sub(1); + } + + let slice = $mkslice(self.ptr, i + 1); + self.ptr = self.end; + Some(slice) + } + } + } + + #[unstable(feature = "slice_group_by", issue = "0")] + impl<'a, T: 'a, P> FusedIterator for $name<'a, T, P> + where P: FnMut(&T, &T) -> bool, + { } + } +} + +/// An iterator over slice in (non-overlapping) chunks separated by a predicate. +/// +/// This struct is created by the [`group_by`] method on [slices]. +/// +/// [`group_by`]: ../../std/primitive.slice.html#method.group_by +/// [slices]: ../../std/primitive.slice.html +#[unstable(feature = "slice_group_by", issue = "0")] +#[derive(Debug)] // FIXME implement Debug to be more user friendly +pub struct GroupBy<'a, T: 'a, P> { + ptr: *const T, + end: *const T, + predicate: P, + _phantom: marker::PhantomData<&'a T>, +} + +#[unstable(feature = "slice_group_by", issue = "0")] +impl<'a, T: 'a, P> GroupBy<'a, T, P> +where P: FnMut(&T, &T) -> bool, +{ + /// Returns the remainder of the original slice that is going to be + /// returned by the iterator. + pub fn remaining(&self) -> &[T] { + let len = self.remaining_len(); + unsafe { from_raw_parts(self.ptr, len) } + } +} + +group_by!{ struct GroupBy, &'a [T], from_raw_parts } + +/// An iterator over slice in (non-overlapping) mutable chunks separated +/// by a predicate. +/// +/// This struct is created by the [`group_by_mut`] method on [slices]. +/// +/// [`group_by_mut`]: ../../std/primitive.slice.html#method.group_by_mut +/// [slices]: ../../std/primitive.slice.html +#[unstable(feature = "slice_group_by", issue = "0")] +#[derive(Debug)] // FIXME implement Debug to be more user friendly +pub struct GroupByMut<'a, T: 'a, P> { + ptr: *mut T, + end: *mut T, + predicate: P, + _phantom: marker::PhantomData<&'a T>, +} + +#[unstable(feature = "slice_group_by", issue = "0")] +impl<'a, T: 'a, P> GroupByMut<'a, T, P> +where P: FnMut(&T, &T) -> bool, +{ + /// Returns the remainder of the original slice that is going to be + /// returned by the iterator. + pub fn into_remaining(self) -> &'a mut [T] { + let len = self.remaining_len(); + unsafe { from_raw_parts_mut(self.ptr, len) } + } +} + +group_by!{ struct GroupByMut, &'a mut [T], from_raw_parts_mut } diff --git a/library/core/src/slice/mod.rs b/library/core/src/slice/mod.rs index 44fe2ca8859..e366baa34c6 100644 --- a/library/core/src/slice/mod.rs +++ b/library/core/src/slice/mod.rs @@ -1207,6 +1207,74 @@ impl [T] { RChunksExactMut::new(self, chunk_size) } + /// Returns an iterator over the slice producing non-overlapping runs + /// of elements using the predicate to separate them. + /// + /// The predicate is called on two elements following themselves, + /// it means the predicate is called on `slice[0]` and `slice[1]` + /// then on `slice[1]` and `slice[2]` and so on. + /// + /// # Examples + /// + /// ``` + /// #![feature(slice_group_by)] + /// + /// let slice = &[1, 1, 1, 3, 3, 2, 2, 2]; + /// + /// let mut iter = slice.group_by(|a, b| a == b); + /// + /// assert_eq!(iter.next(), Some(&[1, 1, 1][..])); + /// assert_eq!(iter.next(), Some(&[3, 3][..])); + /// assert_eq!(iter.next(), Some(&[2, 2, 2][..])); + /// assert_eq!(iter.next(), None); + /// ``` + #[unstable(feature = "slice_group_by", issue = "0")] + #[inline] + pub fn group_by(&self, pred: F) -> GroupBy + where F: FnMut(&T, &T) -> bool + { + GroupBy { + ptr: self.as_ptr(), + end: unsafe { self.as_ptr().add(self.len()) }, + predicate: pred, + _phantom: marker::PhantomData, + } + } + + /// Returns an iterator over the slice producing non-overlapping mutable + /// runs of elements using the predicate to separate them. + /// + /// The predicate is called on two elements following themselves, + /// it means the predicate is called on `slice[0]` and `slice[1]` + /// then on `slice[1]` and `slice[2]` and so on. + /// + /// # Examples + /// + /// ``` + /// #![feature(slice_group_by)] + /// + /// let slice = &mut [1, 1, 1, 3, 3, 2, 2, 2]; + /// + /// let mut iter = slice.group_by_mut(|a, b| a == b); + /// + /// assert_eq!(iter.next(), Some(&mut [1, 1, 1][..])); + /// assert_eq!(iter.next(), Some(&mut [3, 3][..])); + /// assert_eq!(iter.next(), Some(&mut [2, 2, 2][..])); + /// assert_eq!(iter.next(), None); + /// ``` + #[unstable(feature = "slice_group_by", issue = "0")] + #[inline] + pub fn group_by_mut(&mut self, pred: F) -> GroupByMut + where F: FnMut(&T, &T) -> bool + { + GroupByMut { + ptr: self.as_mut_ptr(), + end: unsafe { self.as_mut_ptr().add(self.len()) }, + predicate: pred, + _phantom: marker::PhantomData, + } + } + /// Divides one slice into two at an index. /// /// The first will contain all indices from `[0, mid)` (excluding diff --git a/library/core/tests/lib.rs b/library/core/tests/lib.rs index 106c9fe5da3..1199fa4abbc 100644 --- a/library/core/tests/lib.rs +++ b/library/core/tests/lib.rs @@ -65,6 +65,7 @@ #![feature(nonzero_leading_trailing_zeros)] #![feature(const_option)] #![feature(integer_atomics)] +#![feature(slice_group_by)] #![deny(unsafe_op_in_unsafe_fn)] extern crate test; -- cgit 1.4.1-3-g733a5 From 1b406afe23c17467f43a5c1bd83b4af1d55d08d9 Mon Sep 17 00:00:00 2001 From: Clément Renault Date: Thu, 10 Dec 2020 11:37:40 +0100 Subject: Use none as the issue instead of 0 --- library/alloc/src/slice.rs | 2 +- library/core/src/slice/iter.rs | 18 +++++++++--------- library/core/src/slice/mod.rs | 4 ++-- 3 files changed, 12 insertions(+), 12 deletions(-) (limited to 'library/alloc/src') diff --git a/library/alloc/src/slice.rs b/library/alloc/src/slice.rs index bfa317ffd73..5f92dfe539f 100644 --- a/library/alloc/src/slice.rs +++ b/library/alloc/src/slice.rs @@ -118,7 +118,7 @@ pub use core::slice::{RChunks, RChunksExact, RChunksExactMut, RChunksMut}; pub use core::slice::{RSplit, RSplitMut}; #[stable(feature = "rust1", since = "1.0.0")] pub use core::slice::{RSplitN, RSplitNMut, SplitN, SplitNMut}; -#[unstable(feature = "slice_group_by", issue = "0")] +#[unstable(feature = "slice_group_by", issue = "none")] pub use core::slice::{GroupBy, GroupByMut}; //////////////////////////////////////////////////////////////////////////////// diff --git a/library/core/src/slice/iter.rs b/library/core/src/slice/iter.rs index 90afd00f21d..9053376bdf2 100644 --- a/library/core/src/slice/iter.rs +++ b/library/core/src/slice/iter.rs @@ -2974,21 +2974,21 @@ unsafe impl<'a, T> TrustedRandomAccess for IterMut<'a, T> { /// /// [`group_by`]: ../../std/primitive.slice.html#method.group_by /// [slices]: ../../std/primitive.slice.html -#[unstable(feature = "slice_group_by", issue = "0")] +#[unstable(feature = "slice_group_by", issue = "none")] #[derive(Debug)] // FIXME implement Debug to be more user friendly pub struct GroupBy<'a, T: 'a, P> { slice: &'a [T], predicate: P, } -#[unstable(feature = "slice_group_by", issue = "0")] +#[unstable(feature = "slice_group_by", issue = "none")] impl<'a, T: 'a, P> GroupBy<'a, T, P> { pub(super) fn new(slice: &'a [T], predicate: P) -> Self { GroupBy { slice, predicate } } } -#[unstable(feature = "slice_group_by", issue = "0")] +#[unstable(feature = "slice_group_by", issue = "none")] impl<'a, T: 'a, P> Iterator for GroupBy<'a, T, P> where P: FnMut(&T, &T) -> bool, { @@ -3025,7 +3025,7 @@ where P: FnMut(&T, &T) -> bool, } } -#[unstable(feature = "slice_group_by", issue = "0")] +#[unstable(feature = "slice_group_by", issue = "none")] impl<'a, T: 'a, P> DoubleEndedIterator for GroupBy<'a, T, P> where P: FnMut(&T, &T) -> bool, { @@ -3046,7 +3046,7 @@ where P: FnMut(&T, &T) -> bool, } } -#[unstable(feature = "slice_group_by", issue = "0")] +#[unstable(feature = "slice_group_by", issue = "none")] impl<'a, T: 'a, P> FusedIterator for GroupBy<'a, T, P> where P: FnMut(&T, &T) -> bool, { } @@ -3058,21 +3058,21 @@ where P: FnMut(&T, &T) -> bool, /// /// [`group_by_mut`]: ../../std/primitive.slice.html#method.group_by_mut /// [slices]: ../../std/primitive.slice.html -#[unstable(feature = "slice_group_by", issue = "0")] +#[unstable(feature = "slice_group_by", issue = "none")] #[derive(Debug)] // FIXME implement Debug to be more user friendly pub struct GroupByMut<'a, T: 'a, P> { slice: &'a mut [T], predicate: P, } -#[unstable(feature = "slice_group_by", issue = "0")] +#[unstable(feature = "slice_group_by", issue = "none")] impl<'a, T: 'a, P> GroupByMut<'a, T, P> { pub(super) fn new(slice: &'a mut [T], predicate: P) -> Self { GroupByMut { slice, predicate } } } -#[unstable(feature = "slice_group_by", issue = "0")] +#[unstable(feature = "slice_group_by", issue = "none")] impl<'a, T: 'a, P> Iterator for GroupByMut<'a, T, P> where P: FnMut(&T, &T) -> bool, { @@ -3110,7 +3110,7 @@ where P: FnMut(&T, &T) -> bool, } } -#[unstable(feature = "slice_group_by", issue = "0")] +#[unstable(feature = "slice_group_by", issue = "none")] impl<'a, T: 'a, P> DoubleEndedIterator for GroupByMut<'a, T, P> where P: FnMut(&T, &T) -> bool, { diff --git a/library/core/src/slice/mod.rs b/library/core/src/slice/mod.rs index 2e304cc5d2e..40f480fa85b 100644 --- a/library/core/src/slice/mod.rs +++ b/library/core/src/slice/mod.rs @@ -1228,7 +1228,7 @@ impl [T] { /// assert_eq!(iter.next(), Some(&[2, 2, 2][..])); /// assert_eq!(iter.next(), None); /// ``` - #[unstable(feature = "slice_group_by", issue = "0")] + #[unstable(feature = "slice_group_by", issue = "none")] #[inline] pub fn group_by(&self, pred: F) -> GroupBy where F: FnMut(&T, &T) -> bool @@ -1257,7 +1257,7 @@ impl [T] { /// assert_eq!(iter.next(), Some(&mut [2, 2, 2][..])); /// assert_eq!(iter.next(), None); /// ``` - #[unstable(feature = "slice_group_by", issue = "0")] + #[unstable(feature = "slice_group_by", issue = "none")] #[inline] pub fn group_by_mut(&mut self, pred: F) -> GroupByMut where F: FnMut(&T, &T) -> bool -- cgit 1.4.1-3-g733a5 From 7952ea5a04aa34dc5441a47f7d4d227193c8fdf6 Mon Sep 17 00:00:00 2001 From: Clément Renault Date: Thu, 10 Dec 2020 19:10:09 +0100 Subject: Fix the fmt issues --- library/alloc/src/slice.rs | 4 ++-- library/core/src/slice/iter.rs | 31 ++++++++++++++----------------- library/core/src/slice/mod.rs | 6 ++++-- 3 files changed, 20 insertions(+), 21 deletions(-) (limited to 'library/alloc/src') diff --git a/library/alloc/src/slice.rs b/library/alloc/src/slice.rs index 5f92dfe539f..72da781da3c 100644 --- a/library/alloc/src/slice.rs +++ b/library/alloc/src/slice.rs @@ -110,6 +110,8 @@ pub use core::slice::{Chunks, Windows}; pub use core::slice::{ChunksExact, ChunksExactMut}; #[stable(feature = "rust1", since = "1.0.0")] pub use core::slice::{ChunksMut, Split, SplitMut}; +#[unstable(feature = "slice_group_by", issue = "none")] +pub use core::slice::{GroupBy, GroupByMut}; #[stable(feature = "rust1", since = "1.0.0")] pub use core::slice::{Iter, IterMut}; #[stable(feature = "rchunks", since = "1.31.0")] @@ -118,8 +120,6 @@ pub use core::slice::{RChunks, RChunksExact, RChunksExactMut, RChunksMut}; pub use core::slice::{RSplit, RSplitMut}; #[stable(feature = "rust1", since = "1.0.0")] pub use core::slice::{RSplitN, RSplitNMut, SplitN, SplitNMut}; -#[unstable(feature = "slice_group_by", issue = "none")] -pub use core::slice::{GroupBy, GroupByMut}; //////////////////////////////////////////////////////////////////////////////// // Basic slice extension methods diff --git a/library/core/src/slice/iter.rs b/library/core/src/slice/iter.rs index a10ebacf5fb..423cbd11350 100644 --- a/library/core/src/slice/iter.rs +++ b/library/core/src/slice/iter.rs @@ -2991,7 +2991,8 @@ impl<'a, T: 'a, P> GroupBy<'a, T, P> { #[unstable(feature = "slice_group_by", issue = "none")] impl<'a, T: 'a, P> Iterator for GroupBy<'a, T, P> -where P: FnMut(&T, &T) -> bool, +where + P: FnMut(&T, &T) -> bool, { type Item = &'a [T]; @@ -3013,11 +3014,7 @@ where P: FnMut(&T, &T) -> bool, #[inline] fn size_hint(&self) -> (usize, Option) { - if self.slice.is_empty() { - (0, Some(0)) - } else { - (1, Some(self.slice.len())) - } + if self.slice.is_empty() { (0, Some(0)) } else { (1, Some(self.slice.len())) } } #[inline] @@ -3028,7 +3025,8 @@ where P: FnMut(&T, &T) -> bool, #[unstable(feature = "slice_group_by", issue = "none")] impl<'a, T: 'a, P> DoubleEndedIterator for GroupBy<'a, T, P> -where P: FnMut(&T, &T) -> bool, +where + P: FnMut(&T, &T) -> bool, { #[inline] fn next_back(&mut self) -> Option { @@ -3048,9 +3046,7 @@ where P: FnMut(&T, &T) -> bool, } #[unstable(feature = "slice_group_by", issue = "none")] -impl<'a, T: 'a, P> FusedIterator for GroupBy<'a, T, P> -where P: FnMut(&T, &T) -> bool, -{ } +impl<'a, T: 'a, P> FusedIterator for GroupBy<'a, T, P> where P: FnMut(&T, &T) -> bool {} /// An iterator over slice in (non-overlapping) mutable chunks separated /// by a predicate. @@ -3075,7 +3071,8 @@ impl<'a, T: 'a, P> GroupByMut<'a, T, P> { #[unstable(feature = "slice_group_by", issue = "none")] impl<'a, T: 'a, P> Iterator for GroupByMut<'a, T, P> -where P: FnMut(&T, &T) -> bool, +where + P: FnMut(&T, &T) -> bool, { type Item = &'a mut [T]; @@ -3098,11 +3095,7 @@ where P: FnMut(&T, &T) -> bool, #[inline] fn size_hint(&self) -> (usize, Option) { - if self.slice.is_empty() { - (0, Some(0)) - } else { - (1, Some(self.slice.len())) - } + if self.slice.is_empty() { (0, Some(0)) } else { (1, Some(self.slice.len())) } } #[inline] @@ -3113,7 +3106,8 @@ where P: FnMut(&T, &T) -> bool, #[unstable(feature = "slice_group_by", issue = "none")] impl<'a, T: 'a, P> DoubleEndedIterator for GroupByMut<'a, T, P> -where P: FnMut(&T, &T) -> bool, +where + P: FnMut(&T, &T) -> bool, { #[inline] fn next_back(&mut self) -> Option { @@ -3132,3 +3126,6 @@ where P: FnMut(&T, &T) -> bool, } } } + +#[unstable(feature = "slice_group_by", issue = "none")] +impl<'a, T: 'a, P> FusedIterator for GroupByMut<'a, T, P> where P: FnMut(&T, &T) -> bool {} diff --git a/library/core/src/slice/mod.rs b/library/core/src/slice/mod.rs index 218cd2c25a2..648cf88b7ef 100644 --- a/library/core/src/slice/mod.rs +++ b/library/core/src/slice/mod.rs @@ -1234,7 +1234,8 @@ impl [T] { #[unstable(feature = "slice_group_by", issue = "none")] #[inline] pub fn group_by(&self, pred: F) -> GroupBy<'_, T, F> - where F: FnMut(&T, &T) -> bool + where + F: FnMut(&T, &T) -> bool, { GroupBy::new(self, pred) } @@ -1263,7 +1264,8 @@ impl [T] { #[unstable(feature = "slice_group_by", issue = "none")] #[inline] pub fn group_by_mut(&mut self, pred: F) -> GroupByMut<'_, T, F> - where F: FnMut(&T, &T) -> bool + where + F: FnMut(&T, &T) -> bool, { GroupByMut::new(self, pred) } -- cgit 1.4.1-3-g733a5 From 9cf2516251c5379d3e8429342e8a392df81b9aaa Mon Sep 17 00:00:00 2001 From: William Woodruff Date: Thu, 10 Dec 2020 17:47:28 -0500 Subject: doc(array,vec): add notes about side effects when empty-initializing --- library/alloc/src/macros.rs | 3 +++ library/std/src/primitive_docs.rs | 3 +++ 2 files changed, 6 insertions(+) (limited to 'library/alloc/src') diff --git a/library/alloc/src/macros.rs b/library/alloc/src/macros.rs index a992d768d63..bbff1d3dc4d 100644 --- a/library/alloc/src/macros.rs +++ b/library/alloc/src/macros.rs @@ -29,6 +29,9 @@ /// to the same boxed integer value, not five references pointing to independently /// boxed integers. /// +/// Also, note that `[T; 0]` is a valid initializer. This will initialize (or call) +/// `T` but not populate the vector with it, so be mindful of side effects. +/// /// [`Vec`]: crate::vec::Vec #[cfg(not(test))] #[macro_export] diff --git a/library/std/src/primitive_docs.rs b/library/std/src/primitive_docs.rs index 55171ef2292..b22adbbe3d3 100644 --- a/library/std/src/primitive_docs.rs +++ b/library/std/src/primitive_docs.rs @@ -489,6 +489,9 @@ mod prim_pointer {} /// * A repeat expression `[x; N]`, which produces an array with `N` copies of `x`. /// The type of `x` must be [`Copy`]. /// +/// Note that `[x; 0]` is a valid repeat expression. This will produce an empty array +/// but will also initialize (or call) `x`, which may produce side effects. +/// /// Arrays of *any* size implement the following traits if the element type allows it: /// /// - [`Copy`] -- cgit 1.4.1-3-g733a5 From d986924eb13a103fc79c474eded47a663c91bb7f Mon Sep 17 00:00:00 2001 From: William Woodruff Date: Fri, 11 Dec 2020 10:09:40 -0500 Subject: doc: apply suggestions --- library/alloc/src/macros.rs | 5 +++-- library/std/src/primitive_docs.rs | 5 +++-- 2 files changed, 6 insertions(+), 4 deletions(-) (limited to 'library/alloc/src') diff --git a/library/alloc/src/macros.rs b/library/alloc/src/macros.rs index bbff1d3dc4d..7d4eff6185d 100644 --- a/library/alloc/src/macros.rs +++ b/library/alloc/src/macros.rs @@ -29,8 +29,9 @@ /// to the same boxed integer value, not five references pointing to independently /// boxed integers. /// -/// Also, note that `[T; 0]` is a valid initializer. This will initialize (or call) -/// `T` but not populate the vector with it, so be mindful of side effects. +/// Also, note that `vec![expr; 0]` is allowed, and produces an empty vector. +/// This will still evaluate `expr`, however, and immediately drop the resulting value, so +/// be mindful of side effects. /// /// [`Vec`]: crate::vec::Vec #[cfg(not(test))] diff --git a/library/std/src/primitive_docs.rs b/library/std/src/primitive_docs.rs index b22adbbe3d3..7aca5451ebc 100644 --- a/library/std/src/primitive_docs.rs +++ b/library/std/src/primitive_docs.rs @@ -489,8 +489,9 @@ mod prim_pointer {} /// * A repeat expression `[x; N]`, which produces an array with `N` copies of `x`. /// The type of `x` must be [`Copy`]. /// -/// Note that `[x; 0]` is a valid repeat expression. This will produce an empty array -/// but will also initialize (or call) `x`, which may produce side effects. +/// Note that `[expr; 0]` is allowed, and produces an empty array. +/// This will still evaluate `expr`, however, and immediately drop the resulting value, so +/// be mindful of side effects. /// /// Arrays of *any* size implement the following traits if the element type allows it: /// -- cgit 1.4.1-3-g733a5 From 50576420f559be3c681e6833327845d6cf3217b4 Mon Sep 17 00:00:00 2001 From: Stein Somers Date: Tue, 24 Nov 2020 12:27:38 +0100 Subject: BTreeMap: clarify comments and panics surrounding choose_parent_kv --- library/alloc/src/collections/btree/node.rs | 14 ++++++++------ library/alloc/src/collections/btree/remove.rs | 12 ++++++------ 2 files changed, 14 insertions(+), 12 deletions(-) (limited to 'library/alloc/src') diff --git a/library/alloc/src/collections/btree/node.rs b/library/alloc/src/collections/btree/node.rs index 31809fde57b..588066f9fec 100644 --- a/library/alloc/src/collections/btree/node.rs +++ b/library/alloc/src/collections/btree/node.rs @@ -1282,10 +1282,12 @@ impl<'a, K, V> NodeRef, K, V, marker::LeafOrInternal> { /// Chooses a balancing context involving the node as a child, thus between /// the KV immediately to the left or to the right in the parent node. /// Returns an `Err` if there is no parent. + /// Panics if the parent is empty. /// - /// This method optimizes for a node that has fewer elements than its left - /// and right siblings, if they exist, by preferring the left parent KV. - /// Merging with the left sibling is faster, since we only need to move + /// Prefers the left side, to be optimal if the given node is somehow + /// underfull, meaning here only that it has fewer elements than its left + /// sibling and than its right sibling, if they exist. In that case, + /// merging with the left sibling is faster, since we only need to move /// the node's N elements, instead of shifting them to the right and moving /// more than N elements in front. Stealing from the left sibling is also /// typically faster, since we only need to shift the node's N elements to @@ -1293,19 +1295,19 @@ impl<'a, K, V> NodeRef, K, V, marker::LeafOrInternal> { /// the left. pub fn choose_parent_kv(self) -> Result>, Self> { match unsafe { ptr::read(&self) }.ascend() { - Ok(parent) => match parent.left_kv() { + Ok(parent_edge) => match parent_edge.left_kv() { Ok(left_parent_kv) => Ok(LeftOrRight::Left(BalancingContext { parent: unsafe { ptr::read(&left_parent_kv) }, left_child: left_parent_kv.left_edge().descend(), right_child: self, })), - Err(parent) => match parent.right_kv() { + Err(parent_edge) => match parent_edge.right_kv() { Ok(right_parent_kv) => Ok(LeftOrRight::Right(BalancingContext { parent: unsafe { ptr::read(&right_parent_kv) }, left_child: self, right_child: right_parent_kv.right_edge().descend(), })), - Err(_) => unreachable!("empty non-root node"), + Err(_) => unreachable!("empty internal node"), }, }, Err(root) => Err(root), diff --git a/library/alloc/src/collections/btree/remove.rs b/library/alloc/src/collections/btree/remove.rs index 5ae1c1fcab8..d8a0d51f28a 100644 --- a/library/alloc/src/collections/btree/remove.rs +++ b/library/alloc/src/collections/btree/remove.rs @@ -55,12 +55,12 @@ impl<'a, K: 'a, V: 'a> Handle, K, V, marker::Leaf>, mark pos = unsafe { new_pos.cast_to_leaf_unchecked() }; // Only if we merged, the parent (if any) has shrunk, but skipping - // the following step does not pay off in benchmarks. + // the following step otherwise does not pay off in benchmarks. // // SAFETY: We won't destroy or rearrange the leaf where `pos` is at // by handling its parent recursively; at worst we will destroy or // rearrange the parent through the grandparent, thus change the - // leaf's parent pointer. + // link to the parent inside the leaf. if let Ok(parent) = unsafe { pos.reborrow_mut() }.into_node().ascend() { parent.into_node().handle_shrunk_node_recursively(handle_emptied_internal_root); } @@ -92,8 +92,8 @@ impl<'a, K: 'a, V: 'a> Handle, K, V, marker::Internal>, } impl<'a, K: 'a, V: 'a> NodeRef, K, V, marker::Internal> { - /// Stocks up a possibly underfull internal node, recursively. - /// Climbs up until it reaches an ancestor that has elements to spare or the root. + /// Stocks up a possibly underfull internal node and its ancestors, + /// until it reaches an ancestor that has elements to spare or is the root. fn handle_shrunk_node_recursively(mut self, handle_emptied_internal_root: F) { loop { self = match self.len() { @@ -124,7 +124,7 @@ impl<'a, K: 'a, V: 'a> NodeRef, K, V, marker::Internal> { ) -> Option, K, V, marker::Internal>> { match self.forget_type().choose_parent_kv() { Ok(Left(left_parent_kv)) => { - debug_assert!(left_parent_kv.right_child_len() == MIN_LEN - 1); + debug_assert_eq!(left_parent_kv.right_child_len(), MIN_LEN - 1); if left_parent_kv.can_merge() { let pos = left_parent_kv.merge(None); let parent_edge = unsafe { unwrap_unchecked(pos.into_node().ascend().ok()) }; @@ -136,7 +136,7 @@ impl<'a, K: 'a, V: 'a> NodeRef, K, V, marker::Internal> { } } Ok(Right(right_parent_kv)) => { - debug_assert!(right_parent_kv.left_child_len() == MIN_LEN - 1); + debug_assert_eq!(right_parent_kv.left_child_len(), MIN_LEN - 1); if right_parent_kv.can_merge() { let pos = right_parent_kv.merge(None); let parent_edge = unsafe { unwrap_unchecked(pos.into_node().ascend().ok()) }; -- cgit 1.4.1-3-g733a5 From ad75a96b34c0c52036c7e903cc97816cdba150f8 Mon Sep 17 00:00:00 2001 From: Stein Somers Date: Mon, 23 Nov 2020 14:41:53 +0100 Subject: BTreeMap: detect bulk_steal's count-1 underflow in release builds too --- library/alloc/src/collections/btree/node.rs | 2 ++ 1 file changed, 2 insertions(+) (limited to 'library/alloc/src') diff --git a/library/alloc/src/collections/btree/node.rs b/library/alloc/src/collections/btree/node.rs index 31809fde57b..ffa18201431 100644 --- a/library/alloc/src/collections/btree/node.rs +++ b/library/alloc/src/collections/btree/node.rs @@ -1469,6 +1469,7 @@ impl<'a, K: 'a, V: 'a> BalancingContext<'a, K, V> { /// This does stealing similar to `steal_left` but steals multiple elements at once. pub fn bulk_steal_left(&mut self, count: usize) { + assert!(count > 0); unsafe { let left_node = &mut self.left_child; let old_left_len = left_node.len(); @@ -1526,6 +1527,7 @@ impl<'a, K: 'a, V: 'a> BalancingContext<'a, K, V> { /// The symmetric clone of `bulk_steal_left`. pub fn bulk_steal_right(&mut self, count: usize) { + assert!(count > 0); unsafe { let left_node = &mut self.left_child; let old_left_len = left_node.len(); -- cgit 1.4.1-3-g733a5 From 0ae4c95effa98e30d980264892860e7a0f727b4f Mon Sep 17 00:00:00 2001 From: Stein Somers Date: Mon, 23 Nov 2020 14:41:53 +0100 Subject: BTreeMap: capture a recurring use pattern as replace_kv --- library/alloc/src/collections/btree/node.rs | 12 ++++++++---- library/alloc/src/collections/btree/remove.rs | 6 ++---- 2 files changed, 10 insertions(+), 8 deletions(-) (limited to 'library/alloc/src') diff --git a/library/alloc/src/collections/btree/node.rs b/library/alloc/src/collections/btree/node.rs index 31809fde57b..ae5831d5140 100644 --- a/library/alloc/src/collections/btree/node.rs +++ b/library/alloc/src/collections/btree/node.rs @@ -1159,6 +1159,12 @@ impl<'a, K: 'a, V: 'a, NodeType> Handle, K, V, NodeType> (key, val) } } + + /// Replace the key and value that the KV handle refers to. + pub fn replace_kv(&mut self, k: K, v: V) -> (K, V) { + let (key, val) = self.kv_mut(); + (mem::replace(key, k), mem::replace(val, v)) + } } impl<'a, K: 'a, V: 'a, NodeType> Handle, K, V, NodeType>, marker::KV> { @@ -1432,8 +1438,7 @@ impl<'a, K: 'a, V: 'a> BalancingContext<'a, K, V> { unsafe { let (k, v, edge) = self.left_child.pop(); - let k = mem::replace(self.parent.kv_mut().0, k); - let v = mem::replace(self.parent.kv_mut().1, v); + let (k, v) = self.parent.replace_kv(k, v); match self.right_child.reborrow_mut().force() { ForceResult::Leaf(mut leaf) => leaf.push_front(k, v), @@ -1455,8 +1460,7 @@ impl<'a, K: 'a, V: 'a> BalancingContext<'a, K, V> { unsafe { let (k, v, edge) = self.right_child.pop_front(); - let k = mem::replace(self.parent.kv_mut().0, k); - let v = mem::replace(self.parent.kv_mut().1, v); + let (k, v) = self.parent.replace_kv(k, v); match self.left_child.reborrow_mut().force() { ForceResult::Leaf(mut leaf) => leaf.push(k, v), diff --git a/library/alloc/src/collections/btree/remove.rs b/library/alloc/src/collections/btree/remove.rs index 5ae1c1fcab8..1da0a060806 100644 --- a/library/alloc/src/collections/btree/remove.rs +++ b/library/alloc/src/collections/btree/remove.rs @@ -1,7 +1,6 @@ use super::map::MIN_LEN; use super::node::{marker, ForceResult::*, Handle, LeftOrRight::*, NodeRef}; use super::unwrap_unchecked; -use core::mem; impl<'a, K: 'a, V: 'a> Handle, K, V, marker::LeafOrInternal>, marker::KV> { /// Removes a key-value pair from the tree, and returns that pair, as well as @@ -84,10 +83,9 @@ impl<'a, K: 'a, V: 'a> Handle, K, V, marker::Internal>, // The internal node may have been stolen from or merged. Go back right // to find where the original KV ended up. let mut internal = unsafe { unwrap_unchecked(left_hole.next_kv().ok()) }; - let old_key = mem::replace(internal.kv_mut().0, left_kv.0); - let old_val = mem::replace(internal.kv_mut().1, left_kv.1); + let old_kv = internal.replace_kv(left_kv.0, left_kv.1); let pos = internal.next_leaf_edge(); - ((old_key, old_val), pos) + (old_kv, pos) } } -- cgit 1.4.1-3-g733a5 From 0f30b7dd87b8555698ca7e7de360b037230e1f23 Mon Sep 17 00:00:00 2001 From: Justus K Date: Sun, 13 Dec 2020 10:02:36 +0100 Subject: fix panic if converting ZST Vec to VecDeque --- library/alloc/src/collections/vec_deque/mod.rs | 8 ++++++-- library/alloc/tests/vec_deque.rs | 7 +++++++ 2 files changed, 13 insertions(+), 2 deletions(-) (limited to 'library/alloc/src') diff --git a/library/alloc/src/collections/vec_deque/mod.rs b/library/alloc/src/collections/vec_deque/mod.rs index 57807bc5453..1303b58e31c 100644 --- a/library/alloc/src/collections/vec_deque/mod.rs +++ b/library/alloc/src/collections/vec_deque/mod.rs @@ -2793,8 +2793,12 @@ impl From> for VecDeque { let len = other.len(); // We need to extend the buf if it's not a power of two, too small - // or doesn't have at least one free space - if !buf.capacity().is_power_of_two() + // or doesn't have at least one free space. + // We check if `T` is a ZST in the first condition, + // because `usize::MAX` (the capacity returned by `capacity()` for ZST) + // is not a power of zero and thus it'll always try + // to reserve more memory which will panic for ZST (rust-lang/rust#78532) + if (!buf.capacity().is_power_of_two() && mem::size_of::() != 0) || (buf.capacity() < (MINIMUM_CAPACITY + 1)) || (buf.capacity() == len) { diff --git a/library/alloc/tests/vec_deque.rs b/library/alloc/tests/vec_deque.rs index 705f0d62fbb..a962a5494a9 100644 --- a/library/alloc/tests/vec_deque.rs +++ b/library/alloc/tests/vec_deque.rs @@ -1728,3 +1728,10 @@ fn test_zero_sized_push() { } } } + +#[test] +fn test_from_zero_sized_vec() { + let v = vec![(); 100]; + let queue = VecDeque::from(v); + assert!(queue.len(), 100); +} -- cgit 1.4.1-3-g733a5 From bdc6adfb3bf3723268ac05540cc88bcca1b31227 Mon Sep 17 00:00:00 2001 From: Stein Somers Date: Mon, 23 Nov 2020 14:41:53 +0100 Subject: BTreeMap: declare clear_parent_link directly on the root it needs --- library/alloc/src/collections/btree/node.rs | 21 +++++++++++---------- 1 file changed, 11 insertions(+), 10 deletions(-) (limited to 'library/alloc/src') diff --git a/library/alloc/src/collections/btree/node.rs b/library/alloc/src/collections/btree/node.rs index ae5831d5140..968e197f170 100644 --- a/library/alloc/src/collections/btree/node.rs +++ b/library/alloc/src/collections/btree/node.rs @@ -150,7 +150,7 @@ impl NodeRef { /// Mutably borrows the owned node. Unlike `reborrow_mut`, this is safe, /// because the return value cannot be used to destroy the node itself, /// and there cannot be other references to the tree (except during the - /// process of `into_iter` or `drop`, but that is a horrific already). + /// process of `into_iter` or `drop`, but that is horrific already). pub fn borrow_mut(&mut self) -> NodeRef, K, V, Type> { NodeRef { height: self.height, node: self.node, _marker: PhantomData } } @@ -192,7 +192,7 @@ impl NodeRef { let internal_node = NodeRef { height: self.height, node: top, _marker: PhantomData }; *self = internal_node.first_edge().descend(); - self.borrow_mut().clear_parent_link(); + self.clear_parent_link(); unsafe { Global.deallocate(top.cast(), Layout::new::>()); @@ -611,18 +611,19 @@ impl<'a, K: 'a, V: 'a, Type> NodeRef, K, V, Type> { } impl<'a, K: 'a, V: 'a> NodeRef, K, V, marker::LeafOrInternal> { - /// Set or clear the node's link to its parent edge, + /// Sets the node's link to its parent edge, /// without invalidating other references to the node. fn set_parent_link(&mut self, parent: NonNull>, parent_idx: usize) { let leaf = Self::as_leaf_ptr(self); unsafe { (*leaf).parent = Some(parent) }; unsafe { (*leaf).parent_idx.write(parent_idx as u16) }; } +} - /// Clear the node's link to its parent edge. - /// This only makes sense when there are no other references to the node. +impl NodeRef { + /// Clears the root's link to its parent edge. fn clear_parent_link(&mut self) { - let leaf = Self::as_leaf_mut(self); + let leaf = NodeRef::as_leaf_mut(&mut self.borrow_mut()); leaf.parent = None; } } @@ -720,9 +721,9 @@ impl<'a, K: 'a, V: 'a> NodeRef, K, V, marker::LeafOrInternal> { ForceResult::Internal(internal) => { let node = ptr::read(internal.reborrow().edge_at(idx + 1)); let mut edge = Root { node, height: internal.height - 1, _marker: PhantomData }; - // In practice, clearing the parent is a waste of time, because we will + // Currently, clearing the parent link is superfluous, because we will // insert the node elsewhere and set its parent link again. - edge.borrow_mut().clear_parent_link(); + edge.clear_parent_link(); Some(edge) } }; @@ -748,9 +749,9 @@ impl<'a, K: 'a, V: 'a> NodeRef, K, V, marker::LeafOrInternal> { ForceResult::Internal(mut internal) => { let node = slice_remove(internal.reborrow_mut().into_edge_area_slice(), 0); let mut edge = Root { node, height: internal.height - 1, _marker: PhantomData }; - // In practice, clearing the parent is a waste of time, because we will + // Currently, clearing the parent link is superfluous, because we will // insert the node elsewhere and set its parent link again. - edge.borrow_mut().clear_parent_link(); + edge.clear_parent_link(); internal.correct_childrens_parent_links(0..old_len); -- cgit 1.4.1-3-g733a5 From 94fd1d325c2f36b12b8d62d8a7b06a431375e55e Mon Sep 17 00:00:00 2001 From: Stein Somers Date: Mon, 23 Nov 2020 14:41:53 +0100 Subject: BTreeMap: more expressive local variables in merge --- library/alloc/src/collections/btree/node.rs | 55 ++++++++++++++--------------- 1 file changed, 27 insertions(+), 28 deletions(-) (limited to 'library/alloc/src') diff --git a/library/alloc/src/collections/btree/node.rs b/library/alloc/src/collections/btree/node.rs index ae5831d5140..a8fffb389ef 100644 --- a/library/alloc/src/collections/btree/node.rs +++ b/library/alloc/src/collections/btree/node.rs @@ -1352,66 +1352,65 @@ impl<'a, K: 'a, V: 'a> BalancingContext<'a, K, V> { /// /// Panics unless we `.can_merge()`. pub fn merge( - mut self, + self, track_edge_idx: Option>, ) -> Handle, K, V, marker::LeafOrInternal>, marker::Edge> { + let Handle { node: mut parent_node, idx: parent_idx, _marker } = self.parent; + let old_parent_len = parent_node.len(); let mut left_node = self.left_child; - let left_len = left_node.len(); + let old_left_len = left_node.len(); let right_node = self.right_child; let right_len = right_node.len(); + let new_left_len = old_left_len + 1 + right_len; - assert!(left_len + right_len < CAPACITY); + assert!(new_left_len <= CAPACITY); assert!(match track_edge_idx { None => true, - Some(LeftOrRight::Left(idx)) => idx <= left_len, + Some(LeftOrRight::Left(idx)) => idx <= old_left_len, Some(LeftOrRight::Right(idx)) => idx <= right_len, }); unsafe { - *left_node.reborrow_mut().into_len_mut() += right_len as u16 + 1; + *left_node.reborrow_mut().into_len_mut() = new_left_len as u16; - let parent_key = slice_remove( - self.parent.node.reborrow_mut().into_key_area_slice(), - self.parent.idx, - ); - left_node.reborrow_mut().into_key_area_mut_at(left_len).write(parent_key); + let parent_key = + slice_remove(parent_node.reborrow_mut().into_key_area_slice(), parent_idx); + left_node.reborrow_mut().into_key_area_mut_at(old_left_len).write(parent_key); ptr::copy_nonoverlapping( right_node.reborrow().key_area().as_ptr(), - left_node.reborrow_mut().into_key_area_slice().as_mut_ptr().add(left_len + 1), + left_node.reborrow_mut().into_key_area_slice().as_mut_ptr().add(old_left_len + 1), right_len, ); - let parent_val = slice_remove( - self.parent.node.reborrow_mut().into_val_area_slice(), - self.parent.idx, - ); - left_node.reborrow_mut().into_val_area_mut_at(left_len).write(parent_val); + let parent_val = + slice_remove(parent_node.reborrow_mut().into_val_area_slice(), parent_idx); + left_node.reborrow_mut().into_val_area_mut_at(old_left_len).write(parent_val); ptr::copy_nonoverlapping( right_node.reborrow().val_area().as_ptr(), - left_node.reborrow_mut().into_val_area_slice().as_mut_ptr().add(left_len + 1), + left_node.reborrow_mut().into_val_area_slice().as_mut_ptr().add(old_left_len + 1), right_len, ); - slice_remove( - &mut self.parent.node.reborrow_mut().into_edge_area_slice(), - self.parent.idx + 1, - ); - let parent_old_len = self.parent.node.len(); - self.parent.node.correct_childrens_parent_links(self.parent.idx + 1..parent_old_len); - *self.parent.node.reborrow_mut().into_len_mut() -= 1; + slice_remove(&mut parent_node.reborrow_mut().into_edge_area_slice(), parent_idx + 1); + parent_node.correct_childrens_parent_links(parent_idx + 1..old_parent_len); + *parent_node.reborrow_mut().into_len_mut() -= 1; - if self.parent.node.height > 1 { + if parent_node.height > 1 { // SAFETY: the height of the nodes being merged is one below the height // of the node of this edge, thus above zero, so they are internal. let mut left_node = left_node.reborrow_mut().cast_to_internal_unchecked(); let right_node = right_node.cast_to_internal_unchecked(); ptr::copy_nonoverlapping( right_node.reborrow().edge_area().as_ptr(), - left_node.reborrow_mut().into_edge_area_slice().as_mut_ptr().add(left_len + 1), + left_node + .reborrow_mut() + .into_edge_area_slice() + .as_mut_ptr() + .add(old_left_len + 1), right_len + 1, ); - left_node.correct_childrens_parent_links(left_len + 1..=left_len + 1 + right_len); + left_node.correct_childrens_parent_links(old_left_len + 1..new_left_len + 1); Global.deallocate(right_node.node.cast(), Layout::new::>()); } else { @@ -1421,7 +1420,7 @@ impl<'a, K: 'a, V: 'a> BalancingContext<'a, K, V> { let new_idx = match track_edge_idx { None => 0, Some(LeftOrRight::Left(idx)) => idx, - Some(LeftOrRight::Right(idx)) => left_len + 1 + idx, + Some(LeftOrRight::Right(idx)) => old_left_len + 1 + idx, }; Handle::new_edge(left_node, new_idx) } -- cgit 1.4.1-3-g733a5 From 09d528ec155f77349001fa7eb6c3ae3363f41412 Mon Sep 17 00:00:00 2001 From: Justus K Date: Sun, 13 Dec 2020 15:18:38 +0100 Subject: fix typo --- library/alloc/src/collections/vec_deque/mod.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'library/alloc/src') diff --git a/library/alloc/src/collections/vec_deque/mod.rs b/library/alloc/src/collections/vec_deque/mod.rs index 1303b58e31c..9e54c15ea6a 100644 --- a/library/alloc/src/collections/vec_deque/mod.rs +++ b/library/alloc/src/collections/vec_deque/mod.rs @@ -2796,7 +2796,7 @@ impl From> for VecDeque { // or doesn't have at least one free space. // We check if `T` is a ZST in the first condition, // because `usize::MAX` (the capacity returned by `capacity()` for ZST) - // is not a power of zero and thus it'll always try + // is not a power of two and thus it'll always try // to reserve more memory which will panic for ZST (rust-lang/rust#78532) if (!buf.capacity().is_power_of_two() && mem::size_of::() != 0) || (buf.capacity() < (MINIMUM_CAPACITY + 1)) -- cgit 1.4.1-3-g733a5 From 6c7835e4410f820c2bcdcd3d34fa48f0053af7d4 Mon Sep 17 00:00:00 2001 From: Stein Somers Date: Fri, 20 Nov 2020 21:29:00 +0100 Subject: BTreeSet: simplify implementation of pop_first/pop_last --- library/alloc/src/collections/btree/set.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'library/alloc/src') diff --git a/library/alloc/src/collections/btree/set.rs b/library/alloc/src/collections/btree/set.rs index d8ce47ed77d..f63c3dd5804 100644 --- a/library/alloc/src/collections/btree/set.rs +++ b/library/alloc/src/collections/btree/set.rs @@ -679,7 +679,7 @@ impl BTreeSet { /// ``` #[unstable(feature = "map_first_last", issue = "62924")] pub fn pop_first(&mut self) -> Option { - self.map.first_entry().map(|entry| entry.remove_entry().0) + self.map.pop_first().map(|kv| kv.0) } /// Removes the last value from the set and returns it, if any. @@ -701,7 +701,7 @@ impl BTreeSet { /// ``` #[unstable(feature = "map_first_last", issue = "62924")] pub fn pop_last(&mut self) -> Option { - self.map.last_entry().map(|entry| entry.remove_entry().0) + self.map.pop_last().map(|kv| kv.0) } /// Adds a value to the set. -- cgit 1.4.1-3-g733a5 From 29114ff0fb79f63f14ba1958e745324cedc13b2d Mon Sep 17 00:00:00 2001 From: Stein Somers Date: Mon, 23 Nov 2020 14:41:53 +0100 Subject: BTreeMap: relax the explicit borrow rule to make code shorter and safer --- library/alloc/src/collections/btree/map.rs | 2 +- library/alloc/src/collections/btree/node.rs | 212 ++++++++++++++-------------- 2 files changed, 108 insertions(+), 106 deletions(-) (limited to 'library/alloc/src') diff --git a/library/alloc/src/collections/btree/map.rs b/library/alloc/src/collections/btree/map.rs index bd2ad257402..735213363f6 100644 --- a/library/alloc/src/collections/btree/map.rs +++ b/library/alloc/src/collections/btree/map.rs @@ -248,7 +248,7 @@ where let (map, dormant_map) = DormantMutRef::new(self); let root_node = Self::ensure_is_owned(&mut map.root).borrow_mut(); match search::search_tree::, K, (), K>(root_node, &key) { - Found(handle) => Some(mem::replace(handle.into_key_mut(), key)), + Found(mut kv) => Some(mem::replace(kv.key_mut(), key)), GoDown(handle) => { VacantEntry { key, handle, dormant_map, _marker: PhantomData }.insert(()); None diff --git a/library/alloc/src/collections/btree/node.rs b/library/alloc/src/collections/btree/node.rs index 22e179af4a9..a3ff83561f1 100644 --- a/library/alloc/src/collections/btree/node.rs +++ b/library/alloc/src/collections/btree/node.rs @@ -239,17 +239,16 @@ impl NodeRef { /// - We cannot get implicit coercion from say `Mut<'a>` to `Immut<'a>`. /// Therefore, we have to explicitly call `reborrow` on a more powerfull /// `NodeRef` in order to reach a method like `key_at`. -/// - All methods on `NodeRef` that return some kind of reference, except -/// `reborrow` and `reborrow_mut`, take `self` by value and not by reference. -/// This avoids silently returning a second reference somewhere in the tree. -/// That is irrelevant when `BorrowType` is `Immut<'a>`, but the rule does -/// no harm because we make those `NodeRef` implicitly `Copy`. -/// The rule also avoids implicitly returning the lifetime of `&self`, -/// instead of the lifetime carried by `BorrowType`. -/// An exception to this rule are the insert functions. -/// - Given the above, we need a `reborrow_mut` to explicitly copy a `Mut<'a>` -/// `NodeRef` whenever we want to invoke a method returning an extra reference -/// somewhere in the tree. +/// +/// All methods on `NodeRef` that return some kind of reference, either: +/// - Take `self` by value, and return the lifetime carried by `BorrowType`. +/// Sometimes, to invoke such a method, we need to call `reborrow_mut`. +/// - Take `self` by reference, and (implicitly) return that reference's +/// lifetime, instead of the lifetime carried by `BorrowType`. That way, +/// the borrow checker guarantees that the `NodeRef` remains borrowed as long +/// as the returned reference is used. +/// The methods supporting insert bend this rule by returning a raw pointer, +/// i.e., a reference without any lifetime. pub struct NodeRef { /// The number of levels that the node and the level of leaves are apart, a /// constant of the node that cannot be entirely described by `Type`, and that @@ -305,9 +304,9 @@ impl<'a, K, V> NodeRef, K, V, marker::Internal> { } impl<'a, K, V> NodeRef, K, V, marker::Internal> { - /// Offers exclusive access to the data of an internal node. - fn as_internal_mut(this: &mut Self) -> &'a mut InternalNode { - let ptr = Self::as_internal_ptr(this); + /// Borrows exclusive access to the data of an internal node. + fn as_internal_mut(&mut self) -> &mut InternalNode { + let ptr = Self::as_internal_ptr(self); unsafe { &mut *ptr } } } @@ -355,7 +354,7 @@ impl<'a, K: 'a, V: 'a, Type> NodeRef, K, V, Type> { /// The node has more than `idx` initialized elements. pub unsafe fn key_at(self, idx: usize) -> &'a K { debug_assert!(idx < self.len()); - unsafe { Self::as_leaf(&self).keys.get_unchecked(idx).assume_init_ref() } + unsafe { self.into_leaf().keys.get_unchecked(idx).assume_init_ref() } } /// Exposes one of the values stored in the node. @@ -364,7 +363,7 @@ impl<'a, K: 'a, V: 'a, Type> NodeRef, K, V, Type> { /// The node has more than `idx` initialized elements. unsafe fn val_at(self, idx: usize) -> &'a V { debug_assert!(idx < self.len()); - unsafe { Self::as_leaf(&self).vals.get_unchecked(idx).assume_init_ref() } + unsafe { self.into_leaf().vals.get_unchecked(idx).assume_init_ref() } } } @@ -431,8 +430,8 @@ impl NodeRef { impl<'a, K: 'a, V: 'a, Type> NodeRef, K, V, Type> { /// Exposes the leaf portion of any leaf or internal node in an immutable tree. - fn as_leaf(this: &Self) -> &'a LeafNode { - let ptr = Self::as_leaf_ptr(this); + fn into_leaf(self) -> &'a LeafNode { + let ptr = Self::as_leaf_ptr(&self); // SAFETY: there can be no mutable references into this tree borrowed as `Immut`. unsafe { &*ptr } } @@ -489,42 +488,49 @@ impl<'a, K, V, Type> NodeRef, K, V, Type> { NodeRef { height: self.height, node: self.node, _marker: PhantomData } } + /// Borrows exclusive access to the leaf portion of any leaf or internal node. + fn as_leaf_mut(&mut self) -> &mut LeafNode { + let ptr = Self::as_leaf_ptr(self); + // SAFETY: we have exclusive access to the entire node. + unsafe { &mut *ptr } + } + /// Offers exclusive access to the leaf portion of any leaf or internal node. - fn as_leaf_mut(this: &mut Self) -> &'a mut LeafNode { - let ptr = Self::as_leaf_ptr(this); + fn into_leaf_mut(mut self) -> &'a mut LeafNode { + let ptr = Self::as_leaf_ptr(&mut self); // SAFETY: we have exclusive access to the entire node. unsafe { &mut *ptr } } } impl<'a, K: 'a, V: 'a, Type> NodeRef, K, V, Type> { - /// Offers exclusive access to a part of the key storage area. + /// Borrows exclusive access to an element of the key storage area. /// /// # Safety /// The node has more than `idx` initialized elements. - unsafe fn into_key_area_mut_at(mut self, idx: usize) -> &'a mut MaybeUninit { + unsafe fn key_area_mut_at(&mut self, idx: usize) -> &mut MaybeUninit { debug_assert!(idx < self.len()); - unsafe { Self::as_leaf_mut(&mut self).keys.get_unchecked_mut(idx) } + unsafe { self.as_leaf_mut().keys.get_unchecked_mut(idx) } } - /// Offers exclusive access to a part of the value storage area. + /// Borrows exclusive access to an element of the value storage area. /// /// # Safety /// The node has more than `idx` initialized elements. - unsafe fn into_val_area_mut_at(mut self, idx: usize) -> &'a mut MaybeUninit { + unsafe fn val_area_mut_at(&mut self, idx: usize) -> &mut MaybeUninit { debug_assert!(idx < self.len()); - unsafe { Self::as_leaf_mut(&mut self).vals.get_unchecked_mut(idx) } + unsafe { self.as_leaf_mut().vals.get_unchecked_mut(idx) } } } impl<'a, K: 'a, V: 'a> NodeRef, K, V, marker::Internal> { - /// Offers exclusive access to a part of the storage area for edge contents. + /// Borrows exclusive access to an element of the storage area for edge contents. /// /// # Safety /// The node has at least `idx` initialized elements. - unsafe fn into_edge_area_mut_at(mut self, idx: usize) -> &'a mut MaybeUninit> { + unsafe fn edge_area_mut_at(&mut self, idx: usize) -> &mut MaybeUninit> { debug_assert!(idx <= self.len()); - unsafe { Self::as_internal_mut(&mut self).edges.get_unchecked_mut(idx) } + unsafe { self.as_internal_mut().edges.get_unchecked_mut(idx) } } } @@ -533,14 +539,14 @@ impl<'a, K: 'a, V: 'a, Type> NodeRef, K, V, Type> { /// regardless of the node's current length, /// having exclusive access to the entire node. unsafe fn key_area(self) -> &'a [MaybeUninit] { - Self::as_leaf(&self).keys.as_slice() + self.into_leaf().keys.as_slice() } /// Exposes the entire value storage area in the node, /// regardless of the node's current length, /// having exclusive access to the entire node. unsafe fn val_area(self) -> &'a [MaybeUninit] { - Self::as_leaf(&self).vals.as_slice() + self.into_leaf().vals.as_slice() } } @@ -554,33 +560,33 @@ impl<'a, K: 'a, V: 'a> NodeRef, K, V, marker::Internal> { } impl<'a, K: 'a, V: 'a, Type> NodeRef, K, V, Type> { - /// Offers exclusive access to a sized slice of key storage area in the node. - unsafe fn into_key_area_slice(mut self) -> &'a mut [MaybeUninit] { + /// Borrows exclusive access to a sized slice of key storage area in the node. + unsafe fn key_area_slice(&mut self) -> &mut [MaybeUninit] { let len = self.len(); // SAFETY: the caller will not be able to call further methods on self // until the key slice reference is dropped, as we have unique access // for the lifetime of the borrow. - unsafe { Self::as_leaf_mut(&mut self).keys.get_unchecked_mut(..len) } + unsafe { self.as_leaf_mut().keys.get_unchecked_mut(..len) } } - /// Offers exclusive access to a sized slice of value storage area in the node. - unsafe fn into_val_area_slice(mut self) -> &'a mut [MaybeUninit] { + /// Borrows exclusive access to a sized slice of value storage area in the node. + unsafe fn val_area_slice(&mut self) -> &mut [MaybeUninit] { let len = self.len(); // SAFETY: the caller will not be able to call further methods on self // until the value slice reference is dropped, as we have unique access // for the lifetime of the borrow. - unsafe { Self::as_leaf_mut(&mut self).vals.get_unchecked_mut(..len) } + unsafe { self.as_leaf_mut().vals.get_unchecked_mut(..len) } } } impl<'a, K: 'a, V: 'a> NodeRef, K, V, marker::Internal> { - /// Offers exclusive access to a sized slice of storage area for edge contents in the node. - unsafe fn into_edge_area_slice(mut self) -> &'a mut [MaybeUninit>] { + /// Borrows exclusive access to a sized slice of storage area for edge contents in the node. + unsafe fn edge_area_slice(&mut self) -> &mut [MaybeUninit>] { let len = self.len(); // SAFETY: the caller will not be able to call further methods on self // until the edge slice reference is dropped, as we have unique access // for the lifetime of the borrow. - unsafe { Self::as_internal_mut(&mut self).edges.get_unchecked_mut(..len + 1) } + unsafe { self.as_internal_mut().edges.get_unchecked_mut(..len + 1) } } } @@ -604,9 +610,9 @@ impl<'a, K, V, Type> NodeRef, K, V, Type> { } impl<'a, K: 'a, V: 'a, Type> NodeRef, K, V, Type> { - /// Exposes exclusive access to the length of the node. - pub fn into_len_mut(mut self) -> &'a mut u16 { - &mut (*Self::as_leaf_mut(&mut self)).len + /// Borrows exclusive access to the length of the node. + pub fn len_mut(&mut self) -> &mut u16 { + &mut self.as_leaf_mut().len } } @@ -623,7 +629,8 @@ impl<'a, K: 'a, V: 'a> NodeRef, K, V, marker::LeafOrInternal> { impl NodeRef { /// Clears the root's link to its parent edge. fn clear_parent_link(&mut self) { - let leaf = NodeRef::as_leaf_mut(&mut self.borrow_mut()); + let mut root_node = self.borrow_mut(); + let leaf = root_node.as_leaf_mut(); leaf.parent = None; } } @@ -631,13 +638,13 @@ impl NodeRef { impl<'a, K: 'a, V: 'a> NodeRef, K, V, marker::Leaf> { /// Adds a key-value pair to the end of the node. pub fn push(&mut self, key: K, val: V) { - let len = unsafe { self.reborrow_mut().into_len_mut() }; + let len = self.len_mut(); let idx = usize::from(*len); assert!(idx < CAPACITY); *len += 1; unsafe { - self.reborrow_mut().into_key_area_mut_at(idx).write(key); - self.reborrow_mut().into_val_area_mut_at(idx).write(val); + self.key_area_mut_at(idx).write(key); + self.val_area_mut_at(idx).write(val); } } @@ -646,9 +653,9 @@ impl<'a, K: 'a, V: 'a> NodeRef, K, V, marker::Leaf> { assert!(self.len() < CAPACITY); unsafe { - *self.reborrow_mut().into_len_mut() += 1; - slice_insert(self.reborrow_mut().into_key_area_slice(), 0, key); - slice_insert(self.reborrow_mut().into_val_area_slice(), 0, val); + *self.len_mut() += 1; + slice_insert(self.key_area_slice(), 0, key); + slice_insert(self.val_area_slice(), 0, val); } } } @@ -675,14 +682,14 @@ impl<'a, K: 'a, V: 'a> NodeRef, K, V, marker::Internal> { pub fn push(&mut self, key: K, val: V, edge: Root) { assert!(edge.height == self.height - 1); - let len = unsafe { self.reborrow_mut().into_len_mut() }; + let len = self.len_mut(); let idx = usize::from(*len); assert!(idx < CAPACITY); *len += 1; unsafe { - self.reborrow_mut().into_key_area_mut_at(idx).write(key); - self.reborrow_mut().into_val_area_mut_at(idx).write(val); - self.reborrow_mut().into_edge_area_mut_at(idx + 1).write(edge.node); + self.key_area_mut_at(idx).write(key); + self.val_area_mut_at(idx).write(val); + self.edge_area_mut_at(idx + 1).write(edge.node); Handle::new_edge(self.reborrow_mut(), idx + 1).correct_parent_link(); } } @@ -694,10 +701,10 @@ impl<'a, K: 'a, V: 'a> NodeRef, K, V, marker::Internal> { assert!(self.len() < CAPACITY); unsafe { - *self.reborrow_mut().into_len_mut() += 1; - slice_insert(self.reborrow_mut().into_key_area_slice(), 0, key); - slice_insert(self.reborrow_mut().into_val_area_slice(), 0, val); - slice_insert(self.reborrow_mut().into_edge_area_slice(), 0, edge.node); + *self.len_mut() += 1; + slice_insert(self.key_area_slice(), 0, key); + slice_insert(self.val_area_slice(), 0, val); + slice_insert(self.edge_area_slice(), 0, edge.node); } self.correct_all_childrens_parent_links(); @@ -728,7 +735,7 @@ impl<'a, K: 'a, V: 'a> NodeRef, K, V, marker::LeafOrInternal> { } }; - *self.reborrow_mut().into_len_mut() -= 1; + *self.len_mut() -= 1; (key, val, edge) } } @@ -742,12 +749,12 @@ impl<'a, K: 'a, V: 'a> NodeRef, K, V, marker::LeafOrInternal> { let old_len = self.len(); unsafe { - let key = slice_remove(self.reborrow_mut().into_key_area_slice(), 0); - let val = slice_remove(self.reborrow_mut().into_val_area_slice(), 0); + let key = slice_remove(self.key_area_slice(), 0); + let val = slice_remove(self.val_area_slice(), 0); let edge = match self.reborrow_mut().force() { ForceResult::Leaf(_) => None, ForceResult::Internal(mut internal) => { - let node = slice_remove(internal.reborrow_mut().into_edge_area_slice(), 0); + let node = slice_remove(internal.edge_area_slice(), 0); let mut edge = Root { node, height: internal.height - 1, _marker: PhantomData }; // Currently, clearing the parent link is superfluous, because we will // insert the node elsewhere and set its parent link again. @@ -759,14 +766,14 @@ impl<'a, K: 'a, V: 'a> NodeRef, K, V, marker::LeafOrInternal> { } }; - *self.reborrow_mut().into_len_mut() -= 1; + *self.len_mut() -= 1; (key, val, edge) } } fn into_kv_pointers_mut(mut self) -> (*mut K, *mut V) { - let leaf = Self::as_leaf_mut(&mut self); + let leaf = self.as_leaf_mut(); let keys = MaybeUninit::slice_as_mut_ptr(&mut leaf.keys); let vals = MaybeUninit::slice_as_mut_ptr(&mut leaf.vals); (keys, vals) @@ -970,11 +977,11 @@ impl<'a, K: 'a, V: 'a> Handle, K, V, marker::Leaf>, mark debug_assert!(self.node.len() < CAPACITY); unsafe { - *self.node.reborrow_mut().into_len_mut() += 1; - slice_insert(self.node.reborrow_mut().into_key_area_slice(), self.idx, key); - slice_insert(self.node.reborrow_mut().into_val_area_slice(), self.idx, val); + *self.node.len_mut() += 1; + slice_insert(self.node.key_area_slice(), self.idx, key); + slice_insert(self.node.val_area_slice(), self.idx, val); - self.node.reborrow_mut().into_val_area_mut_at(self.idx).assume_init_mut() + self.node.val_area_mut_at(self.idx).assume_init_mut() } } } @@ -1028,10 +1035,10 @@ impl<'a, K: 'a, V: 'a> Handle, K, V, marker::Internal>, debug_assert!(edge.height == self.node.height - 1); unsafe { - *self.node.reborrow_mut().into_len_mut() += 1; - slice_insert(self.node.reborrow_mut().into_key_area_slice(), self.idx, key); - slice_insert(self.node.reborrow_mut().into_val_area_slice(), self.idx, val); - slice_insert(self.node.reborrow_mut().into_edge_area_slice(), self.idx + 1, edge.node); + *self.node.len_mut() += 1; + slice_insert(self.node.key_area_slice(), self.idx, key); + slice_insert(self.node.val_area_slice(), self.idx, val); + slice_insert(self.node.edge_area_slice(), self.idx + 1, edge.node); self.node.correct_childrens_parent_links((self.idx + 1)..=self.node.len()); } @@ -1134,12 +1141,13 @@ impl<'a, K: 'a, V: 'a, NodeType> Handle, K, V, NodeTyp } impl<'a, K: 'a, V: 'a, NodeType> Handle, K, V, NodeType>, marker::KV> { - pub fn into_key_mut(self) -> &'a mut K { - unsafe { self.node.into_key_area_mut_at(self.idx).assume_init_mut() } + pub fn key_mut(&mut self) -> &mut K { + unsafe { self.node.key_area_mut_at(self.idx).assume_init_mut() } } pub fn into_val_mut(self) -> &'a mut V { - unsafe { self.node.into_val_area_mut_at(self.idx).assume_init_mut() } + let leaf = self.node.into_leaf_mut(); + unsafe { leaf.vals.get_unchecked_mut(self.idx).assume_init_mut() } } } @@ -1154,7 +1162,7 @@ impl<'a, K: 'a, V: 'a, NodeType> Handle, K, V, NodeType> // We cannot call separate key and value methods, because calling the second one // invalidates the reference returned by the first. unsafe { - let leaf = NodeRef::as_leaf_mut(&mut self.node.reborrow_mut()); + let leaf = self.node.as_leaf_mut(); let key = leaf.keys.get_unchecked_mut(self.idx).assume_init_mut(); let val = leaf.vals.get_unchecked_mut(self.idx).assume_init_mut(); (key, val) @@ -1196,7 +1204,7 @@ impl<'a, K: 'a, V: 'a, NodeType> Handle, K, V, NodeType> new_len, ); - *self.node.reborrow_mut().into_len_mut() = self.idx as u16; + *self.node.len_mut() = self.idx as u16; (k, v) } } @@ -1227,9 +1235,9 @@ impl<'a, K: 'a, V: 'a> Handle, K, V, marker::Leaf>, mark mut self, ) -> ((K, V), Handle, K, V, marker::Leaf>, marker::Edge>) { unsafe { - let k = slice_remove(self.node.reborrow_mut().into_key_area_slice(), self.idx); - let v = slice_remove(self.node.reborrow_mut().into_val_area_slice(), self.idx); - *self.node.reborrow_mut().into_len_mut() -= 1; + let k = slice_remove(self.node.key_area_slice(), self.idx); + let v = slice_remove(self.node.val_area_slice(), self.idx); + *self.node.len_mut() -= 1; ((k, v), self.left_edge()) } } @@ -1374,29 +1382,27 @@ impl<'a, K: 'a, V: 'a> BalancingContext<'a, K, V> { }); unsafe { - *left_node.reborrow_mut().into_len_mut() = new_left_len as u16; + *left_node.len_mut() = new_left_len as u16; - let parent_key = - slice_remove(parent_node.reborrow_mut().into_key_area_slice(), parent_idx); - left_node.reborrow_mut().into_key_area_mut_at(old_left_len).write(parent_key); + let parent_key = slice_remove(parent_node.key_area_slice(), parent_idx); + left_node.key_area_mut_at(old_left_len).write(parent_key); ptr::copy_nonoverlapping( right_node.reborrow().key_area().as_ptr(), - left_node.reborrow_mut().into_key_area_slice().as_mut_ptr().add(old_left_len + 1), + left_node.key_area_slice().as_mut_ptr().add(old_left_len + 1), right_len, ); - let parent_val = - slice_remove(parent_node.reborrow_mut().into_val_area_slice(), parent_idx); - left_node.reborrow_mut().into_val_area_mut_at(old_left_len).write(parent_val); + let parent_val = slice_remove(parent_node.val_area_slice(), parent_idx); + left_node.val_area_mut_at(old_left_len).write(parent_val); ptr::copy_nonoverlapping( right_node.reborrow().val_area().as_ptr(), - left_node.reborrow_mut().into_val_area_slice().as_mut_ptr().add(old_left_len + 1), + left_node.val_area_slice().as_mut_ptr().add(old_left_len + 1), right_len, ); - slice_remove(&mut parent_node.reborrow_mut().into_edge_area_slice(), parent_idx + 1); + slice_remove(&mut parent_node.edge_area_slice(), parent_idx + 1); parent_node.correct_childrens_parent_links(parent_idx + 1..old_parent_len); - *parent_node.reborrow_mut().into_len_mut() -= 1; + *parent_node.len_mut() -= 1; if parent_node.height > 1 { // SAFETY: the height of the nodes being merged is one below the height @@ -1405,11 +1411,7 @@ impl<'a, K: 'a, V: 'a> BalancingContext<'a, K, V> { let right_node = right_node.cast_to_internal_unchecked(); ptr::copy_nonoverlapping( right_node.reborrow().edge_area().as_ptr(), - left_node - .reborrow_mut() - .into_edge_area_slice() - .as_mut_ptr() - .add(old_left_len + 1), + left_node.edge_area_slice().as_mut_ptr().add(old_left_len + 1), right_len + 1, ); @@ -1511,14 +1513,14 @@ impl<'a, K: 'a, V: 'a> BalancingContext<'a, K, V> { move_kv(left_kv, new_left_len, parent_kv, 0, 1); } - *left_node.reborrow_mut().into_len_mut() -= count as u16; - *right_node.reborrow_mut().into_len_mut() += count as u16; + *left_node.len_mut() -= count as u16; + *right_node.len_mut() += count as u16; match (left_node.reborrow_mut().force(), right_node.reborrow_mut().force()) { (ForceResult::Internal(left), ForceResult::Internal(mut right)) => { // Make room for stolen edges. let left = left.reborrow(); - let right_edges = right.reborrow_mut().into_edge_area_slice().as_mut_ptr(); + let right_edges = right.edge_area_slice().as_mut_ptr(); ptr::copy(right_edges, right_edges.add(count), old_right_len + 1); right.correct_childrens_parent_links(count..count + old_right_len + 1); @@ -1569,8 +1571,8 @@ impl<'a, K: 'a, V: 'a> BalancingContext<'a, K, V> { ptr::copy(right_kv.1.add(count), right_kv.1, new_right_len); } - *left_node.reborrow_mut().into_len_mut() += count as u16; - *right_node.reborrow_mut().into_len_mut() -= count as u16; + *left_node.len_mut() += count as u16; + *right_node.len_mut() -= count as u16; match (left_node.reborrow_mut().force(), right_node.reborrow_mut().force()) { (ForceResult::Internal(left), ForceResult::Internal(mut right)) => { @@ -1578,7 +1580,7 @@ impl<'a, K: 'a, V: 'a> BalancingContext<'a, K, V> { move_edges(right.reborrow(), 0, left, old_left_len + 1, count); // Fill gap where stolen edges used to be. - let right_edges = right.reborrow_mut().into_edge_area_slice().as_mut_ptr(); + let right_edges = right.edge_area_slice().as_mut_ptr(); ptr::copy(right_edges.add(count), right_edges, new_right_len + 1); right.correct_childrens_parent_links(0..=new_right_len); } @@ -1612,7 +1614,7 @@ unsafe fn move_edges<'a, K: 'a, V: 'a>( ) { unsafe { let source_ptr = source.edge_area().as_ptr(); - let dest_ptr = dest.reborrow_mut().into_edge_area_slice().as_mut_ptr(); + let dest_ptr = dest.edge_area_slice().as_mut_ptr(); ptr::copy_nonoverlapping(source_ptr.add(source_offset), dest_ptr.add(dest_offset), count); dest.correct_childrens_parent_links(dest_offset..dest_offset + count); } @@ -1708,8 +1710,8 @@ impl<'a, K, V> Handle, K, V, marker::LeafOrInternal>, ma move_kv(left_kv, new_left_len, right_kv, 0, new_right_len); - *left_node.reborrow_mut().into_len_mut() = new_left_len as u16; - *right_node.reborrow_mut().into_len_mut() = new_right_len as u16; + *left_node.len_mut() = new_left_len as u16; + *right_node.len_mut() = new_right_len as u16; match (left_node.force(), right_node.force()) { (ForceResult::Internal(left), ForceResult::Internal(right)) => { -- cgit 1.4.1-3-g733a5 From 8824efd61c050d8ee138593b6128950ec25c752d Mon Sep 17 00:00:00 2001 From: Stein Somers Date: Mon, 23 Nov 2020 14:41:53 +0100 Subject: BTreeMap: avoid implicit use of node length in flight --- library/alloc/src/collections/btree/node.rs | 178 +++++++++++++--------------- 1 file changed, 81 insertions(+), 97 deletions(-) (limited to 'library/alloc/src') diff --git a/library/alloc/src/collections/btree/node.rs b/library/alloc/src/collections/btree/node.rs index a3ff83561f1..769383515b7 100644 --- a/library/alloc/src/collections/btree/node.rs +++ b/library/alloc/src/collections/btree/node.rs @@ -35,6 +35,7 @@ use core::cmp::Ordering; use core::marker::PhantomData; use core::mem::{self, MaybeUninit}; use core::ptr::{self, NonNull}; +use core::slice::SliceIndex; use crate::alloc::{Allocator, Global, Layout}; use crate::boxed::Box; @@ -507,30 +508,45 @@ impl<'a, K: 'a, V: 'a, Type> NodeRef, K, V, Type> { /// Borrows exclusive access to an element of the key storage area. /// /// # Safety - /// The node has more than `idx` initialized elements. - unsafe fn key_area_mut_at(&mut self, idx: usize) -> &mut MaybeUninit { - debug_assert!(idx < self.len()); - unsafe { self.as_leaf_mut().keys.get_unchecked_mut(idx) } + /// `index` is in bounds of 0..CAPACITY + unsafe fn key_area_mut_at(&mut self, index: I) -> &mut Output + where + I: SliceIndex<[MaybeUninit], Output = Output>, + { + // SAFETY: the caller will not be able to call further methods on self + // until the key slice reference is dropped, as we have unique access + // for the lifetime of the borrow. + unsafe { self.as_leaf_mut().keys.as_mut_slice().get_unchecked_mut(index) } } - /// Borrows exclusive access to an element of the value storage area. + /// Borrows exclusive access to an element or slice of the node's value storage area. /// /// # Safety - /// The node has more than `idx` initialized elements. - unsafe fn val_area_mut_at(&mut self, idx: usize) -> &mut MaybeUninit { - debug_assert!(idx < self.len()); - unsafe { self.as_leaf_mut().vals.get_unchecked_mut(idx) } + /// `index` is in bounds of 0..CAPACITY + unsafe fn val_area_mut_at(&mut self, index: I) -> &mut Output + where + I: SliceIndex<[MaybeUninit], Output = Output>, + { + // SAFETY: the caller will not be able to call further methods on self + // until the value slice reference is dropped, as we have unique access + // for the lifetime of the borrow. + unsafe { self.as_leaf_mut().vals.as_mut_slice().get_unchecked_mut(index) } } } impl<'a, K: 'a, V: 'a> NodeRef, K, V, marker::Internal> { - /// Borrows exclusive access to an element of the storage area for edge contents. + /// Borrows exclusive access to an element or slice of the node's storage area for edge contents. /// /// # Safety - /// The node has at least `idx` initialized elements. - unsafe fn edge_area_mut_at(&mut self, idx: usize) -> &mut MaybeUninit> { - debug_assert!(idx <= self.len()); - unsafe { self.as_internal_mut().edges.get_unchecked_mut(idx) } + /// `index` is in bounds of 0..CAPACITY + 1 + unsafe fn edge_area_mut_at(&mut self, index: I) -> &mut Output + where + I: SliceIndex<[MaybeUninit>], Output = Output>, + { + // SAFETY: the caller will not be able to call further methods on self + // until the edge slice reference is dropped, as we have unique access + // for the lifetime of the borrow. + unsafe { self.as_internal_mut().edges.as_mut_slice().get_unchecked_mut(index) } } } @@ -559,37 +575,6 @@ impl<'a, K: 'a, V: 'a> NodeRef, K, V, marker::Internal> { } } -impl<'a, K: 'a, V: 'a, Type> NodeRef, K, V, Type> { - /// Borrows exclusive access to a sized slice of key storage area in the node. - unsafe fn key_area_slice(&mut self) -> &mut [MaybeUninit] { - let len = self.len(); - // SAFETY: the caller will not be able to call further methods on self - // until the key slice reference is dropped, as we have unique access - // for the lifetime of the borrow. - unsafe { self.as_leaf_mut().keys.get_unchecked_mut(..len) } - } - - /// Borrows exclusive access to a sized slice of value storage area in the node. - unsafe fn val_area_slice(&mut self) -> &mut [MaybeUninit] { - let len = self.len(); - // SAFETY: the caller will not be able to call further methods on self - // until the value slice reference is dropped, as we have unique access - // for the lifetime of the borrow. - unsafe { self.as_leaf_mut().vals.get_unchecked_mut(..len) } - } -} - -impl<'a, K: 'a, V: 'a> NodeRef, K, V, marker::Internal> { - /// Borrows exclusive access to a sized slice of storage area for edge contents in the node. - unsafe fn edge_area_slice(&mut self) -> &mut [MaybeUninit>] { - let len = self.len(); - // SAFETY: the caller will not be able to call further methods on self - // until the edge slice reference is dropped, as we have unique access - // for the lifetime of the borrow. - unsafe { self.as_internal_mut().edges.get_unchecked_mut(..len + 1) } - } -} - impl<'a, K, V, Type> NodeRef, K, V, Type> { /// # Safety /// - The node has more than `idx` initialized elements. @@ -650,12 +635,12 @@ impl<'a, K: 'a, V: 'a> NodeRef, K, V, marker::Leaf> { /// Adds a key-value pair to the beginning of the node. fn push_front(&mut self, key: K, val: V) { - assert!(self.len() < CAPACITY); - + let new_len = self.len() + 1; + assert!(new_len <= CAPACITY); unsafe { - *self.len_mut() += 1; - slice_insert(self.key_area_slice(), 0, key); - slice_insert(self.val_area_slice(), 0, val); + slice_insert(self.key_area_mut_at(..new_len), 0, key); + slice_insert(self.val_area_mut_at(..new_len), 0, val); + *self.len_mut() = new_len as u16; } } } @@ -697,14 +682,15 @@ impl<'a, K: 'a, V: 'a> NodeRef, K, V, marker::Internal> { /// Adds a key-value pair, and an edge to go to the left of that pair, /// to the beginning of the node. fn push_front(&mut self, key: K, val: V, edge: Root) { + let new_len = self.len() + 1; assert!(edge.height == self.height - 1); - assert!(self.len() < CAPACITY); + assert!(new_len <= CAPACITY); unsafe { - *self.len_mut() += 1; - slice_insert(self.key_area_slice(), 0, key); - slice_insert(self.val_area_slice(), 0, val); - slice_insert(self.edge_area_slice(), 0, edge.node); + slice_insert(self.key_area_mut_at(..new_len), 0, key); + slice_insert(self.val_area_mut_at(..new_len), 0, val); + slice_insert(self.edge_area_mut_at(..new_len + 1), 0, edge.node); + *self.len_mut() = new_len as u16; } self.correct_all_childrens_parent_links(); @@ -749,12 +735,12 @@ impl<'a, K: 'a, V: 'a> NodeRef, K, V, marker::LeafOrInternal> { let old_len = self.len(); unsafe { - let key = slice_remove(self.key_area_slice(), 0); - let val = slice_remove(self.val_area_slice(), 0); + let key = slice_remove(self.key_area_mut_at(..old_len), 0); + let val = slice_remove(self.val_area_mut_at(..old_len), 0); let edge = match self.reborrow_mut().force() { ForceResult::Leaf(_) => None, ForceResult::Internal(mut internal) => { - let node = slice_remove(internal.edge_area_slice(), 0); + let node = slice_remove(internal.edge_area_mut_at(..old_len + 1), 0); let mut edge = Root { node, height: internal.height - 1, _marker: PhantomData }; // Currently, clearing the parent link is superfluous, because we will // insert the node elsewhere and set its parent link again. @@ -975,11 +961,12 @@ impl<'a, K: 'a, V: 'a> Handle, K, V, marker::Leaf>, mark /// The returned pointer points to the inserted value. fn insert_fit(&mut self, key: K, val: V) -> *mut V { debug_assert!(self.node.len() < CAPACITY); + let new_len = self.node.len() + 1; unsafe { - *self.node.len_mut() += 1; - slice_insert(self.node.key_area_slice(), self.idx, key); - slice_insert(self.node.val_area_slice(), self.idx, val); + slice_insert(self.node.key_area_mut_at(..new_len), self.idx, key); + slice_insert(self.node.val_area_mut_at(..new_len), self.idx, val); + *self.node.len_mut() = new_len as u16; self.node.val_area_mut_at(self.idx).assume_init_mut() } @@ -1033,14 +1020,15 @@ impl<'a, K: 'a, V: 'a> Handle, K, V, marker::Internal>, fn insert_fit(&mut self, key: K, val: V, edge: Root) { debug_assert!(self.node.len() < CAPACITY); debug_assert!(edge.height == self.node.height - 1); + let new_len = self.node.len() + 1; unsafe { - *self.node.len_mut() += 1; - slice_insert(self.node.key_area_slice(), self.idx, key); - slice_insert(self.node.val_area_slice(), self.idx, val); - slice_insert(self.node.edge_area_slice(), self.idx + 1, edge.node); + slice_insert(self.node.key_area_mut_at(..new_len), self.idx, key); + slice_insert(self.node.val_area_mut_at(..new_len), self.idx, val); + slice_insert(self.node.edge_area_mut_at(..new_len + 1), self.idx + 1, edge.node); + *self.node.len_mut() = new_len as u16; - self.node.correct_childrens_parent_links((self.idx + 1)..=self.node.len()); + self.node.correct_childrens_parent_links(self.idx + 1..new_len + 1); } } @@ -1177,17 +1165,11 @@ impl<'a, K: 'a, V: 'a, NodeType> Handle, K, V, NodeType> } impl<'a, K: 'a, V: 'a, NodeType> Handle, K, V, NodeType>, marker::KV> { - /// Helps implementations of `split` for a particular `NodeType`, - /// by calculating the length of the new node. - fn split_new_node_len(&self) -> usize { - debug_assert!(self.idx < self.node.len()); - self.node.len() - self.idx - 1 - } - /// Helps implementations of `split` for a particular `NodeType`, /// by taking care of leaf data. fn split_leaf_data(&mut self, new_node: &mut LeafNode) -> (K, V) { - let new_len = self.split_new_node_len(); + debug_assert!(self.idx < self.node.len()); + let new_len = self.node.len() - self.idx - 1; new_node.len = new_len as u16; unsafe { let k = ptr::read(self.node.reborrow().key_at(self.idx)); @@ -1234,10 +1216,11 @@ impl<'a, K: 'a, V: 'a> Handle, K, V, marker::Leaf>, mark pub fn remove( mut self, ) -> ((K, V), Handle, K, V, marker::Leaf>, marker::Edge>) { + let old_len = self.node.len(); unsafe { - let k = slice_remove(self.node.key_area_slice(), self.idx); - let v = slice_remove(self.node.val_area_slice(), self.idx); - *self.node.len_mut() -= 1; + let k = slice_remove(self.node.key_area_mut_at(..old_len), self.idx); + let v = slice_remove(self.node.val_area_mut_at(..old_len), self.idx); + *self.node.len_mut() = (old_len - 1) as u16; ((k, v), self.left_edge()) } } @@ -1254,14 +1237,13 @@ impl<'a, K: 'a, V: 'a> Handle, K, V, marker::Internal>, pub fn split(mut self) -> SplitResult<'a, K, V, marker::Internal> { unsafe { let mut new_node = Box::new(InternalNode::new()); - let new_len = self.split_new_node_len(); - // Move edges out before reducing length: + let kv = self.split_leaf_data(&mut new_node.data); + let new_len = usize::from(new_node.data.len); ptr::copy_nonoverlapping( self.node.reborrow().edge_area().as_ptr().add(self.idx + 1), new_node.edges.as_mut_ptr(), new_len + 1, ); - let kv = self.split_leaf_data(&mut new_node.data); let height = self.node.height; let mut right = NodeRef::from_new_internal(new_node, height); @@ -1384,23 +1366,25 @@ impl<'a, K: 'a, V: 'a> BalancingContext<'a, K, V> { unsafe { *left_node.len_mut() = new_left_len as u16; - let parent_key = slice_remove(parent_node.key_area_slice(), parent_idx); + let parent_key = + slice_remove(parent_node.key_area_mut_at(..old_parent_len), parent_idx); left_node.key_area_mut_at(old_left_len).write(parent_key); ptr::copy_nonoverlapping( right_node.reborrow().key_area().as_ptr(), - left_node.key_area_slice().as_mut_ptr().add(old_left_len + 1), + left_node.key_area_mut_at(old_left_len + 1..).as_mut_ptr(), right_len, ); - let parent_val = slice_remove(parent_node.val_area_slice(), parent_idx); + let parent_val = + slice_remove(parent_node.val_area_mut_at(..old_parent_len), parent_idx); left_node.val_area_mut_at(old_left_len).write(parent_val); ptr::copy_nonoverlapping( right_node.reborrow().val_area().as_ptr(), - left_node.val_area_slice().as_mut_ptr().add(old_left_len + 1), + left_node.val_area_mut_at(old_left_len + 1..).as_mut_ptr(), right_len, ); - slice_remove(&mut parent_node.edge_area_slice(), parent_idx + 1); + slice_remove(&mut parent_node.edge_area_mut_at(..old_parent_len + 1), parent_idx + 1); parent_node.correct_childrens_parent_links(parent_idx + 1..old_parent_len); *parent_node.len_mut() -= 1; @@ -1411,7 +1395,7 @@ impl<'a, K: 'a, V: 'a> BalancingContext<'a, K, V> { let right_node = right_node.cast_to_internal_unchecked(); ptr::copy_nonoverlapping( right_node.reborrow().edge_area().as_ptr(), - left_node.edge_area_slice().as_mut_ptr().add(old_left_len + 1), + left_node.edge_area_mut_at(old_left_len + 1..).as_mut_ptr(), right_len + 1, ); @@ -1489,6 +1473,9 @@ impl<'a, K: 'a, V: 'a> BalancingContext<'a, K, V> { assert!(old_left_len >= count); let new_left_len = old_left_len - count; + let new_right_len = old_right_len + count; + *left_node.len_mut() = new_left_len as u16; + *right_node.len_mut() = new_right_len as u16; // Move leaf data. { @@ -1513,16 +1500,13 @@ impl<'a, K: 'a, V: 'a> BalancingContext<'a, K, V> { move_kv(left_kv, new_left_len, parent_kv, 0, 1); } - *left_node.len_mut() -= count as u16; - *right_node.len_mut() += count as u16; - match (left_node.reborrow_mut().force(), right_node.reborrow_mut().force()) { (ForceResult::Internal(left), ForceResult::Internal(mut right)) => { // Make room for stolen edges. let left = left.reborrow(); - let right_edges = right.edge_area_slice().as_mut_ptr(); + let right_edges = right.edge_area_mut_at(..).as_mut_ptr(); ptr::copy(right_edges, right_edges.add(count), old_right_len + 1); - right.correct_childrens_parent_links(count..count + old_right_len + 1); + right.correct_childrens_parent_links(count..new_right_len + 1); // Steal edges. move_edges(left, new_left_len + 1, right, 0, count); @@ -1546,7 +1530,10 @@ impl<'a, K: 'a, V: 'a> BalancingContext<'a, K, V> { assert!(old_left_len + count <= CAPACITY); assert!(old_right_len >= count); + let new_left_len = old_left_len + count; let new_right_len = old_right_len - count; + *left_node.len_mut() = new_left_len as u16; + *right_node.len_mut() = new_right_len as u16; // Move leaf data. { @@ -1571,16 +1558,13 @@ impl<'a, K: 'a, V: 'a> BalancingContext<'a, K, V> { ptr::copy(right_kv.1.add(count), right_kv.1, new_right_len); } - *left_node.len_mut() += count as u16; - *right_node.len_mut() -= count as u16; - match (left_node.reborrow_mut().force(), right_node.reborrow_mut().force()) { (ForceResult::Internal(left), ForceResult::Internal(mut right)) => { // Steal edges. move_edges(right.reborrow(), 0, left, old_left_len + 1, count); // Fill gap where stolen edges used to be. - let right_edges = right.edge_area_slice().as_mut_ptr(); + let right_edges = right.edge_area_mut_at(..).as_mut_ptr(); ptr::copy(right_edges.add(count), right_edges, new_right_len + 1); right.correct_childrens_parent_links(0..=new_right_len); } @@ -1614,8 +1598,8 @@ unsafe fn move_edges<'a, K: 'a, V: 'a>( ) { unsafe { let source_ptr = source.edge_area().as_ptr(); - let dest_ptr = dest.edge_area_slice().as_mut_ptr(); - ptr::copy_nonoverlapping(source_ptr.add(source_offset), dest_ptr.add(dest_offset), count); + let dest_ptr = dest.edge_area_mut_at(dest_offset..).as_mut_ptr(); + ptr::copy_nonoverlapping(source_ptr.add(source_offset), dest_ptr, count); dest.correct_childrens_parent_links(dest_offset..dest_offset + count); } } -- cgit 1.4.1-3-g733a5 From 9e618bacf2c060d19d7dfbdb04c332b81cf56839 Mon Sep 17 00:00:00 2001 From: Stein Somers Date: Wed, 18 Nov 2020 18:19:38 +0100 Subject: BTreeMap: make test cases more explicit on failure --- library/alloc/src/collections/btree/map/tests.rs | 2 +- library/alloc/src/collections/btree/node/tests.rs | 12 ++++++++---- 2 files changed, 9 insertions(+), 5 deletions(-) (limited to 'library/alloc/src') diff --git a/library/alloc/src/collections/btree/map/tests.rs b/library/alloc/src/collections/btree/map/tests.rs index 97df8ea07d2..c857d4317e4 100644 --- a/library/alloc/src/collections/btree/map/tests.rs +++ b/library/alloc/src/collections/btree/map/tests.rs @@ -115,7 +115,7 @@ impl BTreeMap { impl<'a, K: 'a, V: 'a> NodeRef, K, V, marker::LeafOrInternal> { fn assert_min_len(self, min_len: usize) { - assert!(self.len() >= min_len, "{} < {}", self.len(), min_len); + assert!(self.len() >= min_len, "node len {} < {}", self.len(), min_len); if let node::ForceResult::Internal(node) = self.force() { for idx in 0..=node.len() { let edge = unsafe { Handle::new_edge(node, idx) }; diff --git a/library/alloc/src/collections/btree/node/tests.rs b/library/alloc/src/collections/btree/node/tests.rs index 6886962106b..7fe8ff743c0 100644 --- a/library/alloc/src/collections/btree/node/tests.rs +++ b/library/alloc/src/collections/btree/node/tests.rs @@ -30,11 +30,15 @@ impl<'a, K: 'a, V: 'a> NodeRef, K, V, marker::LeafOrInternal> let depth = self.height(); let indent = " ".repeat(depth); result += &format!("\n{}", indent); - for idx in 0..leaf.len() { - if idx > 0 { - result += ", "; + if leaf.len() == 0 { + result += "(empty node)"; + } else { + for idx in 0..leaf.len() { + if idx > 0 { + result += ", "; + } + result += &format!("{:?}", unsafe { leaf.key_at(idx) }); } - result += &format!("{:?}", unsafe { leaf.key_at(idx) }); } } navigate::Position::Internal(_) => {} -- cgit 1.4.1-3-g733a5 From d473cbe75b50dd583b582d0e99ba0c17228c1f86 Mon Sep 17 00:00:00 2001 From: Stein Somers Date: Wed, 18 Nov 2020 18:19:38 +0100 Subject: BTreeMap: test split_off (and append) more thoroughly --- library/alloc/src/collections/btree/append.rs | 9 ++++++--- library/alloc/src/collections/btree/map/tests.rs | 20 +++++++++++++++++++- library/alloc/src/collections/btree/mod.rs | 7 +++++-- library/alloc/src/collections/btree/set/tests.rs | 4 +++- library/alloc/src/collections/btree/split.rs | 5 +++++ 5 files changed, 38 insertions(+), 7 deletions(-) (limited to 'library/alloc/src') diff --git a/library/alloc/src/collections/btree/append.rs b/library/alloc/src/collections/btree/append.rs index bd99c4ed2f1..9c0ffee84fd 100644 --- a/library/alloc/src/collections/btree/append.rs +++ b/library/alloc/src/collections/btree/append.rs @@ -81,15 +81,18 @@ impl Root { // the appended elements even if advancing the iterator panicks. *length += 1; } - self.fix_right_edge(); + self.fix_right_border_of_plentiful(); } - fn fix_right_edge(&mut self) { - // Handle underfull nodes, start from the top. + /// Stock up any underfull nodes on the right border of the tree. + /// The other nodes, those that are not the root nor a rightmost edge, + /// must have MIN_LEN elements to spare. + fn fix_right_border_of_plentiful(&mut self) { let mut cur_node = self.borrow_mut(); while let Internal(internal) = cur_node.force() { // Check if right-most child is underfull. let mut last_kv = internal.last_kv().consider_for_balancing(); + debug_assert!(last_kv.left_child_len() >= MIN_LEN * 2); let right_child_len = last_kv.right_child_len(); if right_child_len < MIN_LEN { // We need to steal. diff --git a/library/alloc/src/collections/btree/map/tests.rs b/library/alloc/src/collections/btree/map/tests.rs index 97df8ea07d2..924ab378291 100644 --- a/library/alloc/src/collections/btree/map/tests.rs +++ b/library/alloc/src/collections/btree/map/tests.rs @@ -1797,7 +1797,6 @@ fn test_append_ord_chaos() { } fn rand_data(len: usize) -> Vec<(u32, u32)> { - assert!(len * 2 <= 70029); // from that point on numbers repeat let mut rng = DeterministicRng::new(); Vec::from_iter((0..len).map(|_| (rng.next(), rng.next()))) } @@ -1862,6 +1861,25 @@ fn test_split_off_tiny_right_height_2() { assert_eq!(*right.last_key_value().unwrap().0, last); } +#[test] +fn test_split_off_halfway() { + let mut rng = DeterministicRng::new(); + for &len in &[NODE_CAPACITY, 25, 50, 75, 100] { + let mut data = Vec::from_iter((0..len).map(|_| (rng.next(), ()))); + // Insertion in non-ascending order creates some variation in node length. + let mut map = BTreeMap::from_iter(data.iter().copied()); + data.sort(); + let small_keys = data.iter().take(len / 2).map(|kv| kv.0); + let large_keys = data.iter().skip(len / 2).map(|kv| kv.0); + let split_key = large_keys.clone().next().unwrap(); + let right = map.split_off(&split_key); + map.check(); + right.check(); + assert!(map.keys().copied().eq(small_keys)); + assert!(right.keys().copied().eq(large_keys)); + } +} + #[test] fn test_split_off_large_random_sorted() { // Miri is too slow diff --git a/library/alloc/src/collections/btree/mod.rs b/library/alloc/src/collections/btree/mod.rs index ebcbb0e467c..cdb39104047 100644 --- a/library/alloc/src/collections/btree/mod.rs +++ b/library/alloc/src/collections/btree/mod.rs @@ -38,6 +38,7 @@ pub unsafe fn unwrap_unchecked(val: Option) -> T { #[cfg(test)] /// XorShiftRng struct DeterministicRng { + count: usize, x: u32, y: u32, z: u32, @@ -47,11 +48,13 @@ struct DeterministicRng { #[cfg(test)] impl DeterministicRng { fn new() -> Self { - DeterministicRng { x: 0x193a6754, y: 0xa8a7d469, z: 0x97830e05, w: 0x113ba7bb } + DeterministicRng { count: 0, x: 0x193a6754, y: 0xa8a7d469, z: 0x97830e05, w: 0x113ba7bb } } - /// Guarantees that the first 70029 results are unique. + /// Guarantees that each returned number is unique. fn next(&mut self) -> u32 { + self.count += 1; + assert!(self.count <= 70029); let x = self.x; let t = x ^ (x << 11); self.x = self.y; diff --git a/library/alloc/src/collections/btree/set/tests.rs b/library/alloc/src/collections/btree/set/tests.rs index 4d05bc4ebfa..fd19c0078a7 100644 --- a/library/alloc/src/collections/btree/set/tests.rs +++ b/library/alloc/src/collections/btree/set/tests.rs @@ -696,8 +696,10 @@ fn test_first_last() { assert_eq!(a.pop_last(), None); } +// Unlike the function with the same name in map/tests, returns no values. +// Which also means it returns different predetermined pseudo-random keys, +// and the test cases using this function explore slightly different trees. fn rand_data(len: usize) -> Vec { - assert!(len <= 70029); // from that point on numbers repeat let mut rng = DeterministicRng::new(); Vec::from_iter((0..len).map(|_| rng.next())) } diff --git a/library/alloc/src/collections/btree/split.rs b/library/alloc/src/collections/btree/split.rs index 6108c139bb3..4561c8eaf47 100644 --- a/library/alloc/src/collections/btree/split.rs +++ b/library/alloc/src/collections/btree/split.rs @@ -53,6 +53,9 @@ impl Root { } } + /// Stock up or merge away any underfull nodes on the right border of the + /// tree. The other nodes, those that are not the root nor a rightmost edge, + /// must already have at least MIN_LEN elements. fn fix_right_border(&mut self) { self.fix_top(); @@ -72,6 +75,7 @@ impl Root { } cur_node = last_kv.into_right_child(); } + debug_assert!(cur_node.len() > MIN_LEN); } } @@ -98,6 +102,7 @@ impl Root { } cur_node = first_kv.into_left_child(); } + debug_assert!(cur_node.len() > MIN_LEN); } } -- cgit 1.4.1-3-g733a5 From f327a352b89a571dde76e176471d12fbd8fce0dd Mon Sep 17 00:00:00 2001 From: Stein Somers Date: Wed, 18 Nov 2020 18:19:38 +0100 Subject: BTreeMap: test full nodes a little more --- library/alloc/src/collections/btree/append.rs | 2 +- library/alloc/src/collections/btree/map/tests.rs | 40 +++++++++++++++++++----- 2 files changed, 33 insertions(+), 9 deletions(-) (limited to 'library/alloc/src') diff --git a/library/alloc/src/collections/btree/append.rs b/library/alloc/src/collections/btree/append.rs index bd99c4ed2f1..9c53c84f5b2 100644 --- a/library/alloc/src/collections/btree/append.rs +++ b/library/alloc/src/collections/btree/append.rs @@ -30,7 +30,7 @@ impl Root { /// Pushes all key-value pairs to the end of the tree, incrementing a /// `length` variable along the way. The latter makes it easier for the /// caller to avoid a leak when the iterator panicks. - fn bulk_push(&mut self, iter: I, length: &mut usize) + pub fn bulk_push(&mut self, iter: I, length: &mut usize) where I: Iterator, { diff --git a/library/alloc/src/collections/btree/map/tests.rs b/library/alloc/src/collections/btree/map/tests.rs index 97df8ea07d2..565dc175393 100644 --- a/library/alloc/src/collections/btree/map/tests.rs +++ b/library/alloc/src/collections/btree/map/tests.rs @@ -111,6 +111,18 @@ impl BTreeMap { } } } + + // Transform the tree to minimize wasted space, obtaining fewer nodes that + // are mostly filled up to their capacity. The same compact tree could have + // been obtained by inserting keys in a shrewd order. + fn compact(&mut self) + where + K: Ord, + { + let iter = mem::take(self).into_iter(); + let root = BTreeMap::ensure_is_owned(&mut self.root); + root.bulk_push(iter, &mut self.length); + } } impl<'a, K: 'a, V: 'a> NodeRef, K, V, marker::LeafOrInternal> { @@ -1679,17 +1691,29 @@ fn test_first_last_entry() { } #[test] -fn test_insert_into_full_left() { - let mut map: BTreeMap<_, _> = (0..NODE_CAPACITY).map(|i| (i * 2, ())).collect(); - assert!(map.insert(NODE_CAPACITY, ()).is_none()); - map.check(); +fn test_insert_into_full_height_0() { + let size = NODE_CAPACITY; + for pos in 0..=size { + let mut map: BTreeMap<_, _> = (0..size).map(|i| (i * 2 + 1, ())).collect(); + assert!(map.insert(pos * 2, ()).is_none()); + map.check(); + } } #[test] -fn test_insert_into_full_right() { - let mut map: BTreeMap<_, _> = (0..NODE_CAPACITY).map(|i| (i * 2, ())).collect(); - assert!(map.insert(NODE_CAPACITY + 2, ()).is_none()); - map.check(); +fn test_insert_into_full_height_1() { + let size = NODE_CAPACITY + 1 + NODE_CAPACITY; + for pos in 0..=size { + let mut map: BTreeMap<_, _> = (0..size).map(|i| (i * 2 + 1, ())).collect(); + map.compact(); + let root_node = map.root.as_ref().unwrap().reborrow(); + assert_eq!(root_node.len(), 1); + assert_eq!(root_node.first_leaf_edge().into_node().len(), NODE_CAPACITY); + assert_eq!(root_node.last_leaf_edge().into_node().len(), NODE_CAPACITY); + + assert!(map.insert(pos * 2, ()).is_none()); + map.check(); + } } macro_rules! create_append_test { -- cgit 1.4.1-3-g733a5 From 0d2548a173359da5075585e1f5ccb678d87ad24b Mon Sep 17 00:00:00 2001 From: Stein Somers Date: Mon, 23 Nov 2020 14:41:53 +0100 Subject: BTreeMap: declare exclusive access to arrays when copying from them --- library/alloc/src/collections/btree/node.rs | 81 ++++++----------------------- 1 file changed, 17 insertions(+), 64 deletions(-) (limited to 'library/alloc/src') diff --git a/library/alloc/src/collections/btree/node.rs b/library/alloc/src/collections/btree/node.rs index 769383515b7..16b4b1091ef 100644 --- a/library/alloc/src/collections/btree/node.rs +++ b/library/alloc/src/collections/btree/node.rs @@ -295,15 +295,6 @@ impl NodeRef { } } -impl<'a, K, V> NodeRef, K, V, marker::Internal> { - /// Exposes the data of an internal node in an immutable tree. - fn as_internal(this: &Self) -> &'a InternalNode { - let ptr = Self::as_internal_ptr(this); - // SAFETY: there can be no mutable references into this tree borrowed as `Immut`. - unsafe { &*ptr } - } -} - impl<'a, K, V> NodeRef, K, V, marker::Internal> { /// Borrows exclusive access to the data of an internal node. fn as_internal_mut(&mut self) -> &mut InternalNode { @@ -368,17 +359,6 @@ impl<'a, K: 'a, V: 'a, Type> NodeRef, K, V, Type> { } } -impl<'a, K, V> NodeRef, K, V, marker::Internal> { - /// Exposes the contents of one of the edges in the node. - /// - /// # Safety - /// The node has more than `idx` initialized elements. - unsafe fn edge_at(self, idx: usize) -> &'a BoxedNode { - debug_assert!(idx <= self.len()); - unsafe { Self::as_internal(&self).edges.get_unchecked(idx).assume_init_ref() } - } -} - impl NodeRef { /// Finds the parent of the current node. Returns `Ok(handle)` if the current /// node actually has a parent, where `handle` points to the edge of the parent @@ -550,31 +530,6 @@ impl<'a, K: 'a, V: 'a> NodeRef, K, V, marker::Internal> { } } -impl<'a, K: 'a, V: 'a, Type> NodeRef, K, V, Type> { - /// Exposes the entire key storage area in the node, - /// regardless of the node's current length, - /// having exclusive access to the entire node. - unsafe fn key_area(self) -> &'a [MaybeUninit] { - self.into_leaf().keys.as_slice() - } - - /// Exposes the entire value storage area in the node, - /// regardless of the node's current length, - /// having exclusive access to the entire node. - unsafe fn val_area(self) -> &'a [MaybeUninit] { - self.into_leaf().vals.as_slice() - } -} - -impl<'a, K: 'a, V: 'a> NodeRef, K, V, marker::Internal> { - /// Exposes the entire storage area for edge contents in the node, - /// regardless of the node's current length, - /// having exclusive access to the entire node. - unsafe fn edge_area(self) -> &'a [MaybeUninit>] { - Self::as_internal(&self).edges.as_slice() - } -} - impl<'a, K, V, Type> NodeRef, K, V, Type> { /// # Safety /// - The node has more than `idx` initialized elements. @@ -707,12 +662,12 @@ impl<'a, K: 'a, V: 'a> NodeRef, K, V, marker::LeafOrInternal> { let idx = self.len() - 1; unsafe { - let key = ptr::read(self.reborrow().key_at(idx)); - let val = ptr::read(self.reborrow().val_at(idx)); + let key = self.key_area_mut_at(idx).assume_init_read(); + let val = self.val_area_mut_at(idx).assume_init_read(); let edge = match self.reborrow_mut().force() { ForceResult::Leaf(_) => None, - ForceResult::Internal(internal) => { - let node = ptr::read(internal.reborrow().edge_at(idx + 1)); + ForceResult::Internal(mut internal) => { + let node = internal.edge_area_mut_at(idx + 1).assume_init_read(); let mut edge = Root { node, height: internal.height - 1, _marker: PhantomData }; // Currently, clearing the parent link is superfluous, because we will // insert the node elsewhere and set its parent link again. @@ -1172,16 +1127,16 @@ impl<'a, K: 'a, V: 'a, NodeType> Handle, K, V, NodeType> let new_len = self.node.len() - self.idx - 1; new_node.len = new_len as u16; unsafe { - let k = ptr::read(self.node.reborrow().key_at(self.idx)); - let v = ptr::read(self.node.reborrow().val_at(self.idx)); + let k = self.node.key_area_mut_at(self.idx).assume_init_read(); + let v = self.node.val_area_mut_at(self.idx).assume_init_read(); ptr::copy_nonoverlapping( - self.node.reborrow().key_area().as_ptr().add(self.idx + 1), + self.node.key_area_mut_at(self.idx + 1..).as_ptr(), new_node.keys.as_mut_ptr(), new_len, ); ptr::copy_nonoverlapping( - self.node.reborrow().val_area().as_ptr().add(self.idx + 1), + self.node.val_area_mut_at(self.idx + 1..).as_ptr(), new_node.vals.as_mut_ptr(), new_len, ); @@ -1240,7 +1195,7 @@ impl<'a, K: 'a, V: 'a> Handle, K, V, marker::Internal>, let kv = self.split_leaf_data(&mut new_node.data); let new_len = usize::from(new_node.data.len); ptr::copy_nonoverlapping( - self.node.reborrow().edge_area().as_ptr().add(self.idx + 1), + self.node.edge_area_mut_at(self.idx + 1..).as_ptr(), new_node.edges.as_mut_ptr(), new_len + 1, ); @@ -1352,7 +1307,7 @@ impl<'a, K: 'a, V: 'a> BalancingContext<'a, K, V> { let old_parent_len = parent_node.len(); let mut left_node = self.left_child; let old_left_len = left_node.len(); - let right_node = self.right_child; + let mut right_node = self.right_child; let right_len = right_node.len(); let new_left_len = old_left_len + 1 + right_len; @@ -1370,7 +1325,7 @@ impl<'a, K: 'a, V: 'a> BalancingContext<'a, K, V> { slice_remove(parent_node.key_area_mut_at(..old_parent_len), parent_idx); left_node.key_area_mut_at(old_left_len).write(parent_key); ptr::copy_nonoverlapping( - right_node.reborrow().key_area().as_ptr(), + right_node.key_area_mut_at(..).as_ptr(), left_node.key_area_mut_at(old_left_len + 1..).as_mut_ptr(), right_len, ); @@ -1379,7 +1334,7 @@ impl<'a, K: 'a, V: 'a> BalancingContext<'a, K, V> { slice_remove(parent_node.val_area_mut_at(..old_parent_len), parent_idx); left_node.val_area_mut_at(old_left_len).write(parent_val); ptr::copy_nonoverlapping( - right_node.reborrow().val_area().as_ptr(), + right_node.val_area_mut_at(..).as_ptr(), left_node.val_area_mut_at(old_left_len + 1..).as_mut_ptr(), right_len, ); @@ -1392,9 +1347,9 @@ impl<'a, K: 'a, V: 'a> BalancingContext<'a, K, V> { // SAFETY: the height of the nodes being merged is one below the height // of the node of this edge, thus above zero, so they are internal. let mut left_node = left_node.reborrow_mut().cast_to_internal_unchecked(); - let right_node = right_node.cast_to_internal_unchecked(); + let mut right_node = right_node.cast_to_internal_unchecked(); ptr::copy_nonoverlapping( - right_node.reborrow().edge_area().as_ptr(), + right_node.edge_area_mut_at(..).as_ptr(), left_node.edge_area_mut_at(old_left_len + 1..).as_mut_ptr(), right_len + 1, ); @@ -1503,7 +1458,6 @@ impl<'a, K: 'a, V: 'a> BalancingContext<'a, K, V> { match (left_node.reborrow_mut().force(), right_node.reborrow_mut().force()) { (ForceResult::Internal(left), ForceResult::Internal(mut right)) => { // Make room for stolen edges. - let left = left.reborrow(); let right_edges = right.edge_area_mut_at(..).as_mut_ptr(); ptr::copy(right_edges, right_edges.add(count), old_right_len + 1); right.correct_childrens_parent_links(count..new_right_len + 1); @@ -1561,7 +1515,7 @@ impl<'a, K: 'a, V: 'a> BalancingContext<'a, K, V> { match (left_node.reborrow_mut().force(), right_node.reborrow_mut().force()) { (ForceResult::Internal(left), ForceResult::Internal(mut right)) => { // Steal edges. - move_edges(right.reborrow(), 0, left, old_left_len + 1, count); + move_edges(right.reborrow_mut(), 0, left, old_left_len + 1, count); // Fill gap where stolen edges used to be. let right_edges = right.edge_area_mut_at(..).as_mut_ptr(); @@ -1590,14 +1544,14 @@ unsafe fn move_kv( // Source and destination must have the same height. unsafe fn move_edges<'a, K: 'a, V: 'a>( - source: NodeRef, K, V, marker::Internal>, + mut source: NodeRef, K, V, marker::Internal>, source_offset: usize, mut dest: NodeRef, K, V, marker::Internal>, dest_offset: usize, count: usize, ) { unsafe { - let source_ptr = source.edge_area().as_ptr(); + let source_ptr = source.edge_area_mut_at(..).as_ptr(); let dest_ptr = dest.edge_area_mut_at(dest_offset..).as_mut_ptr(); ptr::copy_nonoverlapping(source_ptr.add(source_offset), dest_ptr, count); dest.correct_childrens_parent_links(dest_offset..dest_offset + count); @@ -1699,7 +1653,6 @@ impl<'a, K, V> Handle, K, V, marker::LeafOrInternal>, ma match (left_node.force(), right_node.force()) { (ForceResult::Internal(left), ForceResult::Internal(right)) => { - let left = left.reborrow(); move_edges(left, new_left_len + 1, right, 1, new_right_len); } (ForceResult::Leaf(_), ForceResult::Leaf(_)) => {} -- cgit 1.4.1-3-g733a5 From be3a5a1beccaebdae7deb46870eb4e711464c738 Mon Sep 17 00:00:00 2001 From: Stein Somers Date: Thu, 17 Dec 2020 20:58:25 +0100 Subject: BTreeMap: rename the area access methods --- library/alloc/src/collections/btree/node.rs | 98 ++++++++++++++--------------- 1 file changed, 48 insertions(+), 50 deletions(-) (limited to 'library/alloc/src') diff --git a/library/alloc/src/collections/btree/node.rs b/library/alloc/src/collections/btree/node.rs index 16b4b1091ef..b3641a7a0c6 100644 --- a/library/alloc/src/collections/btree/node.rs +++ b/library/alloc/src/collections/btree/node.rs @@ -489,7 +489,7 @@ impl<'a, K: 'a, V: 'a, Type> NodeRef, K, V, Type> { /// /// # Safety /// `index` is in bounds of 0..CAPACITY - unsafe fn key_area_mut_at(&mut self, index: I) -> &mut Output + unsafe fn key_area_mut(&mut self, index: I) -> &mut Output where I: SliceIndex<[MaybeUninit], Output = Output>, { @@ -503,7 +503,7 @@ impl<'a, K: 'a, V: 'a, Type> NodeRef, K, V, Type> { /// /// # Safety /// `index` is in bounds of 0..CAPACITY - unsafe fn val_area_mut_at(&mut self, index: I) -> &mut Output + unsafe fn val_area_mut(&mut self, index: I) -> &mut Output where I: SliceIndex<[MaybeUninit], Output = Output>, { @@ -519,7 +519,7 @@ impl<'a, K: 'a, V: 'a> NodeRef, K, V, marker::Internal> { /// /// # Safety /// `index` is in bounds of 0..CAPACITY + 1 - unsafe fn edge_area_mut_at(&mut self, index: I) -> &mut Output + unsafe fn edge_area_mut(&mut self, index: I) -> &mut Output where I: SliceIndex<[MaybeUninit>], Output = Output>, { @@ -583,8 +583,8 @@ impl<'a, K: 'a, V: 'a> NodeRef, K, V, marker::Leaf> { assert!(idx < CAPACITY); *len += 1; unsafe { - self.key_area_mut_at(idx).write(key); - self.val_area_mut_at(idx).write(val); + self.key_area_mut(idx).write(key); + self.val_area_mut(idx).write(val); } } @@ -593,8 +593,8 @@ impl<'a, K: 'a, V: 'a> NodeRef, K, V, marker::Leaf> { let new_len = self.len() + 1; assert!(new_len <= CAPACITY); unsafe { - slice_insert(self.key_area_mut_at(..new_len), 0, key); - slice_insert(self.val_area_mut_at(..new_len), 0, val); + slice_insert(self.key_area_mut(..new_len), 0, key); + slice_insert(self.val_area_mut(..new_len), 0, val); *self.len_mut() = new_len as u16; } } @@ -627,9 +627,9 @@ impl<'a, K: 'a, V: 'a> NodeRef, K, V, marker::Internal> { assert!(idx < CAPACITY); *len += 1; unsafe { - self.key_area_mut_at(idx).write(key); - self.val_area_mut_at(idx).write(val); - self.edge_area_mut_at(idx + 1).write(edge.node); + self.key_area_mut(idx).write(key); + self.val_area_mut(idx).write(val); + self.edge_area_mut(idx + 1).write(edge.node); Handle::new_edge(self.reborrow_mut(), idx + 1).correct_parent_link(); } } @@ -642,9 +642,9 @@ impl<'a, K: 'a, V: 'a> NodeRef, K, V, marker::Internal> { assert!(new_len <= CAPACITY); unsafe { - slice_insert(self.key_area_mut_at(..new_len), 0, key); - slice_insert(self.val_area_mut_at(..new_len), 0, val); - slice_insert(self.edge_area_mut_at(..new_len + 1), 0, edge.node); + slice_insert(self.key_area_mut(..new_len), 0, key); + slice_insert(self.val_area_mut(..new_len), 0, val); + slice_insert(self.edge_area_mut(..new_len + 1), 0, edge.node); *self.len_mut() = new_len as u16; } @@ -662,12 +662,12 @@ impl<'a, K: 'a, V: 'a> NodeRef, K, V, marker::LeafOrInternal> { let idx = self.len() - 1; unsafe { - let key = self.key_area_mut_at(idx).assume_init_read(); - let val = self.val_area_mut_at(idx).assume_init_read(); + let key = self.key_area_mut(idx).assume_init_read(); + let val = self.val_area_mut(idx).assume_init_read(); let edge = match self.reborrow_mut().force() { ForceResult::Leaf(_) => None, ForceResult::Internal(mut internal) => { - let node = internal.edge_area_mut_at(idx + 1).assume_init_read(); + let node = internal.edge_area_mut(idx + 1).assume_init_read(); let mut edge = Root { node, height: internal.height - 1, _marker: PhantomData }; // Currently, clearing the parent link is superfluous, because we will // insert the node elsewhere and set its parent link again. @@ -690,12 +690,12 @@ impl<'a, K: 'a, V: 'a> NodeRef, K, V, marker::LeafOrInternal> { let old_len = self.len(); unsafe { - let key = slice_remove(self.key_area_mut_at(..old_len), 0); - let val = slice_remove(self.val_area_mut_at(..old_len), 0); + let key = slice_remove(self.key_area_mut(..old_len), 0); + let val = slice_remove(self.val_area_mut(..old_len), 0); let edge = match self.reborrow_mut().force() { ForceResult::Leaf(_) => None, ForceResult::Internal(mut internal) => { - let node = slice_remove(internal.edge_area_mut_at(..old_len + 1), 0); + let node = slice_remove(internal.edge_area_mut(..old_len + 1), 0); let mut edge = Root { node, height: internal.height - 1, _marker: PhantomData }; // Currently, clearing the parent link is superfluous, because we will // insert the node elsewhere and set its parent link again. @@ -919,11 +919,11 @@ impl<'a, K: 'a, V: 'a> Handle, K, V, marker::Leaf>, mark let new_len = self.node.len() + 1; unsafe { - slice_insert(self.node.key_area_mut_at(..new_len), self.idx, key); - slice_insert(self.node.val_area_mut_at(..new_len), self.idx, val); + slice_insert(self.node.key_area_mut(..new_len), self.idx, key); + slice_insert(self.node.val_area_mut(..new_len), self.idx, val); *self.node.len_mut() = new_len as u16; - self.node.val_area_mut_at(self.idx).assume_init_mut() + self.node.val_area_mut(self.idx).assume_init_mut() } } } @@ -978,9 +978,9 @@ impl<'a, K: 'a, V: 'a> Handle, K, V, marker::Internal>, let new_len = self.node.len() + 1; unsafe { - slice_insert(self.node.key_area_mut_at(..new_len), self.idx, key); - slice_insert(self.node.val_area_mut_at(..new_len), self.idx, val); - slice_insert(self.node.edge_area_mut_at(..new_len + 1), self.idx + 1, edge.node); + slice_insert(self.node.key_area_mut(..new_len), self.idx, key); + slice_insert(self.node.val_area_mut(..new_len), self.idx, val); + slice_insert(self.node.edge_area_mut(..new_len + 1), self.idx + 1, edge.node); *self.node.len_mut() = new_len as u16; self.node.correct_childrens_parent_links(self.idx + 1..new_len + 1); @@ -1085,7 +1085,7 @@ impl<'a, K: 'a, V: 'a, NodeType> Handle, K, V, NodeTyp impl<'a, K: 'a, V: 'a, NodeType> Handle, K, V, NodeType>, marker::KV> { pub fn key_mut(&mut self) -> &mut K { - unsafe { self.node.key_area_mut_at(self.idx).assume_init_mut() } + unsafe { self.node.key_area_mut(self.idx).assume_init_mut() } } pub fn into_val_mut(self) -> &'a mut V { @@ -1127,16 +1127,16 @@ impl<'a, K: 'a, V: 'a, NodeType> Handle, K, V, NodeType> let new_len = self.node.len() - self.idx - 1; new_node.len = new_len as u16; unsafe { - let k = self.node.key_area_mut_at(self.idx).assume_init_read(); - let v = self.node.val_area_mut_at(self.idx).assume_init_read(); + let k = self.node.key_area_mut(self.idx).assume_init_read(); + let v = self.node.val_area_mut(self.idx).assume_init_read(); ptr::copy_nonoverlapping( - self.node.key_area_mut_at(self.idx + 1..).as_ptr(), + self.node.key_area_mut(self.idx + 1..).as_ptr(), new_node.keys.as_mut_ptr(), new_len, ); ptr::copy_nonoverlapping( - self.node.val_area_mut_at(self.idx + 1..).as_ptr(), + self.node.val_area_mut(self.idx + 1..).as_ptr(), new_node.vals.as_mut_ptr(), new_len, ); @@ -1173,8 +1173,8 @@ impl<'a, K: 'a, V: 'a> Handle, K, V, marker::Leaf>, mark ) -> ((K, V), Handle, K, V, marker::Leaf>, marker::Edge>) { let old_len = self.node.len(); unsafe { - let k = slice_remove(self.node.key_area_mut_at(..old_len), self.idx); - let v = slice_remove(self.node.val_area_mut_at(..old_len), self.idx); + let k = slice_remove(self.node.key_area_mut(..old_len), self.idx); + let v = slice_remove(self.node.val_area_mut(..old_len), self.idx); *self.node.len_mut() = (old_len - 1) as u16; ((k, v), self.left_edge()) } @@ -1195,7 +1195,7 @@ impl<'a, K: 'a, V: 'a> Handle, K, V, marker::Internal>, let kv = self.split_leaf_data(&mut new_node.data); let new_len = usize::from(new_node.data.len); ptr::copy_nonoverlapping( - self.node.edge_area_mut_at(self.idx + 1..).as_ptr(), + self.node.edge_area_mut(self.idx + 1..).as_ptr(), new_node.edges.as_mut_ptr(), new_len + 1, ); @@ -1321,25 +1321,23 @@ impl<'a, K: 'a, V: 'a> BalancingContext<'a, K, V> { unsafe { *left_node.len_mut() = new_left_len as u16; - let parent_key = - slice_remove(parent_node.key_area_mut_at(..old_parent_len), parent_idx); - left_node.key_area_mut_at(old_left_len).write(parent_key); + let parent_key = slice_remove(parent_node.key_area_mut(..old_parent_len), parent_idx); + left_node.key_area_mut(old_left_len).write(parent_key); ptr::copy_nonoverlapping( - right_node.key_area_mut_at(..).as_ptr(), - left_node.key_area_mut_at(old_left_len + 1..).as_mut_ptr(), + right_node.key_area_mut(..).as_ptr(), + left_node.key_area_mut(old_left_len + 1..).as_mut_ptr(), right_len, ); - let parent_val = - slice_remove(parent_node.val_area_mut_at(..old_parent_len), parent_idx); - left_node.val_area_mut_at(old_left_len).write(parent_val); + let parent_val = slice_remove(parent_node.val_area_mut(..old_parent_len), parent_idx); + left_node.val_area_mut(old_left_len).write(parent_val); ptr::copy_nonoverlapping( - right_node.val_area_mut_at(..).as_ptr(), - left_node.val_area_mut_at(old_left_len + 1..).as_mut_ptr(), + right_node.val_area_mut(..).as_ptr(), + left_node.val_area_mut(old_left_len + 1..).as_mut_ptr(), right_len, ); - slice_remove(&mut parent_node.edge_area_mut_at(..old_parent_len + 1), parent_idx + 1); + slice_remove(&mut parent_node.edge_area_mut(..old_parent_len + 1), parent_idx + 1); parent_node.correct_childrens_parent_links(parent_idx + 1..old_parent_len); *parent_node.len_mut() -= 1; @@ -1349,8 +1347,8 @@ impl<'a, K: 'a, V: 'a> BalancingContext<'a, K, V> { let mut left_node = left_node.reborrow_mut().cast_to_internal_unchecked(); let mut right_node = right_node.cast_to_internal_unchecked(); ptr::copy_nonoverlapping( - right_node.edge_area_mut_at(..).as_ptr(), - left_node.edge_area_mut_at(old_left_len + 1..).as_mut_ptr(), + right_node.edge_area_mut(..).as_ptr(), + left_node.edge_area_mut(old_left_len + 1..).as_mut_ptr(), right_len + 1, ); @@ -1458,7 +1456,7 @@ impl<'a, K: 'a, V: 'a> BalancingContext<'a, K, V> { match (left_node.reborrow_mut().force(), right_node.reborrow_mut().force()) { (ForceResult::Internal(left), ForceResult::Internal(mut right)) => { // Make room for stolen edges. - let right_edges = right.edge_area_mut_at(..).as_mut_ptr(); + let right_edges = right.edge_area_mut(..).as_mut_ptr(); ptr::copy(right_edges, right_edges.add(count), old_right_len + 1); right.correct_childrens_parent_links(count..new_right_len + 1); @@ -1518,7 +1516,7 @@ impl<'a, K: 'a, V: 'a> BalancingContext<'a, K, V> { move_edges(right.reborrow_mut(), 0, left, old_left_len + 1, count); // Fill gap where stolen edges used to be. - let right_edges = right.edge_area_mut_at(..).as_mut_ptr(); + let right_edges = right.edge_area_mut(..).as_mut_ptr(); ptr::copy(right_edges.add(count), right_edges, new_right_len + 1); right.correct_childrens_parent_links(0..=new_right_len); } @@ -1551,8 +1549,8 @@ unsafe fn move_edges<'a, K: 'a, V: 'a>( count: usize, ) { unsafe { - let source_ptr = source.edge_area_mut_at(..).as_ptr(); - let dest_ptr = dest.edge_area_mut_at(dest_offset..).as_mut_ptr(); + let source_ptr = source.edge_area_mut(..).as_ptr(); + let dest_ptr = dest.edge_area_mut(dest_offset..).as_mut_ptr(); ptr::copy_nonoverlapping(source_ptr.add(source_offset), dest_ptr, count); dest.correct_childrens_parent_links(dest_offset..dest_offset + count); } -- cgit 1.4.1-3-g733a5 From eeed3118d0a10807503346406004aa3e01ae7755 Mon Sep 17 00:00:00 2001 From: CAD97 Date: Sat, 26 Dec 2020 18:16:44 -0500 Subject: Use raw version of align_of in rc data_offset This was missed in #73845 when switching to use the raw operators. Fixes #80365 --- library/alloc/src/sync.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'library/alloc/src') diff --git a/library/alloc/src/sync.rs b/library/alloc/src/sync.rs index 9d478a302e9..38db47cdafb 100644 --- a/library/alloc/src/sync.rs +++ b/library/alloc/src/sync.rs @@ -14,7 +14,7 @@ use core::hint; use core::intrinsics::abort; use core::iter; use core::marker::{PhantomData, Unpin, Unsize}; -use core::mem::{self, align_of_val, size_of_val}; +use core::mem::{self, align_of_val_raw, size_of_val}; use core::ops::{CoerceUnsized, Deref, DispatchFromDyn, Receiver}; use core::pin::Pin; use core::ptr::{self, NonNull}; @@ -2364,7 +2364,7 @@ unsafe fn data_offset(ptr: *const T) -> isize { // Because it is `?Sized`, it will always be the last field in memory. // Note: This is a detail of the current implementation of the compiler, // and is not a guaranteed language detail. Do not rely on it outside of std. - unsafe { data_offset_align(align_of_val(&*ptr)) } + unsafe { data_offset_align(align_of_val_raw(ptr)) } } #[inline] -- cgit 1.4.1-3-g733a5 From 8e0b7f988ee4e12d79c03ed53b3b59fee534330e Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Mon, 28 Dec 2020 00:39:09 +0100 Subject: de-stabilize unsized raw ptr methods for Weak --- library/alloc/src/rc.rs | 4 +++- library/alloc/src/rc/tests.rs | 24 ------------------------ library/alloc/src/sync.rs | 4 +++- library/alloc/src/sync/tests.rs | 24 ------------------------ 4 files changed, 6 insertions(+), 50 deletions(-) (limited to 'library/alloc/src') diff --git a/library/alloc/src/rc.rs b/library/alloc/src/rc.rs index a96be57143d..73d12f0a5f4 100644 --- a/library/alloc/src/rc.rs +++ b/library/alloc/src/rc.rs @@ -1749,7 +1749,7 @@ struct WeakInner<'a> { strong: &'a Cell, } -impl Weak { +impl Weak { /// Returns a raw pointer to the object `T` pointed to by this `Weak`. /// /// The pointer is valid only if there are some strong references. The pointer may be dangling, @@ -1882,7 +1882,9 @@ impl Weak { // SAFETY: we now have recovered the original Weak pointer, so can create the Weak. Weak { ptr: unsafe { NonNull::new_unchecked(ptr) } } } +} +impl Weak { /// Attempts to upgrade the `Weak` pointer to an [`Rc`], delaying /// dropping of the inner value if successful. /// diff --git a/library/alloc/src/rc/tests.rs b/library/alloc/src/rc/tests.rs index bb5c3f4f904..2d183a8c88c 100644 --- a/library/alloc/src/rc/tests.rs +++ b/library/alloc/src/rc/tests.rs @@ -208,30 +208,6 @@ fn into_from_weak_raw() { } } -#[test] -fn test_into_from_weak_raw_unsized() { - use std::fmt::Display; - use std::string::ToString; - - let arc: Rc = Rc::from("foo"); - let weak: Weak = Rc::downgrade(&arc); - - let ptr = Weak::into_raw(weak.clone()); - let weak2 = unsafe { Weak::from_raw(ptr) }; - - assert_eq!(unsafe { &*ptr }, "foo"); - assert!(weak.ptr_eq(&weak2)); - - let arc: Rc = Rc::new(123); - let weak: Weak = Rc::downgrade(&arc); - - let ptr = Weak::into_raw(weak.clone()); - let weak2 = unsafe { Weak::from_raw(ptr) }; - - assert_eq!(unsafe { &*ptr }.to_string(), "123"); - assert!(weak.ptr_eq(&weak2)); -} - #[test] fn get_mut() { let mut x = Rc::new(3); diff --git a/library/alloc/src/sync.rs b/library/alloc/src/sync.rs index 9d478a302e9..53ba9c283ae 100644 --- a/library/alloc/src/sync.rs +++ b/library/alloc/src/sync.rs @@ -1535,7 +1535,7 @@ struct WeakInner<'a> { strong: &'a atomic::AtomicUsize, } -impl Weak { +impl Weak { /// Returns a raw pointer to the object `T` pointed to by this `Weak`. /// /// The pointer is valid only if there are some strong references. The pointer may be dangling, @@ -1668,7 +1668,9 @@ impl Weak { // SAFETY: we now have recovered the original Weak pointer, so can create the Weak. unsafe { Weak { ptr: NonNull::new_unchecked(ptr) } } } +} +impl Weak { /// Attempts to upgrade the `Weak` pointer to an [`Arc`], delaying /// dropping of the inner value if successful. /// diff --git a/library/alloc/src/sync/tests.rs b/library/alloc/src/sync/tests.rs index 77f328d48f9..e8e1e66da5e 100644 --- a/library/alloc/src/sync/tests.rs +++ b/library/alloc/src/sync/tests.rs @@ -158,30 +158,6 @@ fn into_from_weak_raw() { } } -#[test] -fn test_into_from_weak_raw_unsized() { - use std::fmt::Display; - use std::string::ToString; - - let arc: Arc = Arc::from("foo"); - let weak: Weak = Arc::downgrade(&arc); - - let ptr = Weak::into_raw(weak.clone()); - let weak2 = unsafe { Weak::from_raw(ptr) }; - - assert_eq!(unsafe { &*ptr }, "foo"); - assert!(weak.ptr_eq(&weak2)); - - let arc: Arc = Arc::new(123); - let weak: Weak = Arc::downgrade(&arc); - - let ptr = Weak::into_raw(weak.clone()); - let weak2 = unsafe { Weak::from_raw(ptr) }; - - assert_eq!(unsafe { &*ptr }.to_string(), "123"); - assert!(weak.ptr_eq(&weak2)); -} - #[test] fn test_cowarc_clone_make_mut() { let mut cow0 = Arc::new(75); -- cgit 1.4.1-3-g733a5 From 9e779986aa2aaa6d28b48020f9da8f37b95959ee Mon Sep 17 00:00:00 2001 From: Konrad Borowski Date: Mon, 28 Dec 2020 09:13:46 +0100 Subject: Add "length" as doc alias to len methods --- library/alloc/src/collections/binary_heap.rs | 1 + library/alloc/src/collections/btree/map.rs | 1 + library/alloc/src/collections/btree/set.rs | 1 + library/alloc/src/collections/linked_list.rs | 1 + library/alloc/src/collections/vec_deque/mod.rs | 1 + library/alloc/src/string.rs | 1 + library/alloc/src/vec.rs | 1 + library/core/src/iter/traits/exact_size.rs | 1 + library/core/src/slice/mod.rs | 1 + library/core/src/str/mod.rs | 1 + library/std/src/collections/hash/map.rs | 1 + library/std/src/collections/hash/set.rs | 1 + library/std/src/ffi/os_str.rs | 1 + 13 files changed, 13 insertions(+) (limited to 'library/alloc/src') diff --git a/library/alloc/src/collections/binary_heap.rs b/library/alloc/src/collections/binary_heap.rs index 97ebc12175f..76051d9e1df 100644 --- a/library/alloc/src/collections/binary_heap.rs +++ b/library/alloc/src/collections/binary_heap.rs @@ -915,6 +915,7 @@ impl BinaryHeap { /// /// assert_eq!(heap.len(), 2); /// ``` + #[doc(alias = "length")] #[stable(feature = "rust1", since = "1.0.0")] pub fn len(&self) -> usize { self.data.len() diff --git a/library/alloc/src/collections/btree/map.rs b/library/alloc/src/collections/btree/map.rs index 735213363f6..944e0e65cf7 100644 --- a/library/alloc/src/collections/btree/map.rs +++ b/library/alloc/src/collections/btree/map.rs @@ -2132,6 +2132,7 @@ impl BTreeMap { /// a.insert(1, "a"); /// assert_eq!(a.len(), 1); /// ``` + #[doc(alias = "length")] #[stable(feature = "rust1", since = "1.0.0")] #[rustc_const_unstable(feature = "const_btree_new", issue = "71835")] pub const fn len(&self) -> usize { diff --git a/library/alloc/src/collections/btree/set.rs b/library/alloc/src/collections/btree/set.rs index f63c3dd5804..c72e305a1f9 100644 --- a/library/alloc/src/collections/btree/set.rs +++ b/library/alloc/src/collections/btree/set.rs @@ -975,6 +975,7 @@ impl BTreeSet { /// v.insert(1); /// assert_eq!(v.len(), 1); /// ``` + #[doc(alias = "length")] #[stable(feature = "rust1", since = "1.0.0")] #[rustc_const_unstable(feature = "const_btree_new", issue = "71835")] pub const fn len(&self) -> usize { diff --git a/library/alloc/src/collections/linked_list.rs b/library/alloc/src/collections/linked_list.rs index 4707f129401..397e774f1a0 100644 --- a/library/alloc/src/collections/linked_list.rs +++ b/library/alloc/src/collections/linked_list.rs @@ -593,6 +593,7 @@ impl LinkedList { /// dl.push_back(3); /// assert_eq!(dl.len(), 3); /// ``` + #[doc(alias = "length")] #[inline] #[stable(feature = "rust1", since = "1.0.0")] pub fn len(&self) -> usize { diff --git a/library/alloc/src/collections/vec_deque/mod.rs b/library/alloc/src/collections/vec_deque/mod.rs index 7cf4041f292..42a1a08c6fc 100644 --- a/library/alloc/src/collections/vec_deque/mod.rs +++ b/library/alloc/src/collections/vec_deque/mod.rs @@ -1038,6 +1038,7 @@ impl VecDeque { /// v.push_back(1); /// assert_eq!(v.len(), 1); /// ``` + #[doc(alias = "length")] #[stable(feature = "rust1", since = "1.0.0")] pub fn len(&self) -> usize { count(self.tail, self.head, self.cap()) diff --git a/library/alloc/src/string.rs b/library/alloc/src/string.rs index 27b32b69502..91988928593 100644 --- a/library/alloc/src/string.rs +++ b/library/alloc/src/string.rs @@ -1388,6 +1388,7 @@ impl String { /// assert_eq!(fancy_f.len(), 4); /// assert_eq!(fancy_f.chars().count(), 3); /// ``` + #[doc(alias = "length")] #[inline] #[stable(feature = "rust1", since = "1.0.0")] pub fn len(&self) -> usize { diff --git a/library/alloc/src/vec.rs b/library/alloc/src/vec.rs index 2b08f1f3629..c9fa41138cd 100644 --- a/library/alloc/src/vec.rs +++ b/library/alloc/src/vec.rs @@ -1559,6 +1559,7 @@ impl Vec { /// let a = vec![1, 2, 3]; /// assert_eq!(a.len(), 3); /// ``` + #[doc(alias = "length")] #[inline] #[stable(feature = "rust1", since = "1.0.0")] pub fn len(&self) -> usize { diff --git a/library/core/src/iter/traits/exact_size.rs b/library/core/src/iter/traits/exact_size.rs index eadbdf45c7c..996d62e2b4a 100644 --- a/library/core/src/iter/traits/exact_size.rs +++ b/library/core/src/iter/traits/exact_size.rs @@ -91,6 +91,7 @@ pub trait ExactSizeIterator: Iterator { /// /// assert_eq!(5, five.len()); /// ``` + #[doc(alias = "length")] #[inline] #[stable(feature = "rust1", since = "1.0.0")] fn len(&self) -> usize { diff --git a/library/core/src/slice/mod.rs b/library/core/src/slice/mod.rs index f5af48e0dd2..bb1014332a1 100644 --- a/library/core/src/slice/mod.rs +++ b/library/core/src/slice/mod.rs @@ -84,6 +84,7 @@ impl [T] { /// let a = [1, 2, 3]; /// assert_eq!(a.len(), 3); /// ``` + #[doc(alias = "length")] #[stable(feature = "rust1", since = "1.0.0")] #[rustc_const_stable(feature = "const_slice_len", since = "1.32.0")] #[inline] diff --git a/library/core/src/str/mod.rs b/library/core/src/str/mod.rs index 83cf47c8c8f..ba495a1a9fb 100644 --- a/library/core/src/str/mod.rs +++ b/library/core/src/str/mod.rs @@ -138,6 +138,7 @@ impl str { /// assert_eq!("ƒoo".len(), 4); // fancy f! /// assert_eq!("ƒoo".chars().count(), 3); /// ``` + #[doc(alias = "length")] #[stable(feature = "rust1", since = "1.0.0")] #[rustc_const_stable(feature = "const_str_len", since = "1.32.0")] #[inline] diff --git a/library/std/src/collections/hash/map.rs b/library/std/src/collections/hash/map.rs index 4f24a8bb75a..0680b1fc329 100644 --- a/library/std/src/collections/hash/map.rs +++ b/library/std/src/collections/hash/map.rs @@ -448,6 +448,7 @@ impl HashMap { /// a.insert(1, "a"); /// assert_eq!(a.len(), 1); /// ``` + #[doc(alias = "length")] #[stable(feature = "rust1", since = "1.0.0")] pub fn len(&self) -> usize { self.base.len() diff --git a/library/std/src/collections/hash/set.rs b/library/std/src/collections/hash/set.rs index 27093c1a077..f49e5801c35 100644 --- a/library/std/src/collections/hash/set.rs +++ b/library/std/src/collections/hash/set.rs @@ -199,6 +199,7 @@ impl HashSet { /// v.insert(1); /// assert_eq!(v.len(), 1); /// ``` + #[doc(alias = "length")] #[inline] #[stable(feature = "rust1", since = "1.0.0")] pub fn len(&self) -> usize { diff --git a/library/std/src/ffi/os_str.rs b/library/std/src/ffi/os_str.rs index 5d93016cadb..2eef4d58507 100644 --- a/library/std/src/ffi/os_str.rs +++ b/library/std/src/ffi/os_str.rs @@ -653,6 +653,7 @@ impl OsStr { /// let os_str = OsStr::new("foo"); /// assert_eq!(os_str.len(), 3); /// ``` + #[doc(alias = "length")] #[stable(feature = "osstring_simple_functions", since = "1.9.0")] pub fn len(&self) -> usize { self.inner.inner.len() -- cgit 1.4.1-3-g733a5 From 10d6ff71e83e370d345ef43f6aaef8196727f22f Mon Sep 17 00:00:00 2001 From: Mara Bos Date: Mon, 28 Dec 2020 20:04:27 +0100 Subject: Fix stabilization version of deque_range feature. --- library/alloc/src/collections/vec_deque/mod.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'library/alloc/src') diff --git a/library/alloc/src/collections/vec_deque/mod.rs b/library/alloc/src/collections/vec_deque/mod.rs index 7cf4041f292..c27ac498472 100644 --- a/library/alloc/src/collections/vec_deque/mod.rs +++ b/library/alloc/src/collections/vec_deque/mod.rs @@ -1091,7 +1091,7 @@ impl VecDeque { /// assert_eq!(all.len(), 3); /// ``` #[inline] - #[stable(feature = "deque_range", since = "1.50.0")] + #[stable(feature = "deque_range", since = "1.51.0")] pub fn range(&self, range: R) -> Iter<'_, T> where R: RangeBounds, @@ -1130,7 +1130,7 @@ impl VecDeque { /// assert_eq!(v, vec![2, 4, 12]); /// ``` #[inline] - #[stable(feature = "deque_range", since = "1.50.0")] + #[stable(feature = "deque_range", since = "1.51.0")] pub fn range_mut(&mut self, range: R) -> IterMut<'_, T> where R: RangeBounds, -- cgit 1.4.1-3-g733a5 From 5182776c6ceded22b79adc43e275b6b02111fe5b Mon Sep 17 00:00:00 2001 From: C Date: Fri, 4 Dec 2020 23:50:05 +0000 Subject: refactor: moving vec.rs to vec/mod.rs --- library/alloc/src/vec.rs | 3725 ------------------------------------------ library/alloc/src/vec/mod.rs | 3725 ++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 3725 insertions(+), 3725 deletions(-) delete mode 100644 library/alloc/src/vec.rs create mode 100644 library/alloc/src/vec/mod.rs (limited to 'library/alloc/src') diff --git a/library/alloc/src/vec.rs b/library/alloc/src/vec.rs deleted file mode 100644 index c9fa41138cd..00000000000 --- a/library/alloc/src/vec.rs +++ /dev/null @@ -1,3725 +0,0 @@ -// ignore-tidy-filelength -//! A contiguous growable array type with heap-allocated contents, written -//! `Vec`. -//! -//! Vectors have `O(1)` indexing, amortized `O(1)` push (to the end) and -//! `O(1)` pop (from the end). -//! -//! Vectors ensure they never allocate more than `isize::MAX` bytes. -//! -//! # Examples -//! -//! You can explicitly create a [`Vec`] with [`Vec::new`]: -//! -//! ``` -//! let v: Vec = Vec::new(); -//! ``` -//! -//! ...or by using the [`vec!`] macro: -//! -//! ``` -//! let v: Vec = vec![]; -//! -//! let v = vec![1, 2, 3, 4, 5]; -//! -//! let v = vec![0; 10]; // ten zeroes -//! ``` -//! -//! You can [`push`] values onto the end of a vector (which will grow the vector -//! as needed): -//! -//! ``` -//! let mut v = vec![1, 2]; -//! -//! v.push(3); -//! ``` -//! -//! Popping values works in much the same way: -//! -//! ``` -//! let mut v = vec![1, 2]; -//! -//! let two = v.pop(); -//! ``` -//! -//! Vectors also support indexing (through the [`Index`] and [`IndexMut`] traits): -//! -//! ``` -//! let mut v = vec![1, 2, 3]; -//! let three = v[2]; -//! v[1] = v[1] + 5; -//! ``` -//! -//! [`push`]: Vec::push - -#![stable(feature = "rust1", since = "1.0.0")] - -use core::cmp::{self, Ordering}; -use core::convert::TryFrom; -use core::fmt; -use core::hash::{Hash, Hasher}; -use core::intrinsics::{arith_offset, assume}; -use core::iter::{ - FromIterator, FusedIterator, InPlaceIterable, SourceIter, TrustedLen, TrustedRandomAccess, -}; -use core::marker::PhantomData; -use core::mem::{self, ManuallyDrop, MaybeUninit}; -use core::ops::{self, Index, IndexMut, Range, RangeBounds}; -use core::ptr::{self, NonNull}; -use core::slice::{self, SliceIndex}; - -use crate::alloc::{Allocator, Global}; -use crate::borrow::{Cow, ToOwned}; -use crate::boxed::Box; -use crate::collections::TryReserveError; -use crate::raw_vec::RawVec; - -/// A contiguous growable array type, written `Vec` but pronounced 'vector'. -/// -/// # Examples -/// -/// ``` -/// let mut vec = Vec::new(); -/// vec.push(1); -/// vec.push(2); -/// -/// assert_eq!(vec.len(), 2); -/// assert_eq!(vec[0], 1); -/// -/// assert_eq!(vec.pop(), Some(2)); -/// assert_eq!(vec.len(), 1); -/// -/// vec[0] = 7; -/// assert_eq!(vec[0], 7); -/// -/// vec.extend([1, 2, 3].iter().copied()); -/// -/// for x in &vec { -/// println!("{}", x); -/// } -/// assert_eq!(vec, [7, 1, 2, 3]); -/// ``` -/// -/// The [`vec!`] macro is provided to make initialization more convenient: -/// -/// ``` -/// let mut vec = vec![1, 2, 3]; -/// vec.push(4); -/// assert_eq!(vec, [1, 2, 3, 4]); -/// ``` -/// -/// It can also initialize each element of a `Vec` with a given value. -/// This may be more efficient than performing allocation and initialization -/// in separate steps, especially when initializing a vector of zeros: -/// -/// ``` -/// let vec = vec![0; 5]; -/// assert_eq!(vec, [0, 0, 0, 0, 0]); -/// -/// // The following is equivalent, but potentially slower: -/// let mut vec = Vec::with_capacity(5); -/// vec.resize(5, 0); -/// assert_eq!(vec, [0, 0, 0, 0, 0]); -/// ``` -/// -/// For more information, see -/// [Capacity and Reallocation](#capacity-and-reallocation). -/// -/// Use a `Vec` as an efficient stack: -/// -/// ``` -/// let mut stack = Vec::new(); -/// -/// stack.push(1); -/// stack.push(2); -/// stack.push(3); -/// -/// while let Some(top) = stack.pop() { -/// // Prints 3, 2, 1 -/// println!("{}", top); -/// } -/// ``` -/// -/// # Indexing -/// -/// The `Vec` type allows to access values by index, because it implements the -/// [`Index`] trait. An example will be more explicit: -/// -/// ``` -/// let v = vec![0, 2, 4, 6]; -/// println!("{}", v[1]); // it will display '2' -/// ``` -/// -/// However be careful: if you try to access an index which isn't in the `Vec`, -/// your software will panic! You cannot do this: -/// -/// ```should_panic -/// let v = vec![0, 2, 4, 6]; -/// println!("{}", v[6]); // it will panic! -/// ``` -/// -/// Use [`get`] and [`get_mut`] if you want to check whether the index is in -/// the `Vec`. -/// -/// # Slicing -/// -/// A `Vec` can be mutable. Slices, on the other hand, are read-only objects. -/// To get a [slice], use [`&`]. Example: -/// -/// ``` -/// fn read_slice(slice: &[usize]) { -/// // ... -/// } -/// -/// let v = vec![0, 1]; -/// read_slice(&v); -/// -/// // ... and that's all! -/// // you can also do it like this: -/// let u: &[usize] = &v; -/// // or like this: -/// let u: &[_] = &v; -/// ``` -/// -/// In Rust, it's more common to pass slices as arguments rather than vectors -/// when you just want to provide read access. The same goes for [`String`] and -/// [`&str`]. -/// -/// # Capacity and reallocation -/// -/// The capacity of a vector is the amount of space allocated for any future -/// elements that will be added onto the vector. This is not to be confused with -/// the *length* of a vector, which specifies the number of actual elements -/// within the vector. If a vector's length exceeds its capacity, its capacity -/// will automatically be increased, but its elements will have to be -/// reallocated. -/// -/// For example, a vector with capacity 10 and length 0 would be an empty vector -/// with space for 10 more elements. Pushing 10 or fewer elements onto the -/// vector will not change its capacity or cause reallocation to occur. However, -/// if the vector's length is increased to 11, it will have to reallocate, which -/// can be slow. For this reason, it is recommended to use [`Vec::with_capacity`] -/// whenever possible to specify how big the vector is expected to get. -/// -/// # Guarantees -/// -/// Due to its incredibly fundamental nature, `Vec` makes a lot of guarantees -/// about its design. This ensures that it's as low-overhead as possible in -/// the general case, and can be correctly manipulated in primitive ways -/// by unsafe code. Note that these guarantees refer to an unqualified `Vec`. -/// If additional type parameters are added (e.g., to support custom allocators), -/// overriding their defaults may change the behavior. -/// -/// Most fundamentally, `Vec` is and always will be a (pointer, capacity, length) -/// triplet. No more, no less. The order of these fields is completely -/// unspecified, and you should use the appropriate methods to modify these. -/// The pointer will never be null, so this type is null-pointer-optimized. -/// -/// However, the pointer may not actually point to allocated memory. In particular, -/// if you construct a `Vec` with capacity 0 via [`Vec::new`], [`vec![]`][`vec!`], -/// [`Vec::with_capacity(0)`][`Vec::with_capacity`], or by calling [`shrink_to_fit`] -/// on an empty Vec, it will not allocate memory. Similarly, if you store zero-sized -/// types inside a `Vec`, it will not allocate space for them. *Note that in this case -/// the `Vec` may not report a [`capacity`] of 0*. `Vec` will allocate if and only -/// if [`mem::size_of::`]`() * capacity() > 0`. In general, `Vec`'s allocation -/// details are very subtle — if you intend to allocate memory using a `Vec` -/// and use it for something else (either to pass to unsafe code, or to build your -/// own memory-backed collection), be sure to deallocate this memory by using -/// `from_raw_parts` to recover the `Vec` and then dropping it. -/// -/// If a `Vec` *has* allocated memory, then the memory it points to is on the heap -/// (as defined by the allocator Rust is configured to use by default), and its -/// pointer points to [`len`] initialized, contiguous elements in order (what -/// you would see if you coerced it to a slice), followed by [`capacity`]` - -/// `[`len`] logically uninitialized, contiguous elements. -/// -/// `Vec` will never perform a "small optimization" where elements are actually -/// stored on the stack for two reasons: -/// -/// * It would make it more difficult for unsafe code to correctly manipulate -/// a `Vec`. The contents of a `Vec` wouldn't have a stable address if it were -/// only moved, and it would be more difficult to determine if a `Vec` had -/// actually allocated memory. -/// -/// * It would penalize the general case, incurring an additional branch -/// on every access. -/// -/// `Vec` will never automatically shrink itself, even if completely empty. This -/// ensures no unnecessary allocations or deallocations occur. Emptying a `Vec` -/// and then filling it back up to the same [`len`] should incur no calls to -/// the allocator. If you wish to free up unused memory, use -/// [`shrink_to_fit`]. -/// -/// [`push`] and [`insert`] will never (re)allocate if the reported capacity is -/// sufficient. [`push`] and [`insert`] *will* (re)allocate if -/// [`len`]` == `[`capacity`]. That is, the reported capacity is completely -/// accurate, and can be relied on. It can even be used to manually free the memory -/// allocated by a `Vec` if desired. Bulk insertion methods *may* reallocate, even -/// when not necessary. -/// -/// `Vec` does not guarantee any particular growth strategy when reallocating -/// when full, nor when [`reserve`] is called. The current strategy is basic -/// and it may prove desirable to use a non-constant growth factor. Whatever -/// strategy is used will of course guarantee *O*(1) amortized [`push`]. -/// -/// `vec![x; n]`, `vec![a, b, c, d]`, and -/// [`Vec::with_capacity(n)`][`Vec::with_capacity`], will all produce a `Vec` -/// with exactly the requested capacity. If [`len`]` == `[`capacity`], -/// (as is the case for the [`vec!`] macro), then a `Vec` can be converted to -/// and from a [`Box<[T]>`][owned slice] without reallocating or moving the elements. -/// -/// `Vec` will not specifically overwrite any data that is removed from it, -/// but also won't specifically preserve it. Its uninitialized memory is -/// scratch space that it may use however it wants. It will generally just do -/// whatever is most efficient or otherwise easy to implement. Do not rely on -/// removed data to be erased for security purposes. Even if you drop a `Vec`, its -/// buffer may simply be reused by another `Vec`. Even if you zero a `Vec`'s memory -/// first, that may not actually happen because the optimizer does not consider -/// this a side-effect that must be preserved. There is one case which we will -/// not break, however: using `unsafe` code to write to the excess capacity, -/// and then increasing the length to match, is always valid. -/// -/// `Vec` does not currently guarantee the order in which elements are dropped. -/// The order has changed in the past and may change again. -/// -/// [`get`]: ../../std/vec/struct.Vec.html#method.get -/// [`get_mut`]: ../../std/vec/struct.Vec.html#method.get_mut -/// [`String`]: crate::string::String -/// [`&str`]: type@str -/// [`shrink_to_fit`]: Vec::shrink_to_fit -/// [`capacity`]: Vec::capacity -/// [`mem::size_of::`]: core::mem::size_of -/// [`len`]: Vec::len -/// [`push`]: Vec::push -/// [`insert`]: Vec::insert -/// [`reserve`]: Vec::reserve -/// [owned slice]: Box -/// [slice]: ../../std/primitive.slice.html -/// [`&`]: ../../std/primitive.reference.html -#[stable(feature = "rust1", since = "1.0.0")] -#[cfg_attr(not(test), rustc_diagnostic_item = "vec_type")] -pub struct Vec { - buf: RawVec, - len: usize, -} - -//////////////////////////////////////////////////////////////////////////////// -// Inherent methods -//////////////////////////////////////////////////////////////////////////////// - -impl Vec { - /// Constructs a new, empty `Vec`. - /// - /// The vector will not allocate until elements are pushed onto it. - /// - /// # Examples - /// - /// ``` - /// # #![allow(unused_mut)] - /// let mut vec: Vec = Vec::new(); - /// ``` - #[inline] - #[rustc_const_stable(feature = "const_vec_new", since = "1.39.0")] - #[stable(feature = "rust1", since = "1.0.0")] - pub const fn new() -> Self { - Vec { buf: RawVec::NEW, len: 0 } - } - - /// Constructs a new, empty `Vec` with the specified capacity. - /// - /// The vector will be able to hold exactly `capacity` elements without - /// reallocating. If `capacity` is 0, the vector will not allocate. - /// - /// It is important to note that although the returned vector has the - /// *capacity* specified, the vector will have a zero *length*. For an - /// explanation of the difference between length and capacity, see - /// *[Capacity and reallocation]*. - /// - /// [Capacity and reallocation]: #capacity-and-reallocation - /// - /// # Examples - /// - /// ``` - /// let mut vec = Vec::with_capacity(10); - /// - /// // The vector contains no items, even though it has capacity for more - /// assert_eq!(vec.len(), 0); - /// assert_eq!(vec.capacity(), 10); - /// - /// // These are all done without reallocating... - /// for i in 0..10 { - /// vec.push(i); - /// } - /// assert_eq!(vec.len(), 10); - /// assert_eq!(vec.capacity(), 10); - /// - /// // ...but this may make the vector reallocate - /// vec.push(11); - /// assert_eq!(vec.len(), 11); - /// assert!(vec.capacity() >= 11); - /// ``` - #[inline] - #[stable(feature = "rust1", since = "1.0.0")] - pub fn with_capacity(capacity: usize) -> Self { - Self::with_capacity_in(capacity, Global) - } - - /// Creates a `Vec` directly from the raw components of another vector. - /// - /// # Safety - /// - /// This is highly unsafe, due to the number of invariants that aren't - /// checked: - /// - /// * `ptr` needs to have been previously allocated via [`String`]/`Vec` - /// (at least, it's highly likely to be incorrect if it wasn't). - /// * `T` needs to have the same size and alignment as what `ptr` was allocated with. - /// (`T` having a less strict alignment is not sufficient, the alignment really - /// needs to be equal to satisfy the [`dealloc`] requirement that memory must be - /// allocated and deallocated with the same layout.) - /// * `length` needs to be less than or equal to `capacity`. - /// * `capacity` needs to be the capacity that the pointer was allocated with. - /// - /// Violating these may cause problems like corrupting the allocator's - /// internal data structures. For example it is **not** safe - /// to build a `Vec` from a pointer to a C `char` array with length `size_t`. - /// It's also not safe to build one from a `Vec` and its length, because - /// the allocator cares about the alignment, and these two types have different - /// alignments. The buffer was allocated with alignment 2 (for `u16`), but after - /// turning it into a `Vec` it'll be deallocated with alignment 1. - /// - /// The ownership of `ptr` is effectively transferred to the - /// `Vec` which may then deallocate, reallocate or change the - /// contents of memory pointed to by the pointer at will. Ensure - /// that nothing else uses the pointer after calling this - /// function. - /// - /// [`String`]: crate::string::String - /// [`dealloc`]: crate::alloc::GlobalAlloc::dealloc - /// - /// # Examples - /// - /// ``` - /// use std::ptr; - /// use std::mem; - /// - /// let v = vec![1, 2, 3]; - /// - // FIXME Update this when vec_into_raw_parts is stabilized - /// // Prevent running `v`'s destructor so we are in complete control - /// // of the allocation. - /// let mut v = mem::ManuallyDrop::new(v); - /// - /// // Pull out the various important pieces of information about `v` - /// let p = v.as_mut_ptr(); - /// let len = v.len(); - /// let cap = v.capacity(); - /// - /// unsafe { - /// // Overwrite memory with 4, 5, 6 - /// for i in 0..len as isize { - /// ptr::write(p.offset(i), 4 + i); - /// } - /// - /// // Put everything back together into a Vec - /// let rebuilt = Vec::from_raw_parts(p, len, cap); - /// assert_eq!(rebuilt, [4, 5, 6]); - /// } - /// ``` - #[inline] - #[stable(feature = "rust1", since = "1.0.0")] - pub unsafe fn from_raw_parts(ptr: *mut T, length: usize, capacity: usize) -> Self { - unsafe { Self::from_raw_parts_in(ptr, length, capacity, Global) } - } -} - -impl Vec { - /// Constructs a new, empty `Vec`. - /// - /// The vector will not allocate until elements are pushed onto it. - /// - /// # Examples - /// - /// ``` - /// #![feature(allocator_api)] - /// - /// use std::alloc::System; - /// - /// # #[allow(unused_mut)] - /// let mut vec: Vec = Vec::new_in(System); - /// ``` - #[inline] - #[unstable(feature = "allocator_api", issue = "32838")] - pub const fn new_in(alloc: A) -> Self { - Vec { buf: RawVec::new_in(alloc), len: 0 } - } - - /// Constructs a new, empty `Vec` with the specified capacity with the provided - /// allocator. - /// - /// The vector will be able to hold exactly `capacity` elements without - /// reallocating. If `capacity` is 0, the vector will not allocate. - /// - /// It is important to note that although the returned vector has the - /// *capacity* specified, the vector will have a zero *length*. For an - /// explanation of the difference between length and capacity, see - /// *[Capacity and reallocation]*. - /// - /// [Capacity and reallocation]: #capacity-and-reallocation - /// - /// # Examples - /// - /// ``` - /// #![feature(allocator_api)] - /// - /// use std::alloc::System; - /// - /// let mut vec = Vec::with_capacity_in(10, System); - /// - /// // The vector contains no items, even though it has capacity for more - /// assert_eq!(vec.len(), 0); - /// assert_eq!(vec.capacity(), 10); - /// - /// // These are all done without reallocating... - /// for i in 0..10 { - /// vec.push(i); - /// } - /// assert_eq!(vec.len(), 10); - /// assert_eq!(vec.capacity(), 10); - /// - /// // ...but this may make the vector reallocate - /// vec.push(11); - /// assert_eq!(vec.len(), 11); - /// assert!(vec.capacity() >= 11); - /// ``` - #[inline] - #[unstable(feature = "allocator_api", issue = "32838")] - pub fn with_capacity_in(capacity: usize, alloc: A) -> Self { - Vec { buf: RawVec::with_capacity_in(capacity, alloc), len: 0 } - } - - /// Creates a `Vec` directly from the raw components of another vector. - /// - /// # Safety - /// - /// This is highly unsafe, due to the number of invariants that aren't - /// checked: - /// - /// * `ptr` needs to have been previously allocated via [`String`]/`Vec` - /// (at least, it's highly likely to be incorrect if it wasn't). - /// * `T` needs to have the same size and alignment as what `ptr` was allocated with. - /// (`T` having a less strict alignment is not sufficient, the alignment really - /// needs to be equal to satisfy the [`dealloc`] requirement that memory must be - /// allocated and deallocated with the same layout.) - /// * `length` needs to be less than or equal to `capacity`. - /// * `capacity` needs to be the capacity that the pointer was allocated with. - /// - /// Violating these may cause problems like corrupting the allocator's - /// internal data structures. For example it is **not** safe - /// to build a `Vec` from a pointer to a C `char` array with length `size_t`. - /// It's also not safe to build one from a `Vec` and its length, because - /// the allocator cares about the alignment, and these two types have different - /// alignments. The buffer was allocated with alignment 2 (for `u16`), but after - /// turning it into a `Vec` it'll be deallocated with alignment 1. - /// - /// The ownership of `ptr` is effectively transferred to the - /// `Vec` which may then deallocate, reallocate or change the - /// contents of memory pointed to by the pointer at will. Ensure - /// that nothing else uses the pointer after calling this - /// function. - /// - /// [`String`]: crate::string::String - /// [`dealloc`]: crate::alloc::GlobalAlloc::dealloc - /// - /// # Examples - /// - /// ``` - /// #![feature(allocator_api)] - /// - /// use std::alloc::System; - /// - /// use std::ptr; - /// use std::mem; - /// - /// let mut v = Vec::with_capacity_in(3, System); - /// v.push(1); - /// v.push(2); - /// v.push(3); - /// - // FIXME Update this when vec_into_raw_parts is stabilized - /// // Prevent running `v`'s destructor so we are in complete control - /// // of the allocation. - /// let mut v = mem::ManuallyDrop::new(v); - /// - /// // Pull out the various important pieces of information about `v` - /// let p = v.as_mut_ptr(); - /// let len = v.len(); - /// let cap = v.capacity(); - /// let alloc = v.allocator(); - /// - /// unsafe { - /// // Overwrite memory with 4, 5, 6 - /// for i in 0..len as isize { - /// ptr::write(p.offset(i), 4 + i); - /// } - /// - /// // Put everything back together into a Vec - /// let rebuilt = Vec::from_raw_parts_in(p, len, cap, alloc.clone()); - /// assert_eq!(rebuilt, [4, 5, 6]); - /// } - /// ``` - #[inline] - #[unstable(feature = "allocator_api", issue = "32838")] - pub unsafe fn from_raw_parts_in(ptr: *mut T, length: usize, capacity: usize, alloc: A) -> Self { - unsafe { Vec { buf: RawVec::from_raw_parts_in(ptr, capacity, alloc), len: length } } - } - - /// Decomposes a `Vec` into its raw components. - /// - /// Returns the raw pointer to the underlying data, the length of - /// the vector (in elements), and the allocated capacity of the - /// data (in elements). These are the same arguments in the same - /// order as the arguments to [`from_raw_parts`]. - /// - /// After calling this function, the caller is responsible for the - /// memory previously managed by the `Vec`. The only way to do - /// this is to convert the raw pointer, length, and capacity back - /// into a `Vec` with the [`from_raw_parts`] function, allowing - /// the destructor to perform the cleanup. - /// - /// [`from_raw_parts`]: Vec::from_raw_parts - /// - /// # Examples - /// - /// ``` - /// #![feature(vec_into_raw_parts)] - /// let v: Vec = vec![-1, 0, 1]; - /// - /// let (ptr, len, cap) = v.into_raw_parts(); - /// - /// let rebuilt = unsafe { - /// // We can now make changes to the components, such as - /// // transmuting the raw pointer to a compatible type. - /// let ptr = ptr as *mut u32; - /// - /// Vec::from_raw_parts(ptr, len, cap) - /// }; - /// assert_eq!(rebuilt, [4294967295, 0, 1]); - /// ``` - #[unstable(feature = "vec_into_raw_parts", reason = "new API", issue = "65816")] - pub fn into_raw_parts(self) -> (*mut T, usize, usize) { - let mut me = ManuallyDrop::new(self); - (me.as_mut_ptr(), me.len(), me.capacity()) - } - - /// Decomposes a `Vec` into its raw components. - /// - /// Returns the raw pointer to the underlying data, the length of the vector (in elements), - /// the allocated capacity of the data (in elements), and the allocator. These are the same - /// arguments in the same order as the arguments to [`from_raw_parts_in`]. - /// - /// After calling this function, the caller is responsible for the - /// memory previously managed by the `Vec`. The only way to do - /// this is to convert the raw pointer, length, and capacity back - /// into a `Vec` with the [`from_raw_parts_in`] function, allowing - /// the destructor to perform the cleanup. - /// - /// [`from_raw_parts_in`]: Vec::from_raw_parts_in - /// - /// # Examples - /// - /// ``` - /// #![feature(allocator_api, vec_into_raw_parts)] - /// - /// use std::alloc::System; - /// - /// let mut v: Vec = Vec::new_in(System); - /// v.push(-1); - /// v.push(0); - /// v.push(1); - /// - /// let (ptr, len, cap, alloc) = v.into_raw_parts_with_alloc(); - /// - /// let rebuilt = unsafe { - /// // We can now make changes to the components, such as - /// // transmuting the raw pointer to a compatible type. - /// let ptr = ptr as *mut u32; - /// - /// Vec::from_raw_parts_in(ptr, len, cap, alloc) - /// }; - /// assert_eq!(rebuilt, [4294967295, 0, 1]); - /// ``` - #[unstable(feature = "allocator_api", issue = "32838")] - // #[unstable(feature = "vec_into_raw_parts", reason = "new API", issue = "65816")] - pub fn into_raw_parts_with_alloc(self) -> (*mut T, usize, usize, A) { - let mut me = ManuallyDrop::new(self); - let len = me.len(); - let capacity = me.capacity(); - let ptr = me.as_mut_ptr(); - let alloc = unsafe { ptr::read(me.allocator()) }; - (ptr, len, capacity, alloc) - } - - /// Returns the number of elements the vector can hold without - /// reallocating. - /// - /// # Examples - /// - /// ``` - /// let vec: Vec = Vec::with_capacity(10); - /// assert_eq!(vec.capacity(), 10); - /// ``` - #[inline] - #[stable(feature = "rust1", since = "1.0.0")] - pub fn capacity(&self) -> usize { - self.buf.capacity() - } - - /// Reserves capacity for at least `additional` more elements to be inserted - /// in the given `Vec`. The collection may reserve more space to avoid - /// frequent reallocations. After calling `reserve`, capacity will be - /// greater than or equal to `self.len() + additional`. Does nothing if - /// capacity is already sufficient. - /// - /// # Panics - /// - /// Panics if the new capacity exceeds `isize::MAX` bytes. - /// - /// # Examples - /// - /// ``` - /// let mut vec = vec![1]; - /// vec.reserve(10); - /// assert!(vec.capacity() >= 11); - /// ``` - #[stable(feature = "rust1", since = "1.0.0")] - pub fn reserve(&mut self, additional: usize) { - self.buf.reserve(self.len, additional); - } - - /// Reserves the minimum capacity for exactly `additional` more elements to - /// be inserted in the given `Vec`. After calling `reserve_exact`, - /// capacity will be greater than or equal to `self.len() + additional`. - /// Does nothing if the capacity is already sufficient. - /// - /// Note that the allocator may give the collection more space than it - /// requests. Therefore, capacity can not be relied upon to be precisely - /// minimal. Prefer `reserve` if future insertions are expected. - /// - /// # Panics - /// - /// Panics if the new capacity overflows `usize`. - /// - /// # Examples - /// - /// ``` - /// let mut vec = vec![1]; - /// vec.reserve_exact(10); - /// assert!(vec.capacity() >= 11); - /// ``` - #[stable(feature = "rust1", since = "1.0.0")] - pub fn reserve_exact(&mut self, additional: usize) { - self.buf.reserve_exact(self.len, additional); - } - - /// Tries to reserve capacity for at least `additional` more elements to be inserted - /// in the given `Vec`. The collection may reserve more space to avoid - /// frequent reallocations. After calling `try_reserve`, capacity will be - /// greater than or equal to `self.len() + additional`. Does nothing if - /// capacity is already sufficient. - /// - /// # Errors - /// - /// If the capacity overflows, or the allocator reports a failure, then an error - /// is returned. - /// - /// # Examples - /// - /// ``` - /// #![feature(try_reserve)] - /// use std::collections::TryReserveError; - /// - /// fn process_data(data: &[u32]) -> Result, TryReserveError> { - /// let mut output = Vec::new(); - /// - /// // Pre-reserve the memory, exiting if we can't - /// output.try_reserve(data.len())?; - /// - /// // Now we know this can't OOM in the middle of our complex work - /// output.extend(data.iter().map(|&val| { - /// val * 2 + 5 // very complicated - /// })); - /// - /// Ok(output) - /// } - /// # process_data(&[1, 2, 3]).expect("why is the test harness OOMing on 12 bytes?"); - /// ``` - #[unstable(feature = "try_reserve", reason = "new API", issue = "48043")] - pub fn try_reserve(&mut self, additional: usize) -> Result<(), TryReserveError> { - self.buf.try_reserve(self.len, additional) - } - - /// Tries to reserve the minimum capacity for exactly `additional` - /// elements to be inserted in the given `Vec`. After calling - /// `try_reserve_exact`, capacity will be greater than or equal to - /// `self.len() + additional` if it returns `Ok(())`. - /// Does nothing if the capacity is already sufficient. - /// - /// Note that the allocator may give the collection more space than it - /// requests. Therefore, capacity can not be relied upon to be precisely - /// minimal. Prefer `reserve` if future insertions are expected. - /// - /// # Errors - /// - /// If the capacity overflows, or the allocator reports a failure, then an error - /// is returned. - /// - /// # Examples - /// - /// ``` - /// #![feature(try_reserve)] - /// use std::collections::TryReserveError; - /// - /// fn process_data(data: &[u32]) -> Result, TryReserveError> { - /// let mut output = Vec::new(); - /// - /// // Pre-reserve the memory, exiting if we can't - /// output.try_reserve_exact(data.len())?; - /// - /// // Now we know this can't OOM in the middle of our complex work - /// output.extend(data.iter().map(|&val| { - /// val * 2 + 5 // very complicated - /// })); - /// - /// Ok(output) - /// } - /// # process_data(&[1, 2, 3]).expect("why is the test harness OOMing on 12 bytes?"); - /// ``` - #[unstable(feature = "try_reserve", reason = "new API", issue = "48043")] - pub fn try_reserve_exact(&mut self, additional: usize) -> Result<(), TryReserveError> { - self.buf.try_reserve_exact(self.len, additional) - } - - /// Shrinks the capacity of the vector as much as possible. - /// - /// It will drop down as close as possible to the length but the allocator - /// may still inform the vector that there is space for a few more elements. - /// - /// # Examples - /// - /// ``` - /// let mut vec = Vec::with_capacity(10); - /// vec.extend([1, 2, 3].iter().cloned()); - /// assert_eq!(vec.capacity(), 10); - /// vec.shrink_to_fit(); - /// assert!(vec.capacity() >= 3); - /// ``` - #[stable(feature = "rust1", since = "1.0.0")] - pub fn shrink_to_fit(&mut self) { - // The capacity is never less than the length, and there's nothing to do when - // they are equal, so we can avoid the panic case in `RawVec::shrink_to_fit` - // by only calling it with a greater capacity. - if self.capacity() > self.len { - self.buf.shrink_to_fit(self.len); - } - } - - /// Shrinks the capacity of the vector with a lower bound. - /// - /// The capacity will remain at least as large as both the length - /// and the supplied value. - /// - /// # Panics - /// - /// Panics if the current capacity is smaller than the supplied - /// minimum capacity. - /// - /// # Examples - /// - /// ``` - /// #![feature(shrink_to)] - /// let mut vec = Vec::with_capacity(10); - /// vec.extend([1, 2, 3].iter().cloned()); - /// assert_eq!(vec.capacity(), 10); - /// vec.shrink_to(4); - /// assert!(vec.capacity() >= 4); - /// vec.shrink_to(0); - /// assert!(vec.capacity() >= 3); - /// ``` - #[unstable(feature = "shrink_to", reason = "new API", issue = "56431")] - pub fn shrink_to(&mut self, min_capacity: usize) { - self.buf.shrink_to_fit(cmp::max(self.len, min_capacity)); - } - - /// Converts the vector into [`Box<[T]>`][owned slice]. - /// - /// Note that this will drop any excess capacity. - /// - /// [owned slice]: Box - /// - /// # Examples - /// - /// ``` - /// let v = vec![1, 2, 3]; - /// - /// let slice = v.into_boxed_slice(); - /// ``` - /// - /// Any excess capacity is removed: - /// - /// ``` - /// let mut vec = Vec::with_capacity(10); - /// vec.extend([1, 2, 3].iter().cloned()); - /// - /// assert_eq!(vec.capacity(), 10); - /// let slice = vec.into_boxed_slice(); - /// assert_eq!(slice.into_vec().capacity(), 3); - /// ``` - #[stable(feature = "rust1", since = "1.0.0")] - pub fn into_boxed_slice(mut self) -> Box<[T], A> { - unsafe { - self.shrink_to_fit(); - let me = ManuallyDrop::new(self); - let buf = ptr::read(&me.buf); - let len = me.len(); - buf.into_box(len).assume_init() - } - } - - /// Shortens the vector, keeping the first `len` elements and dropping - /// the rest. - /// - /// If `len` is greater than the vector's current length, this has no - /// effect. - /// - /// The [`drain`] method can emulate `truncate`, but causes the excess - /// elements to be returned instead of dropped. - /// - /// Note that this method has no effect on the allocated capacity - /// of the vector. - /// - /// # Examples - /// - /// Truncating a five element vector to two elements: - /// - /// ``` - /// let mut vec = vec![1, 2, 3, 4, 5]; - /// vec.truncate(2); - /// assert_eq!(vec, [1, 2]); - /// ``` - /// - /// No truncation occurs when `len` is greater than the vector's current - /// length: - /// - /// ``` - /// let mut vec = vec![1, 2, 3]; - /// vec.truncate(8); - /// assert_eq!(vec, [1, 2, 3]); - /// ``` - /// - /// Truncating when `len == 0` is equivalent to calling the [`clear`] - /// method. - /// - /// ``` - /// let mut vec = vec![1, 2, 3]; - /// vec.truncate(0); - /// assert_eq!(vec, []); - /// ``` - /// - /// [`clear`]: Vec::clear - /// [`drain`]: Vec::drain - #[stable(feature = "rust1", since = "1.0.0")] - pub fn truncate(&mut self, len: usize) { - // This is safe because: - // - // * the slice passed to `drop_in_place` is valid; the `len > self.len` - // case avoids creating an invalid slice, and - // * the `len` of the vector is shrunk before calling `drop_in_place`, - // such that no value will be dropped twice in case `drop_in_place` - // were to panic once (if it panics twice, the program aborts). - unsafe { - if len > self.len { - return; - } - let remaining_len = self.len - len; - let s = ptr::slice_from_raw_parts_mut(self.as_mut_ptr().add(len), remaining_len); - self.len = len; - ptr::drop_in_place(s); - } - } - - /// Extracts a slice containing the entire vector. - /// - /// Equivalent to `&s[..]`. - /// - /// # Examples - /// - /// ``` - /// use std::io::{self, Write}; - /// let buffer = vec![1, 2, 3, 5, 8]; - /// io::sink().write(buffer.as_slice()).unwrap(); - /// ``` - #[inline] - #[stable(feature = "vec_as_slice", since = "1.7.0")] - pub fn as_slice(&self) -> &[T] { - self - } - - /// Extracts a mutable slice of the entire vector. - /// - /// Equivalent to `&mut s[..]`. - /// - /// # Examples - /// - /// ``` - /// use std::io::{self, Read}; - /// let mut buffer = vec![0; 3]; - /// io::repeat(0b101).read_exact(buffer.as_mut_slice()).unwrap(); - /// ``` - #[inline] - #[stable(feature = "vec_as_slice", since = "1.7.0")] - pub fn as_mut_slice(&mut self) -> &mut [T] { - self - } - - /// Returns a raw pointer to the vector's buffer. - /// - /// The caller must ensure that the vector outlives the pointer this - /// function returns, or else it will end up pointing to garbage. - /// Modifying the vector may cause its buffer to be reallocated, - /// which would also make any pointers to it invalid. - /// - /// The caller must also ensure that the memory the pointer (non-transitively) points to - /// is never written to (except inside an `UnsafeCell`) using this pointer or any pointer - /// derived from it. If you need to mutate the contents of the slice, use [`as_mut_ptr`]. - /// - /// # Examples - /// - /// ``` - /// let x = vec![1, 2, 4]; - /// let x_ptr = x.as_ptr(); - /// - /// unsafe { - /// for i in 0..x.len() { - /// assert_eq!(*x_ptr.add(i), 1 << i); - /// } - /// } - /// ``` - /// - /// [`as_mut_ptr`]: Vec::as_mut_ptr - #[stable(feature = "vec_as_ptr", since = "1.37.0")] - #[inline] - pub fn as_ptr(&self) -> *const T { - // We shadow the slice method of the same name to avoid going through - // `deref`, which creates an intermediate reference. - let ptr = self.buf.ptr(); - unsafe { - assume(!ptr.is_null()); - } - ptr - } - - /// Returns an unsafe mutable pointer to the vector's buffer. - /// - /// The caller must ensure that the vector outlives the pointer this - /// function returns, or else it will end up pointing to garbage. - /// Modifying the vector may cause its buffer to be reallocated, - /// which would also make any pointers to it invalid. - /// - /// # Examples - /// - /// ``` - /// // Allocate vector big enough for 4 elements. - /// let size = 4; - /// let mut x: Vec = Vec::with_capacity(size); - /// let x_ptr = x.as_mut_ptr(); - /// - /// // Initialize elements via raw pointer writes, then set length. - /// unsafe { - /// for i in 0..size { - /// *x_ptr.add(i) = i as i32; - /// } - /// x.set_len(size); - /// } - /// assert_eq!(&*x, &[0, 1, 2, 3]); - /// ``` - #[stable(feature = "vec_as_ptr", since = "1.37.0")] - #[inline] - pub fn as_mut_ptr(&mut self) -> *mut T { - // We shadow the slice method of the same name to avoid going through - // `deref_mut`, which creates an intermediate reference. - let ptr = self.buf.ptr(); - unsafe { - assume(!ptr.is_null()); - } - ptr - } - - /// Returns a reference to the underlying allocator. - #[unstable(feature = "allocator_api", issue = "32838")] - #[inline] - pub fn allocator(&self) -> &A { - self.buf.allocator() - } - - /// Forces the length of the vector to `new_len`. - /// - /// This is a low-level operation that maintains none of the normal - /// invariants of the type. Normally changing the length of a vector - /// is done using one of the safe operations instead, such as - /// [`truncate`], [`resize`], [`extend`], or [`clear`]. - /// - /// [`truncate`]: Vec::truncate - /// [`resize`]: Vec::resize - /// [`extend`]: Extend::extend - /// [`clear`]: Vec::clear - /// - /// # Safety - /// - /// - `new_len` must be less than or equal to [`capacity()`]. - /// - The elements at `old_len..new_len` must be initialized. - /// - /// [`capacity()`]: Vec::capacity - /// - /// # Examples - /// - /// This method can be useful for situations in which the vector - /// is serving as a buffer for other code, particularly over FFI: - /// - /// ```no_run - /// # #![allow(dead_code)] - /// # // This is just a minimal skeleton for the doc example; - /// # // don't use this as a starting point for a real library. - /// # pub struct StreamWrapper { strm: *mut std::ffi::c_void } - /// # const Z_OK: i32 = 0; - /// # extern "C" { - /// # fn deflateGetDictionary( - /// # strm: *mut std::ffi::c_void, - /// # dictionary: *mut u8, - /// # dictLength: *mut usize, - /// # ) -> i32; - /// # } - /// # impl StreamWrapper { - /// pub fn get_dictionary(&self) -> Option> { - /// // Per the FFI method's docs, "32768 bytes is always enough". - /// let mut dict = Vec::with_capacity(32_768); - /// let mut dict_length = 0; - /// // SAFETY: When `deflateGetDictionary` returns `Z_OK`, it holds that: - /// // 1. `dict_length` elements were initialized. - /// // 2. `dict_length` <= the capacity (32_768) - /// // which makes `set_len` safe to call. - /// unsafe { - /// // Make the FFI call... - /// let r = deflateGetDictionary(self.strm, dict.as_mut_ptr(), &mut dict_length); - /// if r == Z_OK { - /// // ...and update the length to what was initialized. - /// dict.set_len(dict_length); - /// Some(dict) - /// } else { - /// None - /// } - /// } - /// } - /// # } - /// ``` - /// - /// While the following example is sound, there is a memory leak since - /// the inner vectors were not freed prior to the `set_len` call: - /// - /// ``` - /// let mut vec = vec![vec![1, 0, 0], - /// vec![0, 1, 0], - /// vec![0, 0, 1]]; - /// // SAFETY: - /// // 1. `old_len..0` is empty so no elements need to be initialized. - /// // 2. `0 <= capacity` always holds whatever `capacity` is. - /// unsafe { - /// vec.set_len(0); - /// } - /// ``` - /// - /// Normally, here, one would use [`clear`] instead to correctly drop - /// the contents and thus not leak memory. - #[inline] - #[stable(feature = "rust1", since = "1.0.0")] - pub unsafe fn set_len(&mut self, new_len: usize) { - debug_assert!(new_len <= self.capacity()); - - self.len = new_len; - } - - /// Removes an element from the vector and returns it. - /// - /// The removed element is replaced by the last element of the vector. - /// - /// This does not preserve ordering, but is O(1). - /// - /// # Panics - /// - /// Panics if `index` is out of bounds. - /// - /// # Examples - /// - /// ``` - /// let mut v = vec!["foo", "bar", "baz", "qux"]; - /// - /// assert_eq!(v.swap_remove(1), "bar"); - /// assert_eq!(v, ["foo", "qux", "baz"]); - /// - /// assert_eq!(v.swap_remove(0), "foo"); - /// assert_eq!(v, ["baz", "qux"]); - /// ``` - #[inline] - #[stable(feature = "rust1", since = "1.0.0")] - pub fn swap_remove(&mut self, index: usize) -> T { - #[cold] - #[inline(never)] - fn assert_failed(index: usize, len: usize) -> ! { - panic!("swap_remove index (is {}) should be < len (is {})", index, len); - } - - let len = self.len(); - if index >= len { - assert_failed(index, len); - } - unsafe { - // We replace self[index] with the last element. Note that if the - // bounds check above succeeds there must be a last element (which - // can be self[index] itself). - let last = ptr::read(self.as_ptr().add(len - 1)); - let hole = self.as_mut_ptr().add(index); - self.set_len(len - 1); - ptr::replace(hole, last) - } - } - - /// Inserts an element at position `index` within the vector, shifting all - /// elements after it to the right. - /// - /// # Panics - /// - /// Panics if `index > len`. - /// - /// # Examples - /// - /// ``` - /// let mut vec = vec![1, 2, 3]; - /// vec.insert(1, 4); - /// assert_eq!(vec, [1, 4, 2, 3]); - /// vec.insert(4, 5); - /// assert_eq!(vec, [1, 4, 2, 3, 5]); - /// ``` - #[stable(feature = "rust1", since = "1.0.0")] - pub fn insert(&mut self, index: usize, element: T) { - #[cold] - #[inline(never)] - fn assert_failed(index: usize, len: usize) -> ! { - panic!("insertion index (is {}) should be <= len (is {})", index, len); - } - - let len = self.len(); - if index > len { - assert_failed(index, len); - } - - // space for the new element - if len == self.buf.capacity() { - self.reserve(1); - } - - unsafe { - // infallible - // The spot to put the new value - { - let p = self.as_mut_ptr().add(index); - // Shift everything over to make space. (Duplicating the - // `index`th element into two consecutive places.) - ptr::copy(p, p.offset(1), len - index); - // Write it in, overwriting the first copy of the `index`th - // element. - ptr::write(p, element); - } - self.set_len(len + 1); - } - } - - /// Removes and returns the element at position `index` within the vector, - /// shifting all elements after it to the left. - /// - /// # Panics - /// - /// Panics if `index` is out of bounds. - /// - /// # Examples - /// - /// ``` - /// let mut v = vec![1, 2, 3]; - /// assert_eq!(v.remove(1), 2); - /// assert_eq!(v, [1, 3]); - /// ``` - #[stable(feature = "rust1", since = "1.0.0")] - pub fn remove(&mut self, index: usize) -> T { - #[cold] - #[inline(never)] - fn assert_failed(index: usize, len: usize) -> ! { - panic!("removal index (is {}) should be < len (is {})", index, len); - } - - let len = self.len(); - if index >= len { - assert_failed(index, len); - } - unsafe { - // infallible - let ret; - { - // the place we are taking from. - let ptr = self.as_mut_ptr().add(index); - // copy it out, unsafely having a copy of the value on - // the stack and in the vector at the same time. - ret = ptr::read(ptr); - - // Shift everything down to fill in that spot. - ptr::copy(ptr.offset(1), ptr, len - index - 1); - } - self.set_len(len - 1); - ret - } - } - - /// Retains only the elements specified by the predicate. - /// - /// In other words, remove all elements `e` such that `f(&e)` returns `false`. - /// This method operates in place, visiting each element exactly once in the - /// original order, and preserves the order of the retained elements. - /// - /// # Examples - /// - /// ``` - /// let mut vec = vec![1, 2, 3, 4]; - /// vec.retain(|&x| x % 2 == 0); - /// assert_eq!(vec, [2, 4]); - /// ``` - /// - /// The exact order may be useful for tracking external state, like an index. - /// - /// ``` - /// let mut vec = vec![1, 2, 3, 4, 5]; - /// let keep = [false, true, true, false, true]; - /// let mut i = 0; - /// vec.retain(|_| (keep[i], i += 1).0); - /// assert_eq!(vec, [2, 3, 5]); - /// ``` - #[stable(feature = "rust1", since = "1.0.0")] - pub fn retain(&mut self, mut f: F) - where - F: FnMut(&T) -> bool, - { - let len = self.len(); - let mut del = 0; - { - let v = &mut **self; - - for i in 0..len { - if !f(&v[i]) { - del += 1; - } else if del > 0 { - v.swap(i - del, i); - } - } - } - if del > 0 { - self.truncate(len - del); - } - } - - /// Removes all but the first of consecutive elements in the vector that resolve to the same - /// key. - /// - /// If the vector is sorted, this removes all duplicates. - /// - /// # Examples - /// - /// ``` - /// let mut vec = vec![10, 20, 21, 30, 20]; - /// - /// vec.dedup_by_key(|i| *i / 10); - /// - /// assert_eq!(vec, [10, 20, 30, 20]); - /// ``` - #[stable(feature = "dedup_by", since = "1.16.0")] - #[inline] - pub fn dedup_by_key(&mut self, mut key: F) - where - F: FnMut(&mut T) -> K, - K: PartialEq, - { - self.dedup_by(|a, b| key(a) == key(b)) - } - - /// Removes all but the first of consecutive elements in the vector satisfying a given equality - /// relation. - /// - /// The `same_bucket` function is passed references to two elements from the vector and - /// must determine if the elements compare equal. The elements are passed in opposite order - /// from their order in the slice, so if `same_bucket(a, b)` returns `true`, `a` is removed. - /// - /// If the vector is sorted, this removes all duplicates. - /// - /// # Examples - /// - /// ``` - /// let mut vec = vec!["foo", "bar", "Bar", "baz", "bar"]; - /// - /// vec.dedup_by(|a, b| a.eq_ignore_ascii_case(b)); - /// - /// assert_eq!(vec, ["foo", "bar", "baz", "bar"]); - /// ``` - #[stable(feature = "dedup_by", since = "1.16.0")] - pub fn dedup_by(&mut self, same_bucket: F) - where - F: FnMut(&mut T, &mut T) -> bool, - { - let len = { - let (dedup, _) = self.as_mut_slice().partition_dedup_by(same_bucket); - dedup.len() - }; - self.truncate(len); - } - - /// Appends an element to the back of a collection. - /// - /// # Panics - /// - /// Panics if the new capacity exceeds `isize::MAX` bytes. - /// - /// # Examples - /// - /// ``` - /// let mut vec = vec![1, 2]; - /// vec.push(3); - /// assert_eq!(vec, [1, 2, 3]); - /// ``` - #[inline] - #[stable(feature = "rust1", since = "1.0.0")] - pub fn push(&mut self, value: T) { - // This will panic or abort if we would allocate > isize::MAX bytes - // or if the length increment would overflow for zero-sized types. - if self.len == self.buf.capacity() { - self.reserve(1); - } - unsafe { - let end = self.as_mut_ptr().add(self.len); - ptr::write(end, value); - self.len += 1; - } - } - - /// Removes the last element from a vector and returns it, or [`None`] if it - /// is empty. - /// - /// # Examples - /// - /// ``` - /// let mut vec = vec![1, 2, 3]; - /// assert_eq!(vec.pop(), Some(3)); - /// assert_eq!(vec, [1, 2]); - /// ``` - #[inline] - #[stable(feature = "rust1", since = "1.0.0")] - pub fn pop(&mut self) -> Option { - if self.len == 0 { - None - } else { - unsafe { - self.len -= 1; - Some(ptr::read(self.as_ptr().add(self.len()))) - } - } - } - - /// Moves all the elements of `other` into `Self`, leaving `other` empty. - /// - /// # Panics - /// - /// Panics if the number of elements in the vector overflows a `usize`. - /// - /// # Examples - /// - /// ``` - /// let mut vec = vec![1, 2, 3]; - /// let mut vec2 = vec![4, 5, 6]; - /// vec.append(&mut vec2); - /// assert_eq!(vec, [1, 2, 3, 4, 5, 6]); - /// assert_eq!(vec2, []); - /// ``` - #[inline] - #[stable(feature = "append", since = "1.4.0")] - pub fn append(&mut self, other: &mut Self) { - unsafe { - self.append_elements(other.as_slice() as _); - other.set_len(0); - } - } - - /// Appends elements to `Self` from other buffer. - #[inline] - unsafe fn append_elements(&mut self, other: *const [T]) { - let count = unsafe { (*other).len() }; - self.reserve(count); - let len = self.len(); - unsafe { ptr::copy_nonoverlapping(other as *const T, self.as_mut_ptr().add(len), count) }; - self.len += count; - } - - /// Creates a draining iterator that removes the specified range in the vector - /// and yields the removed items. - /// - /// When the iterator **is** dropped, all elements in the range are removed - /// from the vector, even if the iterator was not fully consumed. If the - /// iterator **is not** dropped (with [`mem::forget`] for example), it is - /// unspecified how many elements are removed. - /// - /// # Panics - /// - /// Panics if the starting point is greater than the end point or if - /// the end point is greater than the length of the vector. - /// - /// # Examples - /// - /// ``` - /// let mut v = vec![1, 2, 3]; - /// let u: Vec<_> = v.drain(1..).collect(); - /// assert_eq!(v, &[1]); - /// assert_eq!(u, &[2, 3]); - /// - /// // A full range clears the vector - /// v.drain(..); - /// assert_eq!(v, &[]); - /// ``` - #[stable(feature = "drain", since = "1.6.0")] - pub fn drain(&mut self, range: R) -> Drain<'_, T, A> - where - R: RangeBounds, - { - // Memory safety - // - // When the Drain is first created, it shortens the length of - // the source vector to make sure no uninitialized or moved-from elements - // are accessible at all if the Drain's destructor never gets to run. - // - // Drain will ptr::read out the values to remove. - // When finished, remaining tail of the vec is copied back to cover - // the hole, and the vector length is restored to the new length. - // - let len = self.len(); - let Range { start, end } = range.assert_len(len); - - unsafe { - // set self.vec length's to start, to be safe in case Drain is leaked - self.set_len(start); - // Use the borrow in the IterMut to indicate borrowing behavior of the - // whole Drain iterator (like &mut T). - let range_slice = slice::from_raw_parts_mut(self.as_mut_ptr().add(start), end - start); - Drain { - tail_start: end, - tail_len: len - end, - iter: range_slice.iter(), - vec: NonNull::from(self), - } - } - } - - /// Clears the vector, removing all values. - /// - /// Note that this method has no effect on the allocated capacity - /// of the vector. - /// - /// # Examples - /// - /// ``` - /// let mut v = vec![1, 2, 3]; - /// - /// v.clear(); - /// - /// assert!(v.is_empty()); - /// ``` - #[inline] - #[stable(feature = "rust1", since = "1.0.0")] - pub fn clear(&mut self) { - self.truncate(0) - } - - /// Returns the number of elements in the vector, also referred to - /// as its 'length'. - /// - /// # Examples - /// - /// ``` - /// let a = vec![1, 2, 3]; - /// assert_eq!(a.len(), 3); - /// ``` - #[doc(alias = "length")] - #[inline] - #[stable(feature = "rust1", since = "1.0.0")] - pub fn len(&self) -> usize { - self.len - } - - /// Returns `true` if the vector contains no elements. - /// - /// # Examples - /// - /// ``` - /// let mut v = Vec::new(); - /// assert!(v.is_empty()); - /// - /// v.push(1); - /// assert!(!v.is_empty()); - /// ``` - #[stable(feature = "rust1", since = "1.0.0")] - pub fn is_empty(&self) -> bool { - self.len() == 0 - } - - /// Splits the collection into two at the given index. - /// - /// Returns a newly allocated vector containing the elements in the range - /// `[at, len)`. After the call, the original vector will be left containing - /// the elements `[0, at)` with its previous capacity unchanged. - /// - /// # Panics - /// - /// Panics if `at > len`. - /// - /// # Examples - /// - /// ``` - /// let mut vec = vec![1, 2, 3]; - /// let vec2 = vec.split_off(1); - /// assert_eq!(vec, [1]); - /// assert_eq!(vec2, [2, 3]); - /// ``` - #[inline] - #[must_use = "use `.truncate()` if you don't need the other half"] - #[stable(feature = "split_off", since = "1.4.0")] - pub fn split_off(&mut self, at: usize) -> Self - where - A: Clone, - { - #[cold] - #[inline(never)] - fn assert_failed(at: usize, len: usize) -> ! { - panic!("`at` split index (is {}) should be <= len (is {})", at, len); - } - - if at > self.len() { - assert_failed(at, self.len()); - } - - if at == 0 { - // the new vector can take over the original buffer and avoid the copy - return mem::replace( - self, - Vec::with_capacity_in(self.capacity(), self.allocator().clone()), - ); - } - - let other_len = self.len - at; - let mut other = Vec::with_capacity_in(other_len, self.allocator().clone()); - - // Unsafely `set_len` and copy items to `other`. - unsafe { - self.set_len(at); - other.set_len(other_len); - - ptr::copy_nonoverlapping(self.as_ptr().add(at), other.as_mut_ptr(), other.len()); - } - other - } - - /// Resizes the `Vec` in-place so that `len` is equal to `new_len`. - /// - /// If `new_len` is greater than `len`, the `Vec` is extended by the - /// difference, with each additional slot filled with the result of - /// calling the closure `f`. The return values from `f` will end up - /// in the `Vec` in the order they have been generated. - /// - /// If `new_len` is less than `len`, the `Vec` is simply truncated. - /// - /// This method uses a closure to create new values on every push. If - /// you'd rather [`Clone`] a given value, use [`Vec::resize`]. If you - /// want to use the [`Default`] trait to generate values, you can - /// pass [`Default::default`] as the second argument. - /// - /// # Examples - /// - /// ``` - /// let mut vec = vec![1, 2, 3]; - /// vec.resize_with(5, Default::default); - /// assert_eq!(vec, [1, 2, 3, 0, 0]); - /// - /// let mut vec = vec![]; - /// let mut p = 1; - /// vec.resize_with(4, || { p *= 2; p }); - /// assert_eq!(vec, [2, 4, 8, 16]); - /// ``` - #[stable(feature = "vec_resize_with", since = "1.33.0")] - pub fn resize_with(&mut self, new_len: usize, f: F) - where - F: FnMut() -> T, - { - let len = self.len(); - if new_len > len { - self.extend_with(new_len - len, ExtendFunc(f)); - } else { - self.truncate(new_len); - } - } - - /// Consumes and leaks the `Vec`, returning a mutable reference to the contents, - /// `&'a mut [T]`. Note that the type `T` must outlive the chosen lifetime - /// `'a`. If the type has only static references, or none at all, then this - /// may be chosen to be `'static`. - /// - /// This function is similar to the [`leak`][Box::leak] function on [`Box`] - /// except that there is no way to recover the leaked memory. - /// - /// This function is mainly useful for data that lives for the remainder of - /// the program's life. Dropping the returned reference will cause a memory - /// leak. - /// - /// # Examples - /// - /// Simple usage: - /// - /// ``` - /// let x = vec![1, 2, 3]; - /// let static_ref: &'static mut [usize] = x.leak(); - /// static_ref[0] += 1; - /// assert_eq!(static_ref, &[2, 2, 3]); - /// ``` - #[stable(feature = "vec_leak", since = "1.47.0")] - #[inline] - pub fn leak<'a>(self) -> &'a mut [T] - where - A: 'a, - { - Box::leak(self.into_boxed_slice()) - } - - /// Returns the remaining spare capacity of the vector as a slice of - /// `MaybeUninit`. - /// - /// The returned slice can be used to fill the vector with data (e.g. by - /// reading from a file) before marking the data as initialized using the - /// [`set_len`] method. - /// - /// [`set_len`]: Vec::set_len - /// - /// # Examples - /// - /// ``` - /// #![feature(vec_spare_capacity, maybe_uninit_extra)] - /// - /// // Allocate vector big enough for 10 elements. - /// let mut v = Vec::with_capacity(10); - /// - /// // Fill in the first 3 elements. - /// let uninit = v.spare_capacity_mut(); - /// uninit[0].write(0); - /// uninit[1].write(1); - /// uninit[2].write(2); - /// - /// // Mark the first 3 elements of the vector as being initialized. - /// unsafe { - /// v.set_len(3); - /// } - /// - /// assert_eq!(&v, &[0, 1, 2]); - /// ``` - #[unstable(feature = "vec_spare_capacity", issue = "75017")] - #[inline] - pub fn spare_capacity_mut(&mut self) -> &mut [MaybeUninit] { - unsafe { - slice::from_raw_parts_mut( - self.as_mut_ptr().add(self.len) as *mut MaybeUninit, - self.buf.capacity() - self.len, - ) - } - } -} - -impl Vec { - /// Resizes the `Vec` in-place so that `len` is equal to `new_len`. - /// - /// If `new_len` is greater than `len`, the `Vec` is extended by the - /// difference, with each additional slot filled with `value`. - /// If `new_len` is less than `len`, the `Vec` is simply truncated. - /// - /// This method requires `T` to implement [`Clone`], - /// in order to be able to clone the passed value. - /// If you need more flexibility (or want to rely on [`Default`] instead of - /// [`Clone`]), use [`Vec::resize_with`]. - /// - /// # Examples - /// - /// ``` - /// let mut vec = vec!["hello"]; - /// vec.resize(3, "world"); - /// assert_eq!(vec, ["hello", "world", "world"]); - /// - /// let mut vec = vec![1, 2, 3, 4]; - /// vec.resize(2, 0); - /// assert_eq!(vec, [1, 2]); - /// ``` - #[stable(feature = "vec_resize", since = "1.5.0")] - pub fn resize(&mut self, new_len: usize, value: T) { - let len = self.len(); - - if new_len > len { - self.extend_with(new_len - len, ExtendElement(value)) - } else { - self.truncate(new_len); - } - } - - /// Clones and appends all elements in a slice to the `Vec`. - /// - /// Iterates over the slice `other`, clones each element, and then appends - /// it to this `Vec`. The `other` vector is traversed in-order. - /// - /// Note that this function is same as [`extend`] except that it is - /// specialized to work with slices instead. If and when Rust gets - /// specialization this function will likely be deprecated (but still - /// available). - /// - /// # Examples - /// - /// ``` - /// let mut vec = vec![1]; - /// vec.extend_from_slice(&[2, 3, 4]); - /// assert_eq!(vec, [1, 2, 3, 4]); - /// ``` - /// - /// [`extend`]: Vec::extend - #[stable(feature = "vec_extend_from_slice", since = "1.6.0")] - pub fn extend_from_slice(&mut self, other: &[T]) { - self.spec_extend(other.iter()) - } -} - -// This code generalizes `extend_with_{element,default}`. -trait ExtendWith { - fn next(&mut self) -> T; - fn last(self) -> T; -} - -struct ExtendElement(T); -impl ExtendWith for ExtendElement { - fn next(&mut self) -> T { - self.0.clone() - } - fn last(self) -> T { - self.0 - } -} - -struct ExtendDefault; -impl ExtendWith for ExtendDefault { - fn next(&mut self) -> T { - Default::default() - } - fn last(self) -> T { - Default::default() - } -} - -struct ExtendFunc(F); -impl T> ExtendWith for ExtendFunc { - fn next(&mut self) -> T { - (self.0)() - } - fn last(mut self) -> T { - (self.0)() - } -} - -impl Vec { - /// Extend the vector by `n` values, using the given generator. - fn extend_with>(&mut self, n: usize, mut value: E) { - self.reserve(n); - - unsafe { - let mut ptr = self.as_mut_ptr().add(self.len()); - // Use SetLenOnDrop to work around bug where compiler - // may not realize the store through `ptr` through self.set_len() - // don't alias. - let mut local_len = SetLenOnDrop::new(&mut self.len); - - // Write all elements except the last one - for _ in 1..n { - ptr::write(ptr, value.next()); - ptr = ptr.offset(1); - // Increment the length in every step in case next() panics - local_len.increment_len(1); - } - - if n > 0 { - // We can write the last element directly without cloning needlessly - ptr::write(ptr, value.last()); - local_len.increment_len(1); - } - - // len set by scope guard - } - } -} - -// Set the length of the vec when the `SetLenOnDrop` value goes out of scope. -// -// The idea is: The length field in SetLenOnDrop is a local variable -// that the optimizer will see does not alias with any stores through the Vec's data -// pointer. This is a workaround for alias analysis issue #32155 -struct SetLenOnDrop<'a> { - len: &'a mut usize, - local_len: usize, -} - -impl<'a> SetLenOnDrop<'a> { - #[inline] - fn new(len: &'a mut usize) -> Self { - SetLenOnDrop { local_len: *len, len } - } - - #[inline] - fn increment_len(&mut self, increment: usize) { - self.local_len += increment; - } -} - -impl Drop for SetLenOnDrop<'_> { - #[inline] - fn drop(&mut self) { - *self.len = self.local_len; - } -} - -impl Vec { - /// Removes consecutive repeated elements in the vector according to the - /// [`PartialEq`] trait implementation. - /// - /// If the vector is sorted, this removes all duplicates. - /// - /// # Examples - /// - /// ``` - /// let mut vec = vec![1, 2, 2, 3, 2]; - /// - /// vec.dedup(); - /// - /// assert_eq!(vec, [1, 2, 3, 2]); - /// ``` - #[stable(feature = "rust1", since = "1.0.0")] - #[inline] - pub fn dedup(&mut self) { - self.dedup_by(|a, b| a == b) - } -} - -impl Vec { - /// Removes the first instance of `item` from the vector if the item exists. - /// - /// This method will be removed soon. - #[unstable(feature = "vec_remove_item", reason = "recently added", issue = "40062")] - #[rustc_deprecated( - reason = "Removing the first item equal to a needle is already easily possible \ - with iterators and the current Vec methods. Furthermore, having a method for \ - one particular case of removal (linear search, only the first item, no swap remove) \ - but not for others is inconsistent. This method will be removed soon.", - since = "1.46.0" - )] - pub fn remove_item(&mut self, item: &V) -> Option - where - T: PartialEq, - { - let pos = self.iter().position(|x| *x == *item)?; - Some(self.remove(pos)) - } -} - -//////////////////////////////////////////////////////////////////////////////// -// Internal methods and functions -//////////////////////////////////////////////////////////////////////////////// - -#[doc(hidden)] -#[stable(feature = "rust1", since = "1.0.0")] -pub fn from_elem(elem: T, n: usize) -> Vec { - ::from_elem(elem, n, Global) -} - -#[doc(hidden)] -#[unstable(feature = "allocator_api", issue = "32838")] -pub fn from_elem_in(elem: T, n: usize, alloc: A) -> Vec { - ::from_elem(elem, n, alloc) -} - -// Specialization trait used for Vec::from_elem -trait SpecFromElem: Sized { - fn from_elem(elem: Self, n: usize, alloc: A) -> Vec; -} - -impl SpecFromElem for T { - default fn from_elem(elem: Self, n: usize, alloc: A) -> Vec { - let mut v = Vec::with_capacity_in(n, alloc); - v.extend_with(n, ExtendElement(elem)); - v - } -} - -impl SpecFromElem for i8 { - #[inline] - fn from_elem(elem: i8, n: usize, alloc: A) -> Vec { - if elem == 0 { - return Vec { buf: RawVec::with_capacity_zeroed_in(n, alloc), len: n }; - } - unsafe { - let mut v = Vec::with_capacity_in(n, alloc); - ptr::write_bytes(v.as_mut_ptr(), elem as u8, n); - v.set_len(n); - v - } - } -} - -impl SpecFromElem for u8 { - #[inline] - fn from_elem(elem: u8, n: usize, alloc: A) -> Vec { - if elem == 0 { - return Vec { buf: RawVec::with_capacity_zeroed_in(n, alloc), len: n }; - } - unsafe { - let mut v = Vec::with_capacity_in(n, alloc); - ptr::write_bytes(v.as_mut_ptr(), elem, n); - v.set_len(n); - v - } - } -} - -impl SpecFromElem for T { - #[inline] - fn from_elem(elem: T, n: usize, alloc: A) -> Vec { - if elem.is_zero() { - return Vec { buf: RawVec::with_capacity_zeroed_in(n, alloc), len: n }; - } - let mut v = Vec::with_capacity_in(n, alloc); - v.extend_with(n, ExtendElement(elem)); - v - } -} - -#[rustc_specialization_trait] -unsafe trait IsZero { - /// Whether this value is zero - fn is_zero(&self) -> bool; -} - -macro_rules! impl_is_zero { - ($t:ty, $is_zero:expr) => { - unsafe impl IsZero for $t { - #[inline] - fn is_zero(&self) -> bool { - $is_zero(*self) - } - } - }; -} - -impl_is_zero!(i16, |x| x == 0); -impl_is_zero!(i32, |x| x == 0); -impl_is_zero!(i64, |x| x == 0); -impl_is_zero!(i128, |x| x == 0); -impl_is_zero!(isize, |x| x == 0); - -impl_is_zero!(u16, |x| x == 0); -impl_is_zero!(u32, |x| x == 0); -impl_is_zero!(u64, |x| x == 0); -impl_is_zero!(u128, |x| x == 0); -impl_is_zero!(usize, |x| x == 0); - -impl_is_zero!(bool, |x| x == false); -impl_is_zero!(char, |x| x == '\0'); - -impl_is_zero!(f32, |x: f32| x.to_bits() == 0); -impl_is_zero!(f64, |x: f64| x.to_bits() == 0); - -unsafe impl IsZero for *const T { - #[inline] - fn is_zero(&self) -> bool { - (*self).is_null() - } -} - -unsafe impl IsZero for *mut T { - #[inline] - fn is_zero(&self) -> bool { - (*self).is_null() - } -} - -// `Option<&T>` and `Option>` are guaranteed to represent `None` as null. -// For fat pointers, the bytes that would be the pointer metadata in the `Some` -// variant are padding in the `None` variant, so ignoring them and -// zero-initializing instead is ok. -// `Option<&mut T>` never implements `Clone`, so there's no need for an impl of -// `SpecFromElem`. - -unsafe impl IsZero for Option<&T> { - #[inline] - fn is_zero(&self) -> bool { - self.is_none() - } -} - -unsafe impl IsZero for Option> { - #[inline] - fn is_zero(&self) -> bool { - self.is_none() - } -} - -//////////////////////////////////////////////////////////////////////////////// -// Common trait implementations for Vec -//////////////////////////////////////////////////////////////////////////////// - -#[stable(feature = "rust1", since = "1.0.0")] -impl ops::Deref for Vec { - type Target = [T]; - - fn deref(&self) -> &[T] { - unsafe { slice::from_raw_parts(self.as_ptr(), self.len) } - } -} - -#[stable(feature = "rust1", since = "1.0.0")] -impl ops::DerefMut for Vec { - fn deref_mut(&mut self) -> &mut [T] { - unsafe { slice::from_raw_parts_mut(self.as_mut_ptr(), self.len) } - } -} - -#[stable(feature = "rust1", since = "1.0.0")] -impl Clone for Vec { - #[cfg(not(test))] - fn clone(&self) -> Self { - let alloc = self.allocator().clone(); - <[T]>::to_vec_in(&**self, alloc) - } - - // HACK(japaric): with cfg(test) the inherent `[T]::to_vec` method, which is - // required for this method definition, is not available. Instead use the - // `slice::to_vec` function which is only available with cfg(test) - // NB see the slice::hack module in slice.rs for more information - #[cfg(test)] - fn clone(&self) -> Self { - let alloc = self.allocator().clone(); - crate::slice::to_vec(&**self, alloc) - } - - fn clone_from(&mut self, other: &Self) { - // drop anything that will not be overwritten - self.truncate(other.len()); - - // self.len <= other.len due to the truncate above, so the - // slices here are always in-bounds. - let (init, tail) = other.split_at(self.len()); - - // reuse the contained values' allocations/resources. - self.clone_from_slice(init); - self.extend_from_slice(tail); - } -} - -#[stable(feature = "rust1", since = "1.0.0")] -impl Hash for Vec { - #[inline] - fn hash(&self, state: &mut H) { - Hash::hash(&**self, state) - } -} - -#[stable(feature = "rust1", since = "1.0.0")] -#[rustc_on_unimplemented( - message = "vector indices are of type `usize` or ranges of `usize`", - label = "vector indices are of type `usize` or ranges of `usize`" -)] -impl, A: Allocator> Index for Vec { - type Output = I::Output; - - #[inline] - fn index(&self, index: I) -> &Self::Output { - Index::index(&**self, index) - } -} - -#[stable(feature = "rust1", since = "1.0.0")] -#[rustc_on_unimplemented( - message = "vector indices are of type `usize` or ranges of `usize`", - label = "vector indices are of type `usize` or ranges of `usize`" -)] -impl, A: Allocator> IndexMut for Vec { - #[inline] - fn index_mut(&mut self, index: I) -> &mut Self::Output { - IndexMut::index_mut(&mut **self, index) - } -} - -#[stable(feature = "rust1", since = "1.0.0")] -impl FromIterator for Vec { - #[inline] - fn from_iter>(iter: I) -> Vec { - >::from_iter(iter.into_iter()) - } -} - -#[stable(feature = "rust1", since = "1.0.0")] -impl IntoIterator for Vec { - type Item = T; - type IntoIter = IntoIter; - - /// Creates a consuming iterator, that is, one that moves each value out of - /// the vector (from start to end). The vector cannot be used after calling - /// this. - /// - /// # Examples - /// - /// ``` - /// let v = vec!["a".to_string(), "b".to_string()]; - /// for s in v.into_iter() { - /// // s has type String, not &String - /// println!("{}", s); - /// } - /// ``` - #[inline] - fn into_iter(self) -> IntoIter { - unsafe { - let mut me = ManuallyDrop::new(self); - let alloc = ptr::read(me.allocator()); - let begin = me.as_mut_ptr(); - let end = if mem::size_of::() == 0 { - arith_offset(begin as *const i8, me.len() as isize) as *const T - } else { - begin.add(me.len()) as *const T - }; - let cap = me.buf.capacity(); - IntoIter { - buf: NonNull::new_unchecked(begin), - phantom: PhantomData, - cap, - alloc, - ptr: begin, - end, - } - } - } -} - -#[stable(feature = "rust1", since = "1.0.0")] -impl<'a, T, A: Allocator> IntoIterator for &'a Vec { - type Item = &'a T; - type IntoIter = slice::Iter<'a, T>; - - fn into_iter(self) -> slice::Iter<'a, T> { - self.iter() - } -} - -#[stable(feature = "rust1", since = "1.0.0")] -impl<'a, T, A: Allocator> IntoIterator for &'a mut Vec { - type Item = &'a mut T; - type IntoIter = slice::IterMut<'a, T>; - - fn into_iter(self) -> slice::IterMut<'a, T> { - self.iter_mut() - } -} - -#[stable(feature = "rust1", since = "1.0.0")] -impl Extend for Vec { - #[inline] - fn extend>(&mut self, iter: I) { - >::spec_extend(self, iter.into_iter()) - } - - #[inline] - fn extend_one(&mut self, item: T) { - self.push(item); - } - - #[inline] - fn extend_reserve(&mut self, additional: usize) { - self.reserve(additional); - } -} - -/// Specialization trait used for Vec::from_iter -/// -/// ## The delegation graph: -/// -/// ```text -/// +-------------+ -/// |FromIterator | -/// +-+-----------+ -/// | -/// v -/// +-+-------------------------------+ +---------------------+ -/// |SpecFromIter +---->+SpecFromIterNested | -/// |where I: | | |where I: | -/// | Iterator (default)----------+ | | Iterator (default) | -/// | vec::IntoIter | | | TrustedLen | -/// | SourceIterMarker---fallback-+ | | | -/// | slice::Iter | | | -/// | Iterator | +---------------------+ -/// +---------------------------------+ -/// ``` -trait SpecFromIter { - fn from_iter(iter: I) -> Self; -} - -/// Another specialization trait for Vec::from_iter -/// necessary to manually prioritize overlapping specializations -/// see [`SpecFromIter`] for details. -trait SpecFromIterNested { - fn from_iter(iter: I) -> Self; -} - -impl SpecFromIterNested for Vec -where - I: Iterator, -{ - default fn from_iter(mut iterator: I) -> Self { - // Unroll the first iteration, as the vector is going to be - // expanded on this iteration in every case when the iterable is not - // empty, but the loop in extend_desugared() is not going to see the - // vector being full in the few subsequent loop iterations. - // So we get better branch prediction. - let mut vector = match iterator.next() { - None => return Vec::new(), - Some(element) => { - let (lower, _) = iterator.size_hint(); - let mut vector = Vec::with_capacity(lower.saturating_add(1)); - unsafe { - ptr::write(vector.as_mut_ptr(), element); - vector.set_len(1); - } - vector - } - }; - // must delegate to spec_extend() since extend() itself delegates - // to spec_from for empty Vecs - as SpecExtend>::spec_extend(&mut vector, iterator); - vector - } -} - -impl SpecFromIterNested for Vec -where - I: TrustedLen, -{ - fn from_iter(iterator: I) -> Self { - let mut vector = match iterator.size_hint() { - (_, Some(upper)) => Vec::with_capacity(upper), - _ => Vec::new(), - }; - // must delegate to spec_extend() since extend() itself delegates - // to spec_from for empty Vecs - vector.spec_extend(iterator); - vector - } -} - -impl SpecFromIter for Vec -where - I: Iterator, -{ - default fn from_iter(iterator: I) -> Self { - SpecFromIterNested::from_iter(iterator) - } -} - -// A helper struct for in-place iteration that drops the destination slice of iteration, -// i.e. the head. The source slice (the tail) is dropped by IntoIter. -struct InPlaceDrop { - inner: *mut T, - dst: *mut T, -} - -impl InPlaceDrop { - fn len(&self) -> usize { - unsafe { self.dst.offset_from(self.inner) as usize } - } -} - -impl Drop for InPlaceDrop { - #[inline] - fn drop(&mut self) { - unsafe { - ptr::drop_in_place(slice::from_raw_parts_mut(self.inner, self.len())); - } - } -} - -impl SpecFromIter> for Vec { - fn from_iter(iterator: IntoIter) -> Self { - // A common case is passing a vector into a function which immediately - // re-collects into a vector. We can short circuit this if the IntoIter - // has not been advanced at all. - // When it has been advanced We can also reuse the memory and move the data to the front. - // But we only do so when the resulting Vec wouldn't have more unused capacity - // than creating it through the generic FromIterator implementation would. That limitation - // is not strictly necessary as Vec's allocation behavior is intentionally unspecified. - // But it is a conservative choice. - let has_advanced = iterator.buf.as_ptr() as *const _ != iterator.ptr; - if !has_advanced || iterator.len() >= iterator.cap / 2 { - unsafe { - let it = ManuallyDrop::new(iterator); - if has_advanced { - ptr::copy(it.ptr, it.buf.as_ptr(), it.len()); - } - return Vec::from_raw_parts(it.buf.as_ptr(), it.len(), it.cap); - } - } - - let mut vec = Vec::new(); - // must delegate to spec_extend() since extend() itself delegates - // to spec_from for empty Vecs - vec.spec_extend(iterator); - vec - } -} - -fn write_in_place_with_drop( - src_end: *const T, -) -> impl FnMut(InPlaceDrop, T) -> Result, !> { - move |mut sink, item| { - unsafe { - // the InPlaceIterable contract cannot be verified precisely here since - // try_fold has an exclusive reference to the source pointer - // all we can do is check if it's still in range - debug_assert!(sink.dst as *const _ <= src_end, "InPlaceIterable contract violation"); - ptr::write(sink.dst, item); - sink.dst = sink.dst.add(1); - } - Ok(sink) - } -} - -/// Specialization marker for collecting an iterator pipeline into a Vec while reusing the -/// source allocation, i.e. executing the pipeline in place. -/// -/// The SourceIter parent trait is necessary for the specializing function to access the allocation -/// which is to be reused. But it is not sufficient for the specialization to be valid. See -/// additional bounds on the impl. -#[rustc_unsafe_specialization_marker] -trait SourceIterMarker: SourceIter {} - -// The std-internal SourceIter/InPlaceIterable traits are only implemented by chains of -// Adapter>> (all owned by core/std). Additional bounds -// on the adapter implementations (beyond `impl Trait for Adapter`) only depend on other -// traits already marked as specialization traits (Copy, TrustedRandomAccess, FusedIterator). -// I.e. the marker does not depend on lifetimes of user-supplied types. Modulo the Copy hole, which -// several other specializations already depend on. -impl SourceIterMarker for T where T: SourceIter + InPlaceIterable {} - -impl SpecFromIter for Vec -where - I: Iterator + SourceIterMarker, -{ - default fn from_iter(mut iterator: I) -> Self { - // Additional requirements which cannot expressed via trait bounds. We rely on const eval - // instead: - // a) no ZSTs as there would be no allocation to reuse and pointer arithmetic would panic - // b) size match as required by Alloc contract - // c) alignments match as required by Alloc contract - if mem::size_of::() == 0 - || mem::size_of::() - != mem::size_of::<<::Source as AsIntoIter>::Item>() - || mem::align_of::() - != mem::align_of::<<::Source as AsIntoIter>::Item>() - { - // fallback to more generic implementations - return SpecFromIterNested::from_iter(iterator); - } - - let (src_buf, src_ptr, dst_buf, dst_end, cap) = unsafe { - let inner = iterator.as_inner().as_into_iter(); - ( - inner.buf.as_ptr(), - inner.ptr, - inner.buf.as_ptr() as *mut T, - inner.end as *const T, - inner.cap, - ) - }; - - // use try-fold since - // - it vectorizes better for some iterator adapters - // - unlike most internal iteration methods, it only takes a &mut self - // - it lets us thread the write pointer through its innards and get it back in the end - let sink = InPlaceDrop { inner: dst_buf, dst: dst_buf }; - let sink = iterator - .try_fold::<_, _, Result<_, !>>(sink, write_in_place_with_drop(dst_end)) - .unwrap(); - // iteration succeeded, don't drop head - let dst = ManuallyDrop::new(sink).dst; - - let src = unsafe { iterator.as_inner().as_into_iter() }; - // check if SourceIter contract was upheld - // caveat: if they weren't we may not even make it to this point - debug_assert_eq!(src_buf, src.buf.as_ptr()); - // check InPlaceIterable contract. This is only possible if the iterator advanced the - // source pointer at all. If it uses unchecked access via TrustedRandomAccess - // then the source pointer will stay in its initial position and we can't use it as reference - if src.ptr != src_ptr { - debug_assert!( - dst as *const _ <= src.ptr, - "InPlaceIterable contract violation, write pointer advanced beyond read pointer" - ); - } - - // drop any remaining values at the tail of the source - src.drop_remaining(); - // but prevent drop of the allocation itself once IntoIter goes out of scope - src.forget_allocation(); - - let vec = unsafe { - let len = dst.offset_from(dst_buf) as usize; - Vec::from_raw_parts(dst_buf, len, cap) - }; - - vec - } -} - -impl<'a, T: 'a, I> SpecFromIter<&'a T, I> for Vec -where - I: Iterator, - T: Clone, -{ - default fn from_iter(iterator: I) -> Self { - SpecFromIter::from_iter(iterator.cloned()) - } -} - -// This utilizes `iterator.as_slice().to_vec()` since spec_extend -// must take more steps to reason about the final capacity + length -// and thus do more work. `to_vec()` directly allocates the correct amount -// and fills it exactly. -impl<'a, T: 'a + Clone> SpecFromIter<&'a T, slice::Iter<'a, T>> for Vec { - #[cfg(not(test))] - fn from_iter(iterator: slice::Iter<'a, T>) -> Self { - iterator.as_slice().to_vec() - } - - // HACK(japaric): with cfg(test) the inherent `[T]::to_vec` method, which is - // required for this method definition, is not available. Instead use the - // `slice::to_vec` function which is only available with cfg(test) - // NB see the slice::hack module in slice.rs for more information - #[cfg(test)] - fn from_iter(iterator: slice::Iter<'a, T>) -> Self { - crate::slice::to_vec(iterator.as_slice(), Global) - } -} - -// Specialization trait used for Vec::extend -trait SpecExtend { - fn spec_extend(&mut self, iter: I); -} - -impl SpecExtend for Vec -where - I: Iterator, -{ - default fn spec_extend(&mut self, iter: I) { - self.extend_desugared(iter) - } -} - -impl SpecExtend for Vec -where - I: TrustedLen, -{ - default fn spec_extend(&mut self, iterator: I) { - // This is the case for a TrustedLen iterator. - let (low, high) = iterator.size_hint(); - if let Some(high_value) = high { - debug_assert_eq!( - low, - high_value, - "TrustedLen iterator's size hint is not exact: {:?}", - (low, high) - ); - } - if let Some(additional) = high { - self.reserve(additional); - unsafe { - let mut ptr = self.as_mut_ptr().add(self.len()); - let mut local_len = SetLenOnDrop::new(&mut self.len); - iterator.for_each(move |element| { - ptr::write(ptr, element); - ptr = ptr.offset(1); - // NB can't overflow since we would have had to alloc the address space - local_len.increment_len(1); - }); - } - } else { - self.extend_desugared(iterator) - } - } -} - -impl SpecExtend> for Vec { - fn spec_extend(&mut self, mut iterator: IntoIter) { - unsafe { - self.append_elements(iterator.as_slice() as _); - } - iterator.ptr = iterator.end; - } -} - -impl<'a, T: 'a, I, A: Allocator + 'a> SpecExtend<&'a T, I> for Vec -where - I: Iterator, - T: Clone, -{ - default fn spec_extend(&mut self, iterator: I) { - self.spec_extend(iterator.cloned()) - } -} - -impl<'a, T: 'a, A: Allocator + 'a> SpecExtend<&'a T, slice::Iter<'a, T>> for Vec -where - T: Copy, -{ - fn spec_extend(&mut self, iterator: slice::Iter<'a, T>) { - let slice = iterator.as_slice(); - unsafe { self.append_elements(slice) }; - } -} - -impl Vec { - // leaf method to which various SpecFrom/SpecExtend implementations delegate when - // they have no further optimizations to apply - fn extend_desugared>(&mut self, mut iterator: I) { - // This is the case for a general iterator. - // - // This function should be the moral equivalent of: - // - // for item in iterator { - // self.push(item); - // } - while let Some(element) = iterator.next() { - let len = self.len(); - if len == self.capacity() { - let (lower, _) = iterator.size_hint(); - self.reserve(lower.saturating_add(1)); - } - unsafe { - ptr::write(self.as_mut_ptr().add(len), element); - // NB can't overflow since we would have had to alloc the address space - self.set_len(len + 1); - } - } - } - - /// Creates a splicing iterator that replaces the specified range in the vector - /// with the given `replace_with` iterator and yields the removed items. - /// `replace_with` does not need to be the same length as `range`. - /// - /// `range` is removed even if the iterator is not consumed until the end. - /// - /// It is unspecified how many elements are removed from the vector - /// if the `Splice` value is leaked. - /// - /// The input iterator `replace_with` is only consumed when the `Splice` value is dropped. - /// - /// This is optimal if: - /// - /// * The tail (elements in the vector after `range`) is empty, - /// * or `replace_with` yields fewer elements than `range`’s length - /// * or the lower bound of its `size_hint()` is exact. - /// - /// Otherwise, a temporary vector is allocated and the tail is moved twice. - /// - /// # Panics - /// - /// Panics if the starting point is greater than the end point or if - /// the end point is greater than the length of the vector. - /// - /// # Examples - /// - /// ``` - /// let mut v = vec![1, 2, 3]; - /// let new = [7, 8]; - /// let u: Vec<_> = v.splice(..2, new.iter().cloned()).collect(); - /// assert_eq!(v, &[7, 8, 3]); - /// assert_eq!(u, &[1, 2]); - /// ``` - #[inline] - #[stable(feature = "vec_splice", since = "1.21.0")] - pub fn splice(&mut self, range: R, replace_with: I) -> Splice<'_, I::IntoIter, A> - where - R: RangeBounds, - I: IntoIterator, - { - Splice { drain: self.drain(range), replace_with: replace_with.into_iter() } - } - - /// Creates an iterator which uses a closure to determine if an element should be removed. - /// - /// If the closure returns true, then the element is removed and yielded. - /// If the closure returns false, the element will remain in the vector and will not be yielded - /// by the iterator. - /// - /// Using this method is equivalent to the following code: - /// - /// ``` - /// # let some_predicate = |x: &mut i32| { *x == 2 || *x == 3 || *x == 6 }; - /// # let mut vec = vec![1, 2, 3, 4, 5, 6]; - /// let mut i = 0; - /// while i != vec.len() { - /// if some_predicate(&mut vec[i]) { - /// let val = vec.remove(i); - /// // your code here - /// } else { - /// i += 1; - /// } - /// } - /// - /// # assert_eq!(vec, vec![1, 4, 5]); - /// ``` - /// - /// But `drain_filter` is easier to use. `drain_filter` is also more efficient, - /// because it can backshift the elements of the array in bulk. - /// - /// Note that `drain_filter` also lets you mutate every element in the filter closure, - /// regardless of whether you choose to keep or remove it. - /// - /// # Examples - /// - /// Splitting an array into evens and odds, reusing the original allocation: - /// - /// ``` - /// #![feature(drain_filter)] - /// let mut numbers = vec![1, 2, 3, 4, 5, 6, 8, 9, 11, 13, 14, 15]; - /// - /// let evens = numbers.drain_filter(|x| *x % 2 == 0).collect::>(); - /// let odds = numbers; - /// - /// assert_eq!(evens, vec![2, 4, 6, 8, 14]); - /// assert_eq!(odds, 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, A> - where - F: FnMut(&mut T) -> bool, - { - let old_len = self.len(); - - // Guard against us getting leaked (leak amplification) - unsafe { - self.set_len(0); - } - - DrainFilter { vec: self, idx: 0, del: 0, old_len, pred: filter, panic_flag: false } - } -} - -/// Extend implementation that copies elements out of references before pushing them onto the Vec. -/// -/// This implementation is specialized for slice iterators, where it uses [`copy_from_slice`] to -/// append the entire slice at once. -/// -/// [`copy_from_slice`]: ../../std/primitive.slice.html#method.copy_from_slice -#[stable(feature = "extend_ref", since = "1.2.0")] -impl<'a, T: Copy + 'a, A: Allocator + 'a> Extend<&'a T> for Vec { - fn extend>(&mut self, iter: I) { - self.spec_extend(iter.into_iter()) - } - - #[inline] - fn extend_one(&mut self, &item: &'a T) { - self.push(item); - } - - #[inline] - fn extend_reserve(&mut self, additional: usize) { - self.reserve(additional); - } -} - -macro_rules! __impl_slice_eq1 { - ([$($vars:tt)*] $lhs:ty, $rhs:ty $(where $ty:ty: $bound:ident)?, #[$stability:meta]) => { - #[$stability] - impl PartialEq<$rhs> for $lhs - where - T: PartialEq, - $($ty: $bound)? - { - #[inline] - fn eq(&self, other: &$rhs) -> bool { self[..] == other[..] } - #[inline] - fn ne(&self, other: &$rhs) -> bool { self[..] != other[..] } - } - } -} - -__impl_slice_eq1! { [A: Allocator] Vec, Vec, #[stable(feature = "rust1", since = "1.0.0")] } -__impl_slice_eq1! { [A: Allocator] Vec, &[U], #[stable(feature = "rust1", since = "1.0.0")] } -__impl_slice_eq1! { [A: Allocator] Vec, &mut [U], #[stable(feature = "rust1", since = "1.0.0")] } -__impl_slice_eq1! { [A: Allocator] &[T], Vec, #[stable(feature = "partialeq_vec_for_ref_slice", since = "1.46.0")] } -__impl_slice_eq1! { [A: Allocator] &mut [T], Vec, #[stable(feature = "partialeq_vec_for_ref_slice", since = "1.46.0")] } -__impl_slice_eq1! { [A: Allocator] Vec, [U], #[stable(feature = "partialeq_vec_for_slice", since = "1.48.0")] } -__impl_slice_eq1! { [A: Allocator] [T], Vec, #[stable(feature = "partialeq_vec_for_slice", since = "1.48.0")] } -__impl_slice_eq1! { [A: Allocator] Cow<'_, [T]>, Vec where T: Clone, #[stable(feature = "rust1", since = "1.0.0")] } -__impl_slice_eq1! { [] Cow<'_, [T]>, &[U] where T: Clone, #[stable(feature = "rust1", since = "1.0.0")] } -__impl_slice_eq1! { [] Cow<'_, [T]>, &mut [U] where T: Clone, #[stable(feature = "rust1", since = "1.0.0")] } -__impl_slice_eq1! { [A: Allocator, const N: usize] Vec, [U; N], #[stable(feature = "rust1", since = "1.0.0")] } -__impl_slice_eq1! { [A: Allocator, const N: usize] Vec, &[U; N], #[stable(feature = "rust1", since = "1.0.0")] } - -// NOTE: some less important impls are omitted to reduce code bloat -// FIXME(Centril): Reconsider this? -//__impl_slice_eq1! { [const N: usize] Vec, &mut [B; N], } -//__impl_slice_eq1! { [const N: usize] [A; N], Vec, } -//__impl_slice_eq1! { [const N: usize] &[A; N], Vec, } -//__impl_slice_eq1! { [const N: usize] &mut [A; N], Vec, } -//__impl_slice_eq1! { [const N: usize] Cow<'a, [A]>, [B; N], } -//__impl_slice_eq1! { [const N: usize] Cow<'a, [A]>, &[B; N], } -//__impl_slice_eq1! { [const N: usize] Cow<'a, [A]>, &mut [B; N], } - -/// Implements comparison of vectors, [lexicographically](core::cmp::Ord#lexicographical-comparison). -#[stable(feature = "rust1", since = "1.0.0")] -impl PartialOrd for Vec { - #[inline] - fn partial_cmp(&self, other: &Self) -> Option { - PartialOrd::partial_cmp(&**self, &**other) - } -} - -#[stable(feature = "rust1", since = "1.0.0")] -impl Eq for Vec {} - -/// Implements ordering of vectors, [lexicographically](core::cmp::Ord#lexicographical-comparison). -#[stable(feature = "rust1", since = "1.0.0")] -impl Ord for Vec { - #[inline] - fn cmp(&self, other: &Self) -> Ordering { - Ord::cmp(&**self, &**other) - } -} - -#[stable(feature = "rust1", since = "1.0.0")] -unsafe impl<#[may_dangle] T, A: Allocator> Drop for Vec { - fn drop(&mut self) { - unsafe { - // use drop for [T] - // use a raw slice to refer to the elements of the vector as weakest necessary type; - // could avoid questions of validity in certain cases - ptr::drop_in_place(ptr::slice_from_raw_parts_mut(self.as_mut_ptr(), self.len)) - } - // RawVec handles deallocation - } -} - -#[stable(feature = "rust1", since = "1.0.0")] -impl Default for Vec { - /// Creates an empty `Vec`. - fn default() -> Vec { - Vec::new() - } -} - -#[stable(feature = "rust1", since = "1.0.0")] -impl fmt::Debug for Vec { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - fmt::Debug::fmt(&**self, f) - } -} - -#[stable(feature = "rust1", since = "1.0.0")] -impl AsRef> for Vec { - fn as_ref(&self) -> &Vec { - self - } -} - -#[stable(feature = "vec_as_mut", since = "1.5.0")] -impl AsMut> for Vec { - fn as_mut(&mut self) -> &mut Vec { - self - } -} - -#[stable(feature = "rust1", since = "1.0.0")] -impl AsRef<[T]> for Vec { - fn as_ref(&self) -> &[T] { - self - } -} - -#[stable(feature = "vec_as_mut", since = "1.5.0")] -impl AsMut<[T]> for Vec { - fn as_mut(&mut self) -> &mut [T] { - self - } -} - -#[stable(feature = "rust1", since = "1.0.0")] -impl From<&[T]> for Vec { - #[cfg(not(test))] - fn from(s: &[T]) -> Vec { - s.to_vec() - } - #[cfg(test)] - fn from(s: &[T]) -> Vec { - crate::slice::to_vec(s, Global) - } -} - -#[stable(feature = "vec_from_mut", since = "1.19.0")] -impl From<&mut [T]> for Vec { - #[cfg(not(test))] - fn from(s: &mut [T]) -> Vec { - s.to_vec() - } - #[cfg(test)] - fn from(s: &mut [T]) -> Vec { - crate::slice::to_vec(s, Global) - } -} - -#[stable(feature = "vec_from_array", since = "1.44.0")] -impl From<[T; N]> for Vec { - #[cfg(not(test))] - fn from(s: [T; N]) -> Vec { - <[T]>::into_vec(box s) - } - #[cfg(test)] - fn from(s: [T; N]) -> Vec { - crate::slice::into_vec(box s) - } -} - -#[stable(feature = "vec_from_cow_slice", since = "1.14.0")] -impl<'a, T> From> for Vec -where - [T]: ToOwned>, -{ - fn from(s: Cow<'a, [T]>) -> Vec { - s.into_owned() - } -} - -// note: test pulls in libstd, which causes errors here -#[cfg(not(test))] -#[stable(feature = "vec_from_box", since = "1.18.0")] -impl From> for Vec { - fn from(s: Box<[T], A>) -> Self { - let len = s.len(); - Self { buf: RawVec::from_box(s), len } - } -} - -// note: test pulls in libstd, which causes errors here -#[cfg(not(test))] -#[stable(feature = "box_from_vec", since = "1.20.0")] -impl From> for Box<[T], A> { - fn from(v: Vec) -> Self { - v.into_boxed_slice() - } -} - -#[stable(feature = "rust1", since = "1.0.0")] -impl From<&str> for Vec { - fn from(s: &str) -> Vec { - From::from(s.as_bytes()) - } -} - -#[stable(feature = "array_try_from_vec", since = "1.48.0")] -impl TryFrom> for [T; N] { - type Error = Vec; - - /// Gets the entire contents of the `Vec` as an array, - /// if its size exactly matches that of the requested array. - /// - /// # Examples - /// - /// ``` - /// use std::convert::TryInto; - /// assert_eq!(vec![1, 2, 3].try_into(), Ok([1, 2, 3])); - /// assert_eq!(>::new().try_into(), Ok([])); - /// ``` - /// - /// If the length doesn't match, the input comes back in `Err`: - /// ``` - /// use std::convert::TryInto; - /// let r: Result<[i32; 4], _> = (0..10).collect::>().try_into(); - /// assert_eq!(r, Err(vec![0, 1, 2, 3, 4, 5, 6, 7, 8, 9])); - /// ``` - /// - /// If you're fine with just getting a prefix of the `Vec`, - /// you can call [`.truncate(N)`](Vec::truncate) first. - /// ``` - /// use std::convert::TryInto; - /// let mut v = String::from("hello world").into_bytes(); - /// v.sort(); - /// v.truncate(2); - /// let [a, b]: [_; 2] = v.try_into().unwrap(); - /// assert_eq!(a, b' '); - /// assert_eq!(b, b'd'); - /// ``` - fn try_from(mut vec: Vec) -> Result<[T; N], Vec> { - if vec.len() != N { - return Err(vec); - } - - // SAFETY: `.set_len(0)` is always sound. - unsafe { vec.set_len(0) }; - - // SAFETY: A `Vec`'s pointer is always aligned properly, and - // the alignment the array needs is the same as the items. - // We checked earlier that we have sufficient items. - // The items will not double-drop as the `set_len` - // tells the `Vec` not to also drop them. - let array = unsafe { ptr::read(vec.as_ptr() as *const [T; N]) }; - Ok(array) - } -} - -//////////////////////////////////////////////////////////////////////////////// -// Clone-on-write -//////////////////////////////////////////////////////////////////////////////// - -#[stable(feature = "cow_from_vec", since = "1.8.0")] -impl<'a, T: Clone> From<&'a [T]> for Cow<'a, [T]> { - fn from(s: &'a [T]) -> Cow<'a, [T]> { - Cow::Borrowed(s) - } -} - -#[stable(feature = "cow_from_vec", since = "1.8.0")] -impl<'a, T: Clone> From> for Cow<'a, [T]> { - fn from(v: Vec) -> Cow<'a, [T]> { - Cow::Owned(v) - } -} - -#[stable(feature = "cow_from_vec_ref", since = "1.28.0")] -impl<'a, T: Clone> From<&'a Vec> for Cow<'a, [T]> { - fn from(v: &'a Vec) -> Cow<'a, [T]> { - Cow::Borrowed(v.as_slice()) - } -} - -#[stable(feature = "rust1", since = "1.0.0")] -impl<'a, T> FromIterator for Cow<'a, [T]> -where - T: Clone, -{ - fn from_iter>(it: I) -> Cow<'a, [T]> { - Cow::Owned(FromIterator::from_iter(it)) - } -} - -//////////////////////////////////////////////////////////////////////////////// -// Iterators -//////////////////////////////////////////////////////////////////////////////// - -/// An iterator that moves out of a vector. -/// -/// This `struct` is created by the `into_iter` method on [`Vec`] (provided -/// by the [`IntoIterator`] trait). -/// -/// # Example -/// -/// ``` -/// let v = vec![0, 1, 2]; -/// let iter: std::vec::IntoIter<_> = v.into_iter(); -/// ``` -#[stable(feature = "rust1", since = "1.0.0")] -pub struct IntoIter< - T, - #[unstable(feature = "allocator_api", issue = "32838")] A: Allocator = Global, -> { - buf: NonNull, - phantom: PhantomData, - cap: usize, - alloc: A, - ptr: *const T, - end: *const T, -} - -#[stable(feature = "vec_intoiter_debug", since = "1.13.0")] -impl fmt::Debug for IntoIter { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - f.debug_tuple("IntoIter").field(&self.as_slice()).finish() - } -} - -impl IntoIter { - /// Returns the remaining items of this iterator as a slice. - /// - /// # Examples - /// - /// ``` - /// let vec = vec!['a', 'b', 'c']; - /// let mut into_iter = vec.into_iter(); - /// assert_eq!(into_iter.as_slice(), &['a', 'b', 'c']); - /// let _ = into_iter.next().unwrap(); - /// assert_eq!(into_iter.as_slice(), &['b', 'c']); - /// ``` - #[stable(feature = "vec_into_iter_as_slice", since = "1.15.0")] - pub fn as_slice(&self) -> &[T] { - unsafe { slice::from_raw_parts(self.ptr, self.len()) } - } - - /// Returns the remaining items of this iterator as a mutable slice. - /// - /// # Examples - /// - /// ``` - /// let vec = vec!['a', 'b', 'c']; - /// let mut into_iter = vec.into_iter(); - /// assert_eq!(into_iter.as_slice(), &['a', 'b', 'c']); - /// into_iter.as_mut_slice()[2] = 'z'; - /// assert_eq!(into_iter.next().unwrap(), 'a'); - /// assert_eq!(into_iter.next().unwrap(), 'b'); - /// assert_eq!(into_iter.next().unwrap(), 'z'); - /// ``` - #[stable(feature = "vec_into_iter_as_slice", since = "1.15.0")] - pub fn as_mut_slice(&mut self) -> &mut [T] { - unsafe { &mut *self.as_raw_mut_slice() } - } - - /// Returns a reference to the underlying allocator. - #[unstable(feature = "allocator_api", issue = "32838")] - #[inline] - pub fn allocator(&self) -> &A { - &self.alloc - } - - fn as_raw_mut_slice(&mut self) -> *mut [T] { - ptr::slice_from_raw_parts_mut(self.ptr as *mut T, self.len()) - } - - fn drop_remaining(&mut self) { - unsafe { - ptr::drop_in_place(self.as_mut_slice()); - } - self.ptr = self.end; - } - - /// Relinquishes the backing allocation, equivalent to - /// `ptr::write(&mut self, Vec::new().into_iter())` - fn forget_allocation(&mut self) { - self.cap = 0; - self.buf = unsafe { NonNull::new_unchecked(RawVec::NEW.ptr()) }; - self.ptr = self.buf.as_ptr(); - self.end = self.buf.as_ptr(); - } -} - -#[stable(feature = "vec_intoiter_as_ref", since = "1.46.0")] -impl AsRef<[T]> for IntoIter { - fn as_ref(&self) -> &[T] { - self.as_slice() - } -} - -#[stable(feature = "rust1", since = "1.0.0")] -unsafe impl Send for IntoIter {} -#[stable(feature = "rust1", since = "1.0.0")] -unsafe impl Sync for IntoIter {} - -#[stable(feature = "rust1", since = "1.0.0")] -impl Iterator for IntoIter { - type Item = T; - - #[inline] - fn next(&mut self) -> Option { - if self.ptr as *const _ == self.end { - None - } else if mem::size_of::() == 0 { - // purposefully don't use 'ptr.offset' because for - // vectors with 0-size elements this would return the - // same pointer. - self.ptr = unsafe { arith_offset(self.ptr as *const i8, 1) as *mut T }; - - // Make up a value of this ZST. - Some(unsafe { mem::zeroed() }) - } else { - let old = self.ptr; - self.ptr = unsafe { self.ptr.offset(1) }; - - Some(unsafe { ptr::read(old) }) - } - } - - #[inline] - fn size_hint(&self) -> (usize, Option) { - let exact = if mem::size_of::() == 0 { - (self.end as usize).wrapping_sub(self.ptr as usize) - } else { - unsafe { self.end.offset_from(self.ptr) as usize } - }; - (exact, Some(exact)) - } - - #[inline] - fn count(self) -> usize { - self.len() - } - - unsafe fn __iterator_get_unchecked(&mut self, i: usize) -> Self::Item - where - Self: TrustedRandomAccess, - { - // SAFETY: the caller must guarantee that `i` is in bounds of the - // `Vec`, so `i` cannot overflow an `isize`, and the `self.ptr.add(i)` - // is guaranteed to pointer to an element of the `Vec` and - // thus guaranteed to be valid to dereference. - // - // Also note the implementation of `Self: TrustedRandomAccess` requires - // that `T: Copy` so reading elements from the buffer doesn't invalidate - // them for `Drop`. - unsafe { - if mem::size_of::() == 0 { mem::zeroed() } else { ptr::read(self.ptr.add(i)) } - } - } -} - -#[stable(feature = "rust1", since = "1.0.0")] -impl DoubleEndedIterator for IntoIter { - #[inline] - fn next_back(&mut self) -> Option { - if self.end == self.ptr { - None - } else if mem::size_of::() == 0 { - // See above for why 'ptr.offset' isn't used - self.end = unsafe { arith_offset(self.end as *const i8, -1) as *mut T }; - - // Make up a value of this ZST. - Some(unsafe { mem::zeroed() }) - } else { - self.end = unsafe { self.end.offset(-1) }; - - Some(unsafe { ptr::read(self.end) }) - } - } -} - -#[stable(feature = "rust1", since = "1.0.0")] -impl ExactSizeIterator for IntoIter { - fn is_empty(&self) -> bool { - self.ptr == self.end - } -} - -#[stable(feature = "fused", since = "1.26.0")] -impl FusedIterator for IntoIter {} - -#[unstable(feature = "trusted_len", issue = "37572")] -unsafe impl TrustedLen for IntoIter {} - -#[doc(hidden)] -#[unstable(issue = "none", feature = "std_internals")] -// T: Copy as approximation for !Drop since get_unchecked does not advance self.ptr -// and thus we can't implement drop-handling -unsafe impl TrustedRandomAccess for IntoIter -where - T: Copy, -{ - fn may_have_side_effect() -> bool { - false - } -} - -#[stable(feature = "vec_into_iter_clone", since = "1.8.0")] -impl Clone for IntoIter { - #[cfg(not(test))] - fn clone(&self) -> Self { - self.as_slice().to_vec_in(self.alloc.clone()).into_iter() - } - #[cfg(test)] - fn clone(&self) -> Self { - crate::slice::to_vec(self.as_slice(), self.alloc.clone()).into_iter() - } -} - -#[stable(feature = "rust1", since = "1.0.0")] -unsafe impl<#[may_dangle] T, A: Allocator> Drop for IntoIter { - fn drop(&mut self) { - struct DropGuard<'a, T, A: Allocator>(&'a mut IntoIter); - - impl Drop for DropGuard<'_, T, A> { - fn drop(&mut self) { - unsafe { - // `IntoIter::alloc` is not used anymore after this - let alloc = ptr::read(&self.0.alloc); - // RawVec handles deallocation - let _ = RawVec::from_raw_parts_in(self.0.buf.as_ptr(), self.0.cap, alloc); - } - } - } - - let guard = DropGuard(self); - // destroy the remaining elements - unsafe { - ptr::drop_in_place(guard.0.as_raw_mut_slice()); - } - // now `guard` will be dropped and do the rest - } -} - -#[unstable(issue = "none", feature = "inplace_iteration")] -unsafe impl InPlaceIterable for IntoIter {} - -#[unstable(issue = "none", feature = "inplace_iteration")] -unsafe impl SourceIter for IntoIter { - type Source = Self; - - #[inline] - unsafe fn as_inner(&mut self) -> &mut Self::Source { - self - } -} - -// internal helper trait for in-place iteration specialization. -#[rustc_specialization_trait] -pub(crate) trait AsIntoIter { - type Item; - fn as_into_iter(&mut self) -> &mut IntoIter; -} - -impl AsIntoIter for IntoIter { - type Item = T; - - fn as_into_iter(&mut self) -> &mut IntoIter { - self - } -} - -/// A draining iterator for `Vec`. -/// -/// This `struct` is created by [`Vec::drain`]. -/// See its documentation for more. -/// -/// # Example -/// -/// ``` -/// let mut v = vec![0, 1, 2]; -/// let iter: std::vec::Drain<_> = v.drain(..); -/// ``` -#[stable(feature = "drain", since = "1.6.0")] -pub struct Drain< - 'a, - T: 'a, - #[unstable(feature = "allocator_api", issue = "32838")] A: Allocator + 'a = Global, -> { - /// Index of tail to preserve - tail_start: usize, - /// Length of tail - tail_len: usize, - /// Current remaining range to remove - iter: slice::Iter<'a, T>, - vec: NonNull>, -} - -#[stable(feature = "collection_debug", since = "1.17.0")] -impl fmt::Debug for Drain<'_, T, A> { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - f.debug_tuple("Drain").field(&self.iter.as_slice()).finish() - } -} - -impl<'a, T, A: Allocator> Drain<'a, T, A> { - /// Returns the remaining items of this iterator as a slice. - /// - /// # Examples - /// - /// ``` - /// let mut vec = vec!['a', 'b', 'c']; - /// let mut drain = vec.drain(..); - /// assert_eq!(drain.as_slice(), &['a', 'b', 'c']); - /// let _ = drain.next().unwrap(); - /// assert_eq!(drain.as_slice(), &['b', 'c']); - /// ``` - #[stable(feature = "vec_drain_as_slice", since = "1.46.0")] - pub fn as_slice(&self) -> &[T] { - self.iter.as_slice() - } - - /// Returns a reference to the underlying allocator. - #[unstable(feature = "allocator_api", issue = "32838")] - #[inline] - pub fn allocator(&self) -> &A { - unsafe { self.vec.as_ref().allocator() } - } -} - -#[stable(feature = "vec_drain_as_slice", since = "1.46.0")] -impl<'a, T, A: Allocator> AsRef<[T]> for Drain<'a, T, A> { - fn as_ref(&self) -> &[T] { - self.as_slice() - } -} - -#[stable(feature = "drain", since = "1.6.0")] -unsafe impl Sync for Drain<'_, T, A> {} -#[stable(feature = "drain", since = "1.6.0")] -unsafe impl Send for Drain<'_, T, A> {} - -#[stable(feature = "drain", since = "1.6.0")] -impl Iterator for Drain<'_, T, A> { - type Item = T; - - #[inline] - fn next(&mut self) -> Option { - self.iter.next().map(|elt| unsafe { ptr::read(elt as *const _) }) - } - - fn size_hint(&self) -> (usize, Option) { - self.iter.size_hint() - } -} - -#[stable(feature = "drain", since = "1.6.0")] -impl DoubleEndedIterator for Drain<'_, T, A> { - #[inline] - fn next_back(&mut self) -> Option { - self.iter.next_back().map(|elt| unsafe { ptr::read(elt as *const _) }) - } -} - -#[stable(feature = "drain", since = "1.6.0")] -impl Drop for Drain<'_, T, A> { - fn drop(&mut self) { - /// Continues dropping the remaining elements in the `Drain`, then moves back the - /// un-`Drain`ed elements to restore the original `Vec`. - struct DropGuard<'r, 'a, T, A: Allocator>(&'r mut Drain<'a, T, A>); - - impl<'r, 'a, T, A: Allocator> Drop for DropGuard<'r, 'a, T, A> { - fn drop(&mut self) { - // Continue the same loop we have below. If the loop already finished, this does - // nothing. - self.0.for_each(drop); - - if self.0.tail_len > 0 { - unsafe { - let source_vec = self.0.vec.as_mut(); - // memmove back untouched tail, update to new length - let start = source_vec.len(); - let tail = self.0.tail_start; - if tail != start { - let src = source_vec.as_ptr().add(tail); - let dst = source_vec.as_mut_ptr().add(start); - ptr::copy(src, dst, self.0.tail_len); - } - source_vec.set_len(start + self.0.tail_len); - } - } - } - } - - // exhaust self first - while let Some(item) = self.next() { - let guard = DropGuard(self); - drop(item); - mem::forget(guard); - } - - // Drop a `DropGuard` to move back the non-drained tail of `self`. - DropGuard(self); - } -} - -#[stable(feature = "drain", since = "1.6.0")] -impl ExactSizeIterator for Drain<'_, T, A> { - fn is_empty(&self) -> bool { - self.iter.is_empty() - } -} - -#[unstable(feature = "trusted_len", issue = "37572")] -unsafe impl TrustedLen for Drain<'_, T, A> {} - -#[stable(feature = "fused", since = "1.26.0")] -impl FusedIterator for Drain<'_, T, A> {} - -/// A splicing iterator for `Vec`. -/// -/// This struct is created by [`Vec::splice()`]. -/// See its documentation for more. -/// -/// # Example -/// -/// ``` -/// let mut v = vec![0, 1, 2]; -/// let new = [7, 8]; -/// let iter: std::vec::Splice<_> = v.splice(1.., new.iter().cloned()); -/// ``` -#[derive(Debug)] -#[stable(feature = "vec_splice", since = "1.21.0")] -pub struct Splice< - 'a, - I: Iterator + 'a, - #[unstable(feature = "allocator_api", issue = "32838")] A: Allocator + 'a = Global, -> { - drain: Drain<'a, I::Item, A>, - replace_with: I, -} - -#[stable(feature = "vec_splice", since = "1.21.0")] -impl Iterator for Splice<'_, I, A> { - type Item = I::Item; - - fn next(&mut self) -> Option { - self.drain.next() - } - - fn size_hint(&self) -> (usize, Option) { - self.drain.size_hint() - } -} - -#[stable(feature = "vec_splice", since = "1.21.0")] -impl DoubleEndedIterator for Splice<'_, I, A> { - fn next_back(&mut self) -> Option { - self.drain.next_back() - } -} - -#[stable(feature = "vec_splice", since = "1.21.0")] -impl ExactSizeIterator for Splice<'_, I, A> {} - -#[stable(feature = "vec_splice", since = "1.21.0")] -impl Drop for Splice<'_, I, A> { - fn drop(&mut self) { - self.drain.by_ref().for_each(drop); - - unsafe { - if self.drain.tail_len == 0 { - self.drain.vec.as_mut().extend(self.replace_with.by_ref()); - return; - } - - // First fill the range left by drain(). - if !self.drain.fill(&mut self.replace_with) { - return; - } - - // There may be more elements. Use the lower bound as an estimate. - // FIXME: Is the upper bound a better guess? Or something else? - let (lower_bound, _upper_bound) = self.replace_with.size_hint(); - if lower_bound > 0 { - self.drain.move_tail(lower_bound); - if !self.drain.fill(&mut self.replace_with) { - return; - } - } - - // Collect any remaining elements. - // This is a zero-length vector which does not allocate if `lower_bound` was exact. - let mut collected = self.replace_with.by_ref().collect::>().into_iter(); - // Now we have an exact count. - if collected.len() > 0 { - self.drain.move_tail(collected.len()); - let filled = self.drain.fill(&mut collected); - debug_assert!(filled); - debug_assert_eq!(collected.len(), 0); - } - } - // Let `Drain::drop` move the tail back if necessary and restore `vec.len`. - } -} - -/// Private helper methods for `Splice::drop` -impl Drain<'_, T, A> { - /// The range from `self.vec.len` to `self.tail_start` contains elements - /// that have been moved out. - /// Fill that range as much as possible with new elements from the `replace_with` iterator. - /// Returns `true` if we filled the entire range. (`replace_with.next()` didn’t return `None`.) - unsafe fn fill>(&mut self, replace_with: &mut I) -> bool { - let vec = unsafe { self.vec.as_mut() }; - let range_start = vec.len; - let range_end = self.tail_start; - let range_slice = unsafe { - slice::from_raw_parts_mut(vec.as_mut_ptr().add(range_start), range_end - range_start) - }; - - for place in range_slice { - if let Some(new_item) = replace_with.next() { - unsafe { ptr::write(place, new_item) }; - vec.len += 1; - } else { - return false; - } - } - true - } - - /// Makes room for inserting more elements before the tail. - unsafe fn move_tail(&mut self, additional: usize) { - let vec = unsafe { self.vec.as_mut() }; - let len = self.tail_start + self.tail_len; - vec.buf.reserve(len, additional); - - let new_tail_start = self.tail_start + additional; - unsafe { - let src = vec.as_ptr().add(self.tail_start); - let dst = vec.as_mut_ptr().add(new_tail_start); - ptr::copy(src, dst, self.tail_len); - } - self.tail_start = new_tail_start; - } -} - -/// An iterator which uses a closure to determine if an element should be removed. -/// -/// This struct is created by [`Vec::drain_filter`]. -/// See its documentation for more. -/// -/// # Example -/// -/// ``` -/// #![feature(drain_filter)] -/// -/// let mut v = vec![0, 1, 2]; -/// let iter: std::vec::DrainFilter<_, _> = v.drain_filter(|x| *x % 2 == 0); -/// ``` -#[unstable(feature = "drain_filter", reason = "recently added", issue = "43244")] -#[derive(Debug)] -pub struct DrainFilter< - 'a, - T, - F, - #[unstable(feature = "allocator_api", issue = "32838")] A: Allocator = Global, -> where - F: FnMut(&mut T) -> bool, -{ - vec: &'a mut Vec, - /// The index of the item that will be inspected by the next call to `next`. - idx: usize, - /// The number of items that have been drained (removed) thus far. - del: usize, - /// The original length of `vec` prior to draining. - old_len: usize, - /// The filter test predicate. - pred: F, - /// A flag that indicates a panic has occurred in the filter test predicate. - /// This is used as a hint in the drop implementation to prevent consumption - /// of the remainder of the `DrainFilter`. Any unprocessed items will be - /// backshifted in the `vec`, but no further items will be dropped or - /// tested by the filter predicate. - panic_flag: bool, -} - -impl DrainFilter<'_, T, F, A> -where - F: FnMut(&mut T) -> bool, -{ - /// Returns a reference to the underlying allocator. - #[unstable(feature = "allocator_api", issue = "32838")] - #[inline] - pub fn allocator(&self) -> &A { - self.vec.allocator() - } -} - -#[unstable(feature = "drain_filter", reason = "recently added", issue = "43244")] -impl Iterator for DrainFilter<'_, T, F, A> -where - F: FnMut(&mut T) -> bool, -{ - type Item = T; - - fn next(&mut self) -> Option { - unsafe { - while self.idx < self.old_len { - let i = self.idx; - let v = slice::from_raw_parts_mut(self.vec.as_mut_ptr(), self.old_len); - self.panic_flag = true; - let drained = (self.pred)(&mut v[i]); - self.panic_flag = false; - // Update the index *after* the predicate is called. If the index - // is updated prior and the predicate panics, the element at this - // index would be leaked. - self.idx += 1; - if drained { - self.del += 1; - return Some(ptr::read(&v[i])); - } else if self.del > 0 { - let del = self.del; - let src: *const T = &v[i]; - let dst: *mut T = &mut v[i - del]; - ptr::copy_nonoverlapping(src, dst, 1); - } - } - None - } - } - - fn size_hint(&self) -> (usize, Option) { - (0, Some(self.old_len - self.idx)) - } -} - -#[unstable(feature = "drain_filter", reason = "recently added", issue = "43244")] -impl Drop for DrainFilter<'_, T, F, A> -where - F: FnMut(&mut T) -> bool, -{ - fn drop(&mut self) { - struct BackshiftOnDrop<'a, 'b, T, F, A: Allocator> - where - F: FnMut(&mut T) -> bool, - { - drain: &'b mut DrainFilter<'a, T, F, A>, - } - - impl<'a, 'b, T, F, A: Allocator> Drop for BackshiftOnDrop<'a, 'b, T, F, A> - where - F: FnMut(&mut T) -> bool, - { - fn drop(&mut self) { - unsafe { - if self.drain.idx < self.drain.old_len && self.drain.del > 0 { - // This is a pretty messed up state, and there isn't really an - // obviously right thing to do. We don't want to keep trying - // to execute `pred`, so we just backshift all the unprocessed - // elements and tell the vec that they still exist. The backshift - // is required to prevent a double-drop of the last successfully - // drained item prior to a panic in the predicate. - let ptr = self.drain.vec.as_mut_ptr(); - let src = ptr.add(self.drain.idx); - let dst = src.sub(self.drain.del); - let tail_len = self.drain.old_len - self.drain.idx; - src.copy_to(dst, tail_len); - } - self.drain.vec.set_len(self.drain.old_len - self.drain.del); - } - } - } - - let backshift = BackshiftOnDrop { drain: self }; - - // Attempt to consume any remaining elements if the filter predicate - // has not yet panicked. We'll backshift any remaining elements - // whether we've already panicked or if the consumption here panics. - if !backshift.drain.panic_flag { - backshift.drain.for_each(drop); - } - } -} diff --git a/library/alloc/src/vec/mod.rs b/library/alloc/src/vec/mod.rs new file mode 100644 index 00000000000..c9fa41138cd --- /dev/null +++ b/library/alloc/src/vec/mod.rs @@ -0,0 +1,3725 @@ +// ignore-tidy-filelength +//! A contiguous growable array type with heap-allocated contents, written +//! `Vec`. +//! +//! Vectors have `O(1)` indexing, amortized `O(1)` push (to the end) and +//! `O(1)` pop (from the end). +//! +//! Vectors ensure they never allocate more than `isize::MAX` bytes. +//! +//! # Examples +//! +//! You can explicitly create a [`Vec`] with [`Vec::new`]: +//! +//! ``` +//! let v: Vec = Vec::new(); +//! ``` +//! +//! ...or by using the [`vec!`] macro: +//! +//! ``` +//! let v: Vec = vec![]; +//! +//! let v = vec![1, 2, 3, 4, 5]; +//! +//! let v = vec![0; 10]; // ten zeroes +//! ``` +//! +//! You can [`push`] values onto the end of a vector (which will grow the vector +//! as needed): +//! +//! ``` +//! let mut v = vec![1, 2]; +//! +//! v.push(3); +//! ``` +//! +//! Popping values works in much the same way: +//! +//! ``` +//! let mut v = vec![1, 2]; +//! +//! let two = v.pop(); +//! ``` +//! +//! Vectors also support indexing (through the [`Index`] and [`IndexMut`] traits): +//! +//! ``` +//! let mut v = vec![1, 2, 3]; +//! let three = v[2]; +//! v[1] = v[1] + 5; +//! ``` +//! +//! [`push`]: Vec::push + +#![stable(feature = "rust1", since = "1.0.0")] + +use core::cmp::{self, Ordering}; +use core::convert::TryFrom; +use core::fmt; +use core::hash::{Hash, Hasher}; +use core::intrinsics::{arith_offset, assume}; +use core::iter::{ + FromIterator, FusedIterator, InPlaceIterable, SourceIter, TrustedLen, TrustedRandomAccess, +}; +use core::marker::PhantomData; +use core::mem::{self, ManuallyDrop, MaybeUninit}; +use core::ops::{self, Index, IndexMut, Range, RangeBounds}; +use core::ptr::{self, NonNull}; +use core::slice::{self, SliceIndex}; + +use crate::alloc::{Allocator, Global}; +use crate::borrow::{Cow, ToOwned}; +use crate::boxed::Box; +use crate::collections::TryReserveError; +use crate::raw_vec::RawVec; + +/// A contiguous growable array type, written `Vec` but pronounced 'vector'. +/// +/// # Examples +/// +/// ``` +/// let mut vec = Vec::new(); +/// vec.push(1); +/// vec.push(2); +/// +/// assert_eq!(vec.len(), 2); +/// assert_eq!(vec[0], 1); +/// +/// assert_eq!(vec.pop(), Some(2)); +/// assert_eq!(vec.len(), 1); +/// +/// vec[0] = 7; +/// assert_eq!(vec[0], 7); +/// +/// vec.extend([1, 2, 3].iter().copied()); +/// +/// for x in &vec { +/// println!("{}", x); +/// } +/// assert_eq!(vec, [7, 1, 2, 3]); +/// ``` +/// +/// The [`vec!`] macro is provided to make initialization more convenient: +/// +/// ``` +/// let mut vec = vec![1, 2, 3]; +/// vec.push(4); +/// assert_eq!(vec, [1, 2, 3, 4]); +/// ``` +/// +/// It can also initialize each element of a `Vec` with a given value. +/// This may be more efficient than performing allocation and initialization +/// in separate steps, especially when initializing a vector of zeros: +/// +/// ``` +/// let vec = vec![0; 5]; +/// assert_eq!(vec, [0, 0, 0, 0, 0]); +/// +/// // The following is equivalent, but potentially slower: +/// let mut vec = Vec::with_capacity(5); +/// vec.resize(5, 0); +/// assert_eq!(vec, [0, 0, 0, 0, 0]); +/// ``` +/// +/// For more information, see +/// [Capacity and Reallocation](#capacity-and-reallocation). +/// +/// Use a `Vec` as an efficient stack: +/// +/// ``` +/// let mut stack = Vec::new(); +/// +/// stack.push(1); +/// stack.push(2); +/// stack.push(3); +/// +/// while let Some(top) = stack.pop() { +/// // Prints 3, 2, 1 +/// println!("{}", top); +/// } +/// ``` +/// +/// # Indexing +/// +/// The `Vec` type allows to access values by index, because it implements the +/// [`Index`] trait. An example will be more explicit: +/// +/// ``` +/// let v = vec![0, 2, 4, 6]; +/// println!("{}", v[1]); // it will display '2' +/// ``` +/// +/// However be careful: if you try to access an index which isn't in the `Vec`, +/// your software will panic! You cannot do this: +/// +/// ```should_panic +/// let v = vec![0, 2, 4, 6]; +/// println!("{}", v[6]); // it will panic! +/// ``` +/// +/// Use [`get`] and [`get_mut`] if you want to check whether the index is in +/// the `Vec`. +/// +/// # Slicing +/// +/// A `Vec` can be mutable. Slices, on the other hand, are read-only objects. +/// To get a [slice], use [`&`]. Example: +/// +/// ``` +/// fn read_slice(slice: &[usize]) { +/// // ... +/// } +/// +/// let v = vec![0, 1]; +/// read_slice(&v); +/// +/// // ... and that's all! +/// // you can also do it like this: +/// let u: &[usize] = &v; +/// // or like this: +/// let u: &[_] = &v; +/// ``` +/// +/// In Rust, it's more common to pass slices as arguments rather than vectors +/// when you just want to provide read access. The same goes for [`String`] and +/// [`&str`]. +/// +/// # Capacity and reallocation +/// +/// The capacity of a vector is the amount of space allocated for any future +/// elements that will be added onto the vector. This is not to be confused with +/// the *length* of a vector, which specifies the number of actual elements +/// within the vector. If a vector's length exceeds its capacity, its capacity +/// will automatically be increased, but its elements will have to be +/// reallocated. +/// +/// For example, a vector with capacity 10 and length 0 would be an empty vector +/// with space for 10 more elements. Pushing 10 or fewer elements onto the +/// vector will not change its capacity or cause reallocation to occur. However, +/// if the vector's length is increased to 11, it will have to reallocate, which +/// can be slow. For this reason, it is recommended to use [`Vec::with_capacity`] +/// whenever possible to specify how big the vector is expected to get. +/// +/// # Guarantees +/// +/// Due to its incredibly fundamental nature, `Vec` makes a lot of guarantees +/// about its design. This ensures that it's as low-overhead as possible in +/// the general case, and can be correctly manipulated in primitive ways +/// by unsafe code. Note that these guarantees refer to an unqualified `Vec`. +/// If additional type parameters are added (e.g., to support custom allocators), +/// overriding their defaults may change the behavior. +/// +/// Most fundamentally, `Vec` is and always will be a (pointer, capacity, length) +/// triplet. No more, no less. The order of these fields is completely +/// unspecified, and you should use the appropriate methods to modify these. +/// The pointer will never be null, so this type is null-pointer-optimized. +/// +/// However, the pointer may not actually point to allocated memory. In particular, +/// if you construct a `Vec` with capacity 0 via [`Vec::new`], [`vec![]`][`vec!`], +/// [`Vec::with_capacity(0)`][`Vec::with_capacity`], or by calling [`shrink_to_fit`] +/// on an empty Vec, it will not allocate memory. Similarly, if you store zero-sized +/// types inside a `Vec`, it will not allocate space for them. *Note that in this case +/// the `Vec` may not report a [`capacity`] of 0*. `Vec` will allocate if and only +/// if [`mem::size_of::`]`() * capacity() > 0`. In general, `Vec`'s allocation +/// details are very subtle — if you intend to allocate memory using a `Vec` +/// and use it for something else (either to pass to unsafe code, or to build your +/// own memory-backed collection), be sure to deallocate this memory by using +/// `from_raw_parts` to recover the `Vec` and then dropping it. +/// +/// If a `Vec` *has* allocated memory, then the memory it points to is on the heap +/// (as defined by the allocator Rust is configured to use by default), and its +/// pointer points to [`len`] initialized, contiguous elements in order (what +/// you would see if you coerced it to a slice), followed by [`capacity`]` - +/// `[`len`] logically uninitialized, contiguous elements. +/// +/// `Vec` will never perform a "small optimization" where elements are actually +/// stored on the stack for two reasons: +/// +/// * It would make it more difficult for unsafe code to correctly manipulate +/// a `Vec`. The contents of a `Vec` wouldn't have a stable address if it were +/// only moved, and it would be more difficult to determine if a `Vec` had +/// actually allocated memory. +/// +/// * It would penalize the general case, incurring an additional branch +/// on every access. +/// +/// `Vec` will never automatically shrink itself, even if completely empty. This +/// ensures no unnecessary allocations or deallocations occur. Emptying a `Vec` +/// and then filling it back up to the same [`len`] should incur no calls to +/// the allocator. If you wish to free up unused memory, use +/// [`shrink_to_fit`]. +/// +/// [`push`] and [`insert`] will never (re)allocate if the reported capacity is +/// sufficient. [`push`] and [`insert`] *will* (re)allocate if +/// [`len`]` == `[`capacity`]. That is, the reported capacity is completely +/// accurate, and can be relied on. It can even be used to manually free the memory +/// allocated by a `Vec` if desired. Bulk insertion methods *may* reallocate, even +/// when not necessary. +/// +/// `Vec` does not guarantee any particular growth strategy when reallocating +/// when full, nor when [`reserve`] is called. The current strategy is basic +/// and it may prove desirable to use a non-constant growth factor. Whatever +/// strategy is used will of course guarantee *O*(1) amortized [`push`]. +/// +/// `vec![x; n]`, `vec![a, b, c, d]`, and +/// [`Vec::with_capacity(n)`][`Vec::with_capacity`], will all produce a `Vec` +/// with exactly the requested capacity. If [`len`]` == `[`capacity`], +/// (as is the case for the [`vec!`] macro), then a `Vec` can be converted to +/// and from a [`Box<[T]>`][owned slice] without reallocating or moving the elements. +/// +/// `Vec` will not specifically overwrite any data that is removed from it, +/// but also won't specifically preserve it. Its uninitialized memory is +/// scratch space that it may use however it wants. It will generally just do +/// whatever is most efficient or otherwise easy to implement. Do not rely on +/// removed data to be erased for security purposes. Even if you drop a `Vec`, its +/// buffer may simply be reused by another `Vec`. Even if you zero a `Vec`'s memory +/// first, that may not actually happen because the optimizer does not consider +/// this a side-effect that must be preserved. There is one case which we will +/// not break, however: using `unsafe` code to write to the excess capacity, +/// and then increasing the length to match, is always valid. +/// +/// `Vec` does not currently guarantee the order in which elements are dropped. +/// The order has changed in the past and may change again. +/// +/// [`get`]: ../../std/vec/struct.Vec.html#method.get +/// [`get_mut`]: ../../std/vec/struct.Vec.html#method.get_mut +/// [`String`]: crate::string::String +/// [`&str`]: type@str +/// [`shrink_to_fit`]: Vec::shrink_to_fit +/// [`capacity`]: Vec::capacity +/// [`mem::size_of::`]: core::mem::size_of +/// [`len`]: Vec::len +/// [`push`]: Vec::push +/// [`insert`]: Vec::insert +/// [`reserve`]: Vec::reserve +/// [owned slice]: Box +/// [slice]: ../../std/primitive.slice.html +/// [`&`]: ../../std/primitive.reference.html +#[stable(feature = "rust1", since = "1.0.0")] +#[cfg_attr(not(test), rustc_diagnostic_item = "vec_type")] +pub struct Vec { + buf: RawVec, + len: usize, +} + +//////////////////////////////////////////////////////////////////////////////// +// Inherent methods +//////////////////////////////////////////////////////////////////////////////// + +impl Vec { + /// Constructs a new, empty `Vec`. + /// + /// The vector will not allocate until elements are pushed onto it. + /// + /// # Examples + /// + /// ``` + /// # #![allow(unused_mut)] + /// let mut vec: Vec = Vec::new(); + /// ``` + #[inline] + #[rustc_const_stable(feature = "const_vec_new", since = "1.39.0")] + #[stable(feature = "rust1", since = "1.0.0")] + pub const fn new() -> Self { + Vec { buf: RawVec::NEW, len: 0 } + } + + /// Constructs a new, empty `Vec` with the specified capacity. + /// + /// The vector will be able to hold exactly `capacity` elements without + /// reallocating. If `capacity` is 0, the vector will not allocate. + /// + /// It is important to note that although the returned vector has the + /// *capacity* specified, the vector will have a zero *length*. For an + /// explanation of the difference between length and capacity, see + /// *[Capacity and reallocation]*. + /// + /// [Capacity and reallocation]: #capacity-and-reallocation + /// + /// # Examples + /// + /// ``` + /// let mut vec = Vec::with_capacity(10); + /// + /// // The vector contains no items, even though it has capacity for more + /// assert_eq!(vec.len(), 0); + /// assert_eq!(vec.capacity(), 10); + /// + /// // These are all done without reallocating... + /// for i in 0..10 { + /// vec.push(i); + /// } + /// assert_eq!(vec.len(), 10); + /// assert_eq!(vec.capacity(), 10); + /// + /// // ...but this may make the vector reallocate + /// vec.push(11); + /// assert_eq!(vec.len(), 11); + /// assert!(vec.capacity() >= 11); + /// ``` + #[inline] + #[stable(feature = "rust1", since = "1.0.0")] + pub fn with_capacity(capacity: usize) -> Self { + Self::with_capacity_in(capacity, Global) + } + + /// Creates a `Vec` directly from the raw components of another vector. + /// + /// # Safety + /// + /// This is highly unsafe, due to the number of invariants that aren't + /// checked: + /// + /// * `ptr` needs to have been previously allocated via [`String`]/`Vec` + /// (at least, it's highly likely to be incorrect if it wasn't). + /// * `T` needs to have the same size and alignment as what `ptr` was allocated with. + /// (`T` having a less strict alignment is not sufficient, the alignment really + /// needs to be equal to satisfy the [`dealloc`] requirement that memory must be + /// allocated and deallocated with the same layout.) + /// * `length` needs to be less than or equal to `capacity`. + /// * `capacity` needs to be the capacity that the pointer was allocated with. + /// + /// Violating these may cause problems like corrupting the allocator's + /// internal data structures. For example it is **not** safe + /// to build a `Vec` from a pointer to a C `char` array with length `size_t`. + /// It's also not safe to build one from a `Vec` and its length, because + /// the allocator cares about the alignment, and these two types have different + /// alignments. The buffer was allocated with alignment 2 (for `u16`), but after + /// turning it into a `Vec` it'll be deallocated with alignment 1. + /// + /// The ownership of `ptr` is effectively transferred to the + /// `Vec` which may then deallocate, reallocate or change the + /// contents of memory pointed to by the pointer at will. Ensure + /// that nothing else uses the pointer after calling this + /// function. + /// + /// [`String`]: crate::string::String + /// [`dealloc`]: crate::alloc::GlobalAlloc::dealloc + /// + /// # Examples + /// + /// ``` + /// use std::ptr; + /// use std::mem; + /// + /// let v = vec![1, 2, 3]; + /// + // FIXME Update this when vec_into_raw_parts is stabilized + /// // Prevent running `v`'s destructor so we are in complete control + /// // of the allocation. + /// let mut v = mem::ManuallyDrop::new(v); + /// + /// // Pull out the various important pieces of information about `v` + /// let p = v.as_mut_ptr(); + /// let len = v.len(); + /// let cap = v.capacity(); + /// + /// unsafe { + /// // Overwrite memory with 4, 5, 6 + /// for i in 0..len as isize { + /// ptr::write(p.offset(i), 4 + i); + /// } + /// + /// // Put everything back together into a Vec + /// let rebuilt = Vec::from_raw_parts(p, len, cap); + /// assert_eq!(rebuilt, [4, 5, 6]); + /// } + /// ``` + #[inline] + #[stable(feature = "rust1", since = "1.0.0")] + pub unsafe fn from_raw_parts(ptr: *mut T, length: usize, capacity: usize) -> Self { + unsafe { Self::from_raw_parts_in(ptr, length, capacity, Global) } + } +} + +impl Vec { + /// Constructs a new, empty `Vec`. + /// + /// The vector will not allocate until elements are pushed onto it. + /// + /// # Examples + /// + /// ``` + /// #![feature(allocator_api)] + /// + /// use std::alloc::System; + /// + /// # #[allow(unused_mut)] + /// let mut vec: Vec = Vec::new_in(System); + /// ``` + #[inline] + #[unstable(feature = "allocator_api", issue = "32838")] + pub const fn new_in(alloc: A) -> Self { + Vec { buf: RawVec::new_in(alloc), len: 0 } + } + + /// Constructs a new, empty `Vec` with the specified capacity with the provided + /// allocator. + /// + /// The vector will be able to hold exactly `capacity` elements without + /// reallocating. If `capacity` is 0, the vector will not allocate. + /// + /// It is important to note that although the returned vector has the + /// *capacity* specified, the vector will have a zero *length*. For an + /// explanation of the difference between length and capacity, see + /// *[Capacity and reallocation]*. + /// + /// [Capacity and reallocation]: #capacity-and-reallocation + /// + /// # Examples + /// + /// ``` + /// #![feature(allocator_api)] + /// + /// use std::alloc::System; + /// + /// let mut vec = Vec::with_capacity_in(10, System); + /// + /// // The vector contains no items, even though it has capacity for more + /// assert_eq!(vec.len(), 0); + /// assert_eq!(vec.capacity(), 10); + /// + /// // These are all done without reallocating... + /// for i in 0..10 { + /// vec.push(i); + /// } + /// assert_eq!(vec.len(), 10); + /// assert_eq!(vec.capacity(), 10); + /// + /// // ...but this may make the vector reallocate + /// vec.push(11); + /// assert_eq!(vec.len(), 11); + /// assert!(vec.capacity() >= 11); + /// ``` + #[inline] + #[unstable(feature = "allocator_api", issue = "32838")] + pub fn with_capacity_in(capacity: usize, alloc: A) -> Self { + Vec { buf: RawVec::with_capacity_in(capacity, alloc), len: 0 } + } + + /// Creates a `Vec` directly from the raw components of another vector. + /// + /// # Safety + /// + /// This is highly unsafe, due to the number of invariants that aren't + /// checked: + /// + /// * `ptr` needs to have been previously allocated via [`String`]/`Vec` + /// (at least, it's highly likely to be incorrect if it wasn't). + /// * `T` needs to have the same size and alignment as what `ptr` was allocated with. + /// (`T` having a less strict alignment is not sufficient, the alignment really + /// needs to be equal to satisfy the [`dealloc`] requirement that memory must be + /// allocated and deallocated with the same layout.) + /// * `length` needs to be less than or equal to `capacity`. + /// * `capacity` needs to be the capacity that the pointer was allocated with. + /// + /// Violating these may cause problems like corrupting the allocator's + /// internal data structures. For example it is **not** safe + /// to build a `Vec` from a pointer to a C `char` array with length `size_t`. + /// It's also not safe to build one from a `Vec` and its length, because + /// the allocator cares about the alignment, and these two types have different + /// alignments. The buffer was allocated with alignment 2 (for `u16`), but after + /// turning it into a `Vec` it'll be deallocated with alignment 1. + /// + /// The ownership of `ptr` is effectively transferred to the + /// `Vec` which may then deallocate, reallocate or change the + /// contents of memory pointed to by the pointer at will. Ensure + /// that nothing else uses the pointer after calling this + /// function. + /// + /// [`String`]: crate::string::String + /// [`dealloc`]: crate::alloc::GlobalAlloc::dealloc + /// + /// # Examples + /// + /// ``` + /// #![feature(allocator_api)] + /// + /// use std::alloc::System; + /// + /// use std::ptr; + /// use std::mem; + /// + /// let mut v = Vec::with_capacity_in(3, System); + /// v.push(1); + /// v.push(2); + /// v.push(3); + /// + // FIXME Update this when vec_into_raw_parts is stabilized + /// // Prevent running `v`'s destructor so we are in complete control + /// // of the allocation. + /// let mut v = mem::ManuallyDrop::new(v); + /// + /// // Pull out the various important pieces of information about `v` + /// let p = v.as_mut_ptr(); + /// let len = v.len(); + /// let cap = v.capacity(); + /// let alloc = v.allocator(); + /// + /// unsafe { + /// // Overwrite memory with 4, 5, 6 + /// for i in 0..len as isize { + /// ptr::write(p.offset(i), 4 + i); + /// } + /// + /// // Put everything back together into a Vec + /// let rebuilt = Vec::from_raw_parts_in(p, len, cap, alloc.clone()); + /// assert_eq!(rebuilt, [4, 5, 6]); + /// } + /// ``` + #[inline] + #[unstable(feature = "allocator_api", issue = "32838")] + pub unsafe fn from_raw_parts_in(ptr: *mut T, length: usize, capacity: usize, alloc: A) -> Self { + unsafe { Vec { buf: RawVec::from_raw_parts_in(ptr, capacity, alloc), len: length } } + } + + /// Decomposes a `Vec` into its raw components. + /// + /// Returns the raw pointer to the underlying data, the length of + /// the vector (in elements), and the allocated capacity of the + /// data (in elements). These are the same arguments in the same + /// order as the arguments to [`from_raw_parts`]. + /// + /// After calling this function, the caller is responsible for the + /// memory previously managed by the `Vec`. The only way to do + /// this is to convert the raw pointer, length, and capacity back + /// into a `Vec` with the [`from_raw_parts`] function, allowing + /// the destructor to perform the cleanup. + /// + /// [`from_raw_parts`]: Vec::from_raw_parts + /// + /// # Examples + /// + /// ``` + /// #![feature(vec_into_raw_parts)] + /// let v: Vec = vec![-1, 0, 1]; + /// + /// let (ptr, len, cap) = v.into_raw_parts(); + /// + /// let rebuilt = unsafe { + /// // We can now make changes to the components, such as + /// // transmuting the raw pointer to a compatible type. + /// let ptr = ptr as *mut u32; + /// + /// Vec::from_raw_parts(ptr, len, cap) + /// }; + /// assert_eq!(rebuilt, [4294967295, 0, 1]); + /// ``` + #[unstable(feature = "vec_into_raw_parts", reason = "new API", issue = "65816")] + pub fn into_raw_parts(self) -> (*mut T, usize, usize) { + let mut me = ManuallyDrop::new(self); + (me.as_mut_ptr(), me.len(), me.capacity()) + } + + /// Decomposes a `Vec` into its raw components. + /// + /// Returns the raw pointer to the underlying data, the length of the vector (in elements), + /// the allocated capacity of the data (in elements), and the allocator. These are the same + /// arguments in the same order as the arguments to [`from_raw_parts_in`]. + /// + /// After calling this function, the caller is responsible for the + /// memory previously managed by the `Vec`. The only way to do + /// this is to convert the raw pointer, length, and capacity back + /// into a `Vec` with the [`from_raw_parts_in`] function, allowing + /// the destructor to perform the cleanup. + /// + /// [`from_raw_parts_in`]: Vec::from_raw_parts_in + /// + /// # Examples + /// + /// ``` + /// #![feature(allocator_api, vec_into_raw_parts)] + /// + /// use std::alloc::System; + /// + /// let mut v: Vec = Vec::new_in(System); + /// v.push(-1); + /// v.push(0); + /// v.push(1); + /// + /// let (ptr, len, cap, alloc) = v.into_raw_parts_with_alloc(); + /// + /// let rebuilt = unsafe { + /// // We can now make changes to the components, such as + /// // transmuting the raw pointer to a compatible type. + /// let ptr = ptr as *mut u32; + /// + /// Vec::from_raw_parts_in(ptr, len, cap, alloc) + /// }; + /// assert_eq!(rebuilt, [4294967295, 0, 1]); + /// ``` + #[unstable(feature = "allocator_api", issue = "32838")] + // #[unstable(feature = "vec_into_raw_parts", reason = "new API", issue = "65816")] + pub fn into_raw_parts_with_alloc(self) -> (*mut T, usize, usize, A) { + let mut me = ManuallyDrop::new(self); + let len = me.len(); + let capacity = me.capacity(); + let ptr = me.as_mut_ptr(); + let alloc = unsafe { ptr::read(me.allocator()) }; + (ptr, len, capacity, alloc) + } + + /// Returns the number of elements the vector can hold without + /// reallocating. + /// + /// # Examples + /// + /// ``` + /// let vec: Vec = Vec::with_capacity(10); + /// assert_eq!(vec.capacity(), 10); + /// ``` + #[inline] + #[stable(feature = "rust1", since = "1.0.0")] + pub fn capacity(&self) -> usize { + self.buf.capacity() + } + + /// Reserves capacity for at least `additional` more elements to be inserted + /// in the given `Vec`. The collection may reserve more space to avoid + /// frequent reallocations. After calling `reserve`, capacity will be + /// greater than or equal to `self.len() + additional`. Does nothing if + /// capacity is already sufficient. + /// + /// # Panics + /// + /// Panics if the new capacity exceeds `isize::MAX` bytes. + /// + /// # Examples + /// + /// ``` + /// let mut vec = vec![1]; + /// vec.reserve(10); + /// assert!(vec.capacity() >= 11); + /// ``` + #[stable(feature = "rust1", since = "1.0.0")] + pub fn reserve(&mut self, additional: usize) { + self.buf.reserve(self.len, additional); + } + + /// Reserves the minimum capacity for exactly `additional` more elements to + /// be inserted in the given `Vec`. After calling `reserve_exact`, + /// capacity will be greater than or equal to `self.len() + additional`. + /// Does nothing if the capacity is already sufficient. + /// + /// Note that the allocator may give the collection more space than it + /// requests. Therefore, capacity can not be relied upon to be precisely + /// minimal. Prefer `reserve` if future insertions are expected. + /// + /// # Panics + /// + /// Panics if the new capacity overflows `usize`. + /// + /// # Examples + /// + /// ``` + /// let mut vec = vec![1]; + /// vec.reserve_exact(10); + /// assert!(vec.capacity() >= 11); + /// ``` + #[stable(feature = "rust1", since = "1.0.0")] + pub fn reserve_exact(&mut self, additional: usize) { + self.buf.reserve_exact(self.len, additional); + } + + /// Tries to reserve capacity for at least `additional` more elements to be inserted + /// in the given `Vec`. The collection may reserve more space to avoid + /// frequent reallocations. After calling `try_reserve`, capacity will be + /// greater than or equal to `self.len() + additional`. Does nothing if + /// capacity is already sufficient. + /// + /// # Errors + /// + /// If the capacity overflows, or the allocator reports a failure, then an error + /// is returned. + /// + /// # Examples + /// + /// ``` + /// #![feature(try_reserve)] + /// use std::collections::TryReserveError; + /// + /// fn process_data(data: &[u32]) -> Result, TryReserveError> { + /// let mut output = Vec::new(); + /// + /// // Pre-reserve the memory, exiting if we can't + /// output.try_reserve(data.len())?; + /// + /// // Now we know this can't OOM in the middle of our complex work + /// output.extend(data.iter().map(|&val| { + /// val * 2 + 5 // very complicated + /// })); + /// + /// Ok(output) + /// } + /// # process_data(&[1, 2, 3]).expect("why is the test harness OOMing on 12 bytes?"); + /// ``` + #[unstable(feature = "try_reserve", reason = "new API", issue = "48043")] + pub fn try_reserve(&mut self, additional: usize) -> Result<(), TryReserveError> { + self.buf.try_reserve(self.len, additional) + } + + /// Tries to reserve the minimum capacity for exactly `additional` + /// elements to be inserted in the given `Vec`. After calling + /// `try_reserve_exact`, capacity will be greater than or equal to + /// `self.len() + additional` if it returns `Ok(())`. + /// Does nothing if the capacity is already sufficient. + /// + /// Note that the allocator may give the collection more space than it + /// requests. Therefore, capacity can not be relied upon to be precisely + /// minimal. Prefer `reserve` if future insertions are expected. + /// + /// # Errors + /// + /// If the capacity overflows, or the allocator reports a failure, then an error + /// is returned. + /// + /// # Examples + /// + /// ``` + /// #![feature(try_reserve)] + /// use std::collections::TryReserveError; + /// + /// fn process_data(data: &[u32]) -> Result, TryReserveError> { + /// let mut output = Vec::new(); + /// + /// // Pre-reserve the memory, exiting if we can't + /// output.try_reserve_exact(data.len())?; + /// + /// // Now we know this can't OOM in the middle of our complex work + /// output.extend(data.iter().map(|&val| { + /// val * 2 + 5 // very complicated + /// })); + /// + /// Ok(output) + /// } + /// # process_data(&[1, 2, 3]).expect("why is the test harness OOMing on 12 bytes?"); + /// ``` + #[unstable(feature = "try_reserve", reason = "new API", issue = "48043")] + pub fn try_reserve_exact(&mut self, additional: usize) -> Result<(), TryReserveError> { + self.buf.try_reserve_exact(self.len, additional) + } + + /// Shrinks the capacity of the vector as much as possible. + /// + /// It will drop down as close as possible to the length but the allocator + /// may still inform the vector that there is space for a few more elements. + /// + /// # Examples + /// + /// ``` + /// let mut vec = Vec::with_capacity(10); + /// vec.extend([1, 2, 3].iter().cloned()); + /// assert_eq!(vec.capacity(), 10); + /// vec.shrink_to_fit(); + /// assert!(vec.capacity() >= 3); + /// ``` + #[stable(feature = "rust1", since = "1.0.0")] + pub fn shrink_to_fit(&mut self) { + // The capacity is never less than the length, and there's nothing to do when + // they are equal, so we can avoid the panic case in `RawVec::shrink_to_fit` + // by only calling it with a greater capacity. + if self.capacity() > self.len { + self.buf.shrink_to_fit(self.len); + } + } + + /// Shrinks the capacity of the vector with a lower bound. + /// + /// The capacity will remain at least as large as both the length + /// and the supplied value. + /// + /// # Panics + /// + /// Panics if the current capacity is smaller than the supplied + /// minimum capacity. + /// + /// # Examples + /// + /// ``` + /// #![feature(shrink_to)] + /// let mut vec = Vec::with_capacity(10); + /// vec.extend([1, 2, 3].iter().cloned()); + /// assert_eq!(vec.capacity(), 10); + /// vec.shrink_to(4); + /// assert!(vec.capacity() >= 4); + /// vec.shrink_to(0); + /// assert!(vec.capacity() >= 3); + /// ``` + #[unstable(feature = "shrink_to", reason = "new API", issue = "56431")] + pub fn shrink_to(&mut self, min_capacity: usize) { + self.buf.shrink_to_fit(cmp::max(self.len, min_capacity)); + } + + /// Converts the vector into [`Box<[T]>`][owned slice]. + /// + /// Note that this will drop any excess capacity. + /// + /// [owned slice]: Box + /// + /// # Examples + /// + /// ``` + /// let v = vec![1, 2, 3]; + /// + /// let slice = v.into_boxed_slice(); + /// ``` + /// + /// Any excess capacity is removed: + /// + /// ``` + /// let mut vec = Vec::with_capacity(10); + /// vec.extend([1, 2, 3].iter().cloned()); + /// + /// assert_eq!(vec.capacity(), 10); + /// let slice = vec.into_boxed_slice(); + /// assert_eq!(slice.into_vec().capacity(), 3); + /// ``` + #[stable(feature = "rust1", since = "1.0.0")] + pub fn into_boxed_slice(mut self) -> Box<[T], A> { + unsafe { + self.shrink_to_fit(); + let me = ManuallyDrop::new(self); + let buf = ptr::read(&me.buf); + let len = me.len(); + buf.into_box(len).assume_init() + } + } + + /// Shortens the vector, keeping the first `len` elements and dropping + /// the rest. + /// + /// If `len` is greater than the vector's current length, this has no + /// effect. + /// + /// The [`drain`] method can emulate `truncate`, but causes the excess + /// elements to be returned instead of dropped. + /// + /// Note that this method has no effect on the allocated capacity + /// of the vector. + /// + /// # Examples + /// + /// Truncating a five element vector to two elements: + /// + /// ``` + /// let mut vec = vec![1, 2, 3, 4, 5]; + /// vec.truncate(2); + /// assert_eq!(vec, [1, 2]); + /// ``` + /// + /// No truncation occurs when `len` is greater than the vector's current + /// length: + /// + /// ``` + /// let mut vec = vec![1, 2, 3]; + /// vec.truncate(8); + /// assert_eq!(vec, [1, 2, 3]); + /// ``` + /// + /// Truncating when `len == 0` is equivalent to calling the [`clear`] + /// method. + /// + /// ``` + /// let mut vec = vec![1, 2, 3]; + /// vec.truncate(0); + /// assert_eq!(vec, []); + /// ``` + /// + /// [`clear`]: Vec::clear + /// [`drain`]: Vec::drain + #[stable(feature = "rust1", since = "1.0.0")] + pub fn truncate(&mut self, len: usize) { + // This is safe because: + // + // * the slice passed to `drop_in_place` is valid; the `len > self.len` + // case avoids creating an invalid slice, and + // * the `len` of the vector is shrunk before calling `drop_in_place`, + // such that no value will be dropped twice in case `drop_in_place` + // were to panic once (if it panics twice, the program aborts). + unsafe { + if len > self.len { + return; + } + let remaining_len = self.len - len; + let s = ptr::slice_from_raw_parts_mut(self.as_mut_ptr().add(len), remaining_len); + self.len = len; + ptr::drop_in_place(s); + } + } + + /// Extracts a slice containing the entire vector. + /// + /// Equivalent to `&s[..]`. + /// + /// # Examples + /// + /// ``` + /// use std::io::{self, Write}; + /// let buffer = vec![1, 2, 3, 5, 8]; + /// io::sink().write(buffer.as_slice()).unwrap(); + /// ``` + #[inline] + #[stable(feature = "vec_as_slice", since = "1.7.0")] + pub fn as_slice(&self) -> &[T] { + self + } + + /// Extracts a mutable slice of the entire vector. + /// + /// Equivalent to `&mut s[..]`. + /// + /// # Examples + /// + /// ``` + /// use std::io::{self, Read}; + /// let mut buffer = vec![0; 3]; + /// io::repeat(0b101).read_exact(buffer.as_mut_slice()).unwrap(); + /// ``` + #[inline] + #[stable(feature = "vec_as_slice", since = "1.7.0")] + pub fn as_mut_slice(&mut self) -> &mut [T] { + self + } + + /// Returns a raw pointer to the vector's buffer. + /// + /// The caller must ensure that the vector outlives the pointer this + /// function returns, or else it will end up pointing to garbage. + /// Modifying the vector may cause its buffer to be reallocated, + /// which would also make any pointers to it invalid. + /// + /// The caller must also ensure that the memory the pointer (non-transitively) points to + /// is never written to (except inside an `UnsafeCell`) using this pointer or any pointer + /// derived from it. If you need to mutate the contents of the slice, use [`as_mut_ptr`]. + /// + /// # Examples + /// + /// ``` + /// let x = vec![1, 2, 4]; + /// let x_ptr = x.as_ptr(); + /// + /// unsafe { + /// for i in 0..x.len() { + /// assert_eq!(*x_ptr.add(i), 1 << i); + /// } + /// } + /// ``` + /// + /// [`as_mut_ptr`]: Vec::as_mut_ptr + #[stable(feature = "vec_as_ptr", since = "1.37.0")] + #[inline] + pub fn as_ptr(&self) -> *const T { + // We shadow the slice method of the same name to avoid going through + // `deref`, which creates an intermediate reference. + let ptr = self.buf.ptr(); + unsafe { + assume(!ptr.is_null()); + } + ptr + } + + /// Returns an unsafe mutable pointer to the vector's buffer. + /// + /// The caller must ensure that the vector outlives the pointer this + /// function returns, or else it will end up pointing to garbage. + /// Modifying the vector may cause its buffer to be reallocated, + /// which would also make any pointers to it invalid. + /// + /// # Examples + /// + /// ``` + /// // Allocate vector big enough for 4 elements. + /// let size = 4; + /// let mut x: Vec = Vec::with_capacity(size); + /// let x_ptr = x.as_mut_ptr(); + /// + /// // Initialize elements via raw pointer writes, then set length. + /// unsafe { + /// for i in 0..size { + /// *x_ptr.add(i) = i as i32; + /// } + /// x.set_len(size); + /// } + /// assert_eq!(&*x, &[0, 1, 2, 3]); + /// ``` + #[stable(feature = "vec_as_ptr", since = "1.37.0")] + #[inline] + pub fn as_mut_ptr(&mut self) -> *mut T { + // We shadow the slice method of the same name to avoid going through + // `deref_mut`, which creates an intermediate reference. + let ptr = self.buf.ptr(); + unsafe { + assume(!ptr.is_null()); + } + ptr + } + + /// Returns a reference to the underlying allocator. + #[unstable(feature = "allocator_api", issue = "32838")] + #[inline] + pub fn allocator(&self) -> &A { + self.buf.allocator() + } + + /// Forces the length of the vector to `new_len`. + /// + /// This is a low-level operation that maintains none of the normal + /// invariants of the type. Normally changing the length of a vector + /// is done using one of the safe operations instead, such as + /// [`truncate`], [`resize`], [`extend`], or [`clear`]. + /// + /// [`truncate`]: Vec::truncate + /// [`resize`]: Vec::resize + /// [`extend`]: Extend::extend + /// [`clear`]: Vec::clear + /// + /// # Safety + /// + /// - `new_len` must be less than or equal to [`capacity()`]. + /// - The elements at `old_len..new_len` must be initialized. + /// + /// [`capacity()`]: Vec::capacity + /// + /// # Examples + /// + /// This method can be useful for situations in which the vector + /// is serving as a buffer for other code, particularly over FFI: + /// + /// ```no_run + /// # #![allow(dead_code)] + /// # // This is just a minimal skeleton for the doc example; + /// # // don't use this as a starting point for a real library. + /// # pub struct StreamWrapper { strm: *mut std::ffi::c_void } + /// # const Z_OK: i32 = 0; + /// # extern "C" { + /// # fn deflateGetDictionary( + /// # strm: *mut std::ffi::c_void, + /// # dictionary: *mut u8, + /// # dictLength: *mut usize, + /// # ) -> i32; + /// # } + /// # impl StreamWrapper { + /// pub fn get_dictionary(&self) -> Option> { + /// // Per the FFI method's docs, "32768 bytes is always enough". + /// let mut dict = Vec::with_capacity(32_768); + /// let mut dict_length = 0; + /// // SAFETY: When `deflateGetDictionary` returns `Z_OK`, it holds that: + /// // 1. `dict_length` elements were initialized. + /// // 2. `dict_length` <= the capacity (32_768) + /// // which makes `set_len` safe to call. + /// unsafe { + /// // Make the FFI call... + /// let r = deflateGetDictionary(self.strm, dict.as_mut_ptr(), &mut dict_length); + /// if r == Z_OK { + /// // ...and update the length to what was initialized. + /// dict.set_len(dict_length); + /// Some(dict) + /// } else { + /// None + /// } + /// } + /// } + /// # } + /// ``` + /// + /// While the following example is sound, there is a memory leak since + /// the inner vectors were not freed prior to the `set_len` call: + /// + /// ``` + /// let mut vec = vec![vec![1, 0, 0], + /// vec![0, 1, 0], + /// vec![0, 0, 1]]; + /// // SAFETY: + /// // 1. `old_len..0` is empty so no elements need to be initialized. + /// // 2. `0 <= capacity` always holds whatever `capacity` is. + /// unsafe { + /// vec.set_len(0); + /// } + /// ``` + /// + /// Normally, here, one would use [`clear`] instead to correctly drop + /// the contents and thus not leak memory. + #[inline] + #[stable(feature = "rust1", since = "1.0.0")] + pub unsafe fn set_len(&mut self, new_len: usize) { + debug_assert!(new_len <= self.capacity()); + + self.len = new_len; + } + + /// Removes an element from the vector and returns it. + /// + /// The removed element is replaced by the last element of the vector. + /// + /// This does not preserve ordering, but is O(1). + /// + /// # Panics + /// + /// Panics if `index` is out of bounds. + /// + /// # Examples + /// + /// ``` + /// let mut v = vec!["foo", "bar", "baz", "qux"]; + /// + /// assert_eq!(v.swap_remove(1), "bar"); + /// assert_eq!(v, ["foo", "qux", "baz"]); + /// + /// assert_eq!(v.swap_remove(0), "foo"); + /// assert_eq!(v, ["baz", "qux"]); + /// ``` + #[inline] + #[stable(feature = "rust1", since = "1.0.0")] + pub fn swap_remove(&mut self, index: usize) -> T { + #[cold] + #[inline(never)] + fn assert_failed(index: usize, len: usize) -> ! { + panic!("swap_remove index (is {}) should be < len (is {})", index, len); + } + + let len = self.len(); + if index >= len { + assert_failed(index, len); + } + unsafe { + // We replace self[index] with the last element. Note that if the + // bounds check above succeeds there must be a last element (which + // can be self[index] itself). + let last = ptr::read(self.as_ptr().add(len - 1)); + let hole = self.as_mut_ptr().add(index); + self.set_len(len - 1); + ptr::replace(hole, last) + } + } + + /// Inserts an element at position `index` within the vector, shifting all + /// elements after it to the right. + /// + /// # Panics + /// + /// Panics if `index > len`. + /// + /// # Examples + /// + /// ``` + /// let mut vec = vec![1, 2, 3]; + /// vec.insert(1, 4); + /// assert_eq!(vec, [1, 4, 2, 3]); + /// vec.insert(4, 5); + /// assert_eq!(vec, [1, 4, 2, 3, 5]); + /// ``` + #[stable(feature = "rust1", since = "1.0.0")] + pub fn insert(&mut self, index: usize, element: T) { + #[cold] + #[inline(never)] + fn assert_failed(index: usize, len: usize) -> ! { + panic!("insertion index (is {}) should be <= len (is {})", index, len); + } + + let len = self.len(); + if index > len { + assert_failed(index, len); + } + + // space for the new element + if len == self.buf.capacity() { + self.reserve(1); + } + + unsafe { + // infallible + // The spot to put the new value + { + let p = self.as_mut_ptr().add(index); + // Shift everything over to make space. (Duplicating the + // `index`th element into two consecutive places.) + ptr::copy(p, p.offset(1), len - index); + // Write it in, overwriting the first copy of the `index`th + // element. + ptr::write(p, element); + } + self.set_len(len + 1); + } + } + + /// Removes and returns the element at position `index` within the vector, + /// shifting all elements after it to the left. + /// + /// # Panics + /// + /// Panics if `index` is out of bounds. + /// + /// # Examples + /// + /// ``` + /// let mut v = vec![1, 2, 3]; + /// assert_eq!(v.remove(1), 2); + /// assert_eq!(v, [1, 3]); + /// ``` + #[stable(feature = "rust1", since = "1.0.0")] + pub fn remove(&mut self, index: usize) -> T { + #[cold] + #[inline(never)] + fn assert_failed(index: usize, len: usize) -> ! { + panic!("removal index (is {}) should be < len (is {})", index, len); + } + + let len = self.len(); + if index >= len { + assert_failed(index, len); + } + unsafe { + // infallible + let ret; + { + // the place we are taking from. + let ptr = self.as_mut_ptr().add(index); + // copy it out, unsafely having a copy of the value on + // the stack and in the vector at the same time. + ret = ptr::read(ptr); + + // Shift everything down to fill in that spot. + ptr::copy(ptr.offset(1), ptr, len - index - 1); + } + self.set_len(len - 1); + ret + } + } + + /// Retains only the elements specified by the predicate. + /// + /// In other words, remove all elements `e` such that `f(&e)` returns `false`. + /// This method operates in place, visiting each element exactly once in the + /// original order, and preserves the order of the retained elements. + /// + /// # Examples + /// + /// ``` + /// let mut vec = vec![1, 2, 3, 4]; + /// vec.retain(|&x| x % 2 == 0); + /// assert_eq!(vec, [2, 4]); + /// ``` + /// + /// The exact order may be useful for tracking external state, like an index. + /// + /// ``` + /// let mut vec = vec![1, 2, 3, 4, 5]; + /// let keep = [false, true, true, false, true]; + /// let mut i = 0; + /// vec.retain(|_| (keep[i], i += 1).0); + /// assert_eq!(vec, [2, 3, 5]); + /// ``` + #[stable(feature = "rust1", since = "1.0.0")] + pub fn retain(&mut self, mut f: F) + where + F: FnMut(&T) -> bool, + { + let len = self.len(); + let mut del = 0; + { + let v = &mut **self; + + for i in 0..len { + if !f(&v[i]) { + del += 1; + } else if del > 0 { + v.swap(i - del, i); + } + } + } + if del > 0 { + self.truncate(len - del); + } + } + + /// Removes all but the first of consecutive elements in the vector that resolve to the same + /// key. + /// + /// If the vector is sorted, this removes all duplicates. + /// + /// # Examples + /// + /// ``` + /// let mut vec = vec![10, 20, 21, 30, 20]; + /// + /// vec.dedup_by_key(|i| *i / 10); + /// + /// assert_eq!(vec, [10, 20, 30, 20]); + /// ``` + #[stable(feature = "dedup_by", since = "1.16.0")] + #[inline] + pub fn dedup_by_key(&mut self, mut key: F) + where + F: FnMut(&mut T) -> K, + K: PartialEq, + { + self.dedup_by(|a, b| key(a) == key(b)) + } + + /// Removes all but the first of consecutive elements in the vector satisfying a given equality + /// relation. + /// + /// The `same_bucket` function is passed references to two elements from the vector and + /// must determine if the elements compare equal. The elements are passed in opposite order + /// from their order in the slice, so if `same_bucket(a, b)` returns `true`, `a` is removed. + /// + /// If the vector is sorted, this removes all duplicates. + /// + /// # Examples + /// + /// ``` + /// let mut vec = vec!["foo", "bar", "Bar", "baz", "bar"]; + /// + /// vec.dedup_by(|a, b| a.eq_ignore_ascii_case(b)); + /// + /// assert_eq!(vec, ["foo", "bar", "baz", "bar"]); + /// ``` + #[stable(feature = "dedup_by", since = "1.16.0")] + pub fn dedup_by(&mut self, same_bucket: F) + where + F: FnMut(&mut T, &mut T) -> bool, + { + let len = { + let (dedup, _) = self.as_mut_slice().partition_dedup_by(same_bucket); + dedup.len() + }; + self.truncate(len); + } + + /// Appends an element to the back of a collection. + /// + /// # Panics + /// + /// Panics if the new capacity exceeds `isize::MAX` bytes. + /// + /// # Examples + /// + /// ``` + /// let mut vec = vec![1, 2]; + /// vec.push(3); + /// assert_eq!(vec, [1, 2, 3]); + /// ``` + #[inline] + #[stable(feature = "rust1", since = "1.0.0")] + pub fn push(&mut self, value: T) { + // This will panic or abort if we would allocate > isize::MAX bytes + // or if the length increment would overflow for zero-sized types. + if self.len == self.buf.capacity() { + self.reserve(1); + } + unsafe { + let end = self.as_mut_ptr().add(self.len); + ptr::write(end, value); + self.len += 1; + } + } + + /// Removes the last element from a vector and returns it, or [`None`] if it + /// is empty. + /// + /// # Examples + /// + /// ``` + /// let mut vec = vec![1, 2, 3]; + /// assert_eq!(vec.pop(), Some(3)); + /// assert_eq!(vec, [1, 2]); + /// ``` + #[inline] + #[stable(feature = "rust1", since = "1.0.0")] + pub fn pop(&mut self) -> Option { + if self.len == 0 { + None + } else { + unsafe { + self.len -= 1; + Some(ptr::read(self.as_ptr().add(self.len()))) + } + } + } + + /// Moves all the elements of `other` into `Self`, leaving `other` empty. + /// + /// # Panics + /// + /// Panics if the number of elements in the vector overflows a `usize`. + /// + /// # Examples + /// + /// ``` + /// let mut vec = vec![1, 2, 3]; + /// let mut vec2 = vec![4, 5, 6]; + /// vec.append(&mut vec2); + /// assert_eq!(vec, [1, 2, 3, 4, 5, 6]); + /// assert_eq!(vec2, []); + /// ``` + #[inline] + #[stable(feature = "append", since = "1.4.0")] + pub fn append(&mut self, other: &mut Self) { + unsafe { + self.append_elements(other.as_slice() as _); + other.set_len(0); + } + } + + /// Appends elements to `Self` from other buffer. + #[inline] + unsafe fn append_elements(&mut self, other: *const [T]) { + let count = unsafe { (*other).len() }; + self.reserve(count); + let len = self.len(); + unsafe { ptr::copy_nonoverlapping(other as *const T, self.as_mut_ptr().add(len), count) }; + self.len += count; + } + + /// Creates a draining iterator that removes the specified range in the vector + /// and yields the removed items. + /// + /// When the iterator **is** dropped, all elements in the range are removed + /// from the vector, even if the iterator was not fully consumed. If the + /// iterator **is not** dropped (with [`mem::forget`] for example), it is + /// unspecified how many elements are removed. + /// + /// # Panics + /// + /// Panics if the starting point is greater than the end point or if + /// the end point is greater than the length of the vector. + /// + /// # Examples + /// + /// ``` + /// let mut v = vec![1, 2, 3]; + /// let u: Vec<_> = v.drain(1..).collect(); + /// assert_eq!(v, &[1]); + /// assert_eq!(u, &[2, 3]); + /// + /// // A full range clears the vector + /// v.drain(..); + /// assert_eq!(v, &[]); + /// ``` + #[stable(feature = "drain", since = "1.6.0")] + pub fn drain(&mut self, range: R) -> Drain<'_, T, A> + where + R: RangeBounds, + { + // Memory safety + // + // When the Drain is first created, it shortens the length of + // the source vector to make sure no uninitialized or moved-from elements + // are accessible at all if the Drain's destructor never gets to run. + // + // Drain will ptr::read out the values to remove. + // When finished, remaining tail of the vec is copied back to cover + // the hole, and the vector length is restored to the new length. + // + let len = self.len(); + let Range { start, end } = range.assert_len(len); + + unsafe { + // set self.vec length's to start, to be safe in case Drain is leaked + self.set_len(start); + // Use the borrow in the IterMut to indicate borrowing behavior of the + // whole Drain iterator (like &mut T). + let range_slice = slice::from_raw_parts_mut(self.as_mut_ptr().add(start), end - start); + Drain { + tail_start: end, + tail_len: len - end, + iter: range_slice.iter(), + vec: NonNull::from(self), + } + } + } + + /// Clears the vector, removing all values. + /// + /// Note that this method has no effect on the allocated capacity + /// of the vector. + /// + /// # Examples + /// + /// ``` + /// let mut v = vec![1, 2, 3]; + /// + /// v.clear(); + /// + /// assert!(v.is_empty()); + /// ``` + #[inline] + #[stable(feature = "rust1", since = "1.0.0")] + pub fn clear(&mut self) { + self.truncate(0) + } + + /// Returns the number of elements in the vector, also referred to + /// as its 'length'. + /// + /// # Examples + /// + /// ``` + /// let a = vec![1, 2, 3]; + /// assert_eq!(a.len(), 3); + /// ``` + #[doc(alias = "length")] + #[inline] + #[stable(feature = "rust1", since = "1.0.0")] + pub fn len(&self) -> usize { + self.len + } + + /// Returns `true` if the vector contains no elements. + /// + /// # Examples + /// + /// ``` + /// let mut v = Vec::new(); + /// assert!(v.is_empty()); + /// + /// v.push(1); + /// assert!(!v.is_empty()); + /// ``` + #[stable(feature = "rust1", since = "1.0.0")] + pub fn is_empty(&self) -> bool { + self.len() == 0 + } + + /// Splits the collection into two at the given index. + /// + /// Returns a newly allocated vector containing the elements in the range + /// `[at, len)`. After the call, the original vector will be left containing + /// the elements `[0, at)` with its previous capacity unchanged. + /// + /// # Panics + /// + /// Panics if `at > len`. + /// + /// # Examples + /// + /// ``` + /// let mut vec = vec![1, 2, 3]; + /// let vec2 = vec.split_off(1); + /// assert_eq!(vec, [1]); + /// assert_eq!(vec2, [2, 3]); + /// ``` + #[inline] + #[must_use = "use `.truncate()` if you don't need the other half"] + #[stable(feature = "split_off", since = "1.4.0")] + pub fn split_off(&mut self, at: usize) -> Self + where + A: Clone, + { + #[cold] + #[inline(never)] + fn assert_failed(at: usize, len: usize) -> ! { + panic!("`at` split index (is {}) should be <= len (is {})", at, len); + } + + if at > self.len() { + assert_failed(at, self.len()); + } + + if at == 0 { + // the new vector can take over the original buffer and avoid the copy + return mem::replace( + self, + Vec::with_capacity_in(self.capacity(), self.allocator().clone()), + ); + } + + let other_len = self.len - at; + let mut other = Vec::with_capacity_in(other_len, self.allocator().clone()); + + // Unsafely `set_len` and copy items to `other`. + unsafe { + self.set_len(at); + other.set_len(other_len); + + ptr::copy_nonoverlapping(self.as_ptr().add(at), other.as_mut_ptr(), other.len()); + } + other + } + + /// Resizes the `Vec` in-place so that `len` is equal to `new_len`. + /// + /// If `new_len` is greater than `len`, the `Vec` is extended by the + /// difference, with each additional slot filled with the result of + /// calling the closure `f`. The return values from `f` will end up + /// in the `Vec` in the order they have been generated. + /// + /// If `new_len` is less than `len`, the `Vec` is simply truncated. + /// + /// This method uses a closure to create new values on every push. If + /// you'd rather [`Clone`] a given value, use [`Vec::resize`]. If you + /// want to use the [`Default`] trait to generate values, you can + /// pass [`Default::default`] as the second argument. + /// + /// # Examples + /// + /// ``` + /// let mut vec = vec![1, 2, 3]; + /// vec.resize_with(5, Default::default); + /// assert_eq!(vec, [1, 2, 3, 0, 0]); + /// + /// let mut vec = vec![]; + /// let mut p = 1; + /// vec.resize_with(4, || { p *= 2; p }); + /// assert_eq!(vec, [2, 4, 8, 16]); + /// ``` + #[stable(feature = "vec_resize_with", since = "1.33.0")] + pub fn resize_with(&mut self, new_len: usize, f: F) + where + F: FnMut() -> T, + { + let len = self.len(); + if new_len > len { + self.extend_with(new_len - len, ExtendFunc(f)); + } else { + self.truncate(new_len); + } + } + + /// Consumes and leaks the `Vec`, returning a mutable reference to the contents, + /// `&'a mut [T]`. Note that the type `T` must outlive the chosen lifetime + /// `'a`. If the type has only static references, or none at all, then this + /// may be chosen to be `'static`. + /// + /// This function is similar to the [`leak`][Box::leak] function on [`Box`] + /// except that there is no way to recover the leaked memory. + /// + /// This function is mainly useful for data that lives for the remainder of + /// the program's life. Dropping the returned reference will cause a memory + /// leak. + /// + /// # Examples + /// + /// Simple usage: + /// + /// ``` + /// let x = vec![1, 2, 3]; + /// let static_ref: &'static mut [usize] = x.leak(); + /// static_ref[0] += 1; + /// assert_eq!(static_ref, &[2, 2, 3]); + /// ``` + #[stable(feature = "vec_leak", since = "1.47.0")] + #[inline] + pub fn leak<'a>(self) -> &'a mut [T] + where + A: 'a, + { + Box::leak(self.into_boxed_slice()) + } + + /// Returns the remaining spare capacity of the vector as a slice of + /// `MaybeUninit`. + /// + /// The returned slice can be used to fill the vector with data (e.g. by + /// reading from a file) before marking the data as initialized using the + /// [`set_len`] method. + /// + /// [`set_len`]: Vec::set_len + /// + /// # Examples + /// + /// ``` + /// #![feature(vec_spare_capacity, maybe_uninit_extra)] + /// + /// // Allocate vector big enough for 10 elements. + /// let mut v = Vec::with_capacity(10); + /// + /// // Fill in the first 3 elements. + /// let uninit = v.spare_capacity_mut(); + /// uninit[0].write(0); + /// uninit[1].write(1); + /// uninit[2].write(2); + /// + /// // Mark the first 3 elements of the vector as being initialized. + /// unsafe { + /// v.set_len(3); + /// } + /// + /// assert_eq!(&v, &[0, 1, 2]); + /// ``` + #[unstable(feature = "vec_spare_capacity", issue = "75017")] + #[inline] + pub fn spare_capacity_mut(&mut self) -> &mut [MaybeUninit] { + unsafe { + slice::from_raw_parts_mut( + self.as_mut_ptr().add(self.len) as *mut MaybeUninit, + self.buf.capacity() - self.len, + ) + } + } +} + +impl Vec { + /// Resizes the `Vec` in-place so that `len` is equal to `new_len`. + /// + /// If `new_len` is greater than `len`, the `Vec` is extended by the + /// difference, with each additional slot filled with `value`. + /// If `new_len` is less than `len`, the `Vec` is simply truncated. + /// + /// This method requires `T` to implement [`Clone`], + /// in order to be able to clone the passed value. + /// If you need more flexibility (or want to rely on [`Default`] instead of + /// [`Clone`]), use [`Vec::resize_with`]. + /// + /// # Examples + /// + /// ``` + /// let mut vec = vec!["hello"]; + /// vec.resize(3, "world"); + /// assert_eq!(vec, ["hello", "world", "world"]); + /// + /// let mut vec = vec![1, 2, 3, 4]; + /// vec.resize(2, 0); + /// assert_eq!(vec, [1, 2]); + /// ``` + #[stable(feature = "vec_resize", since = "1.5.0")] + pub fn resize(&mut self, new_len: usize, value: T) { + let len = self.len(); + + if new_len > len { + self.extend_with(new_len - len, ExtendElement(value)) + } else { + self.truncate(new_len); + } + } + + /// Clones and appends all elements in a slice to the `Vec`. + /// + /// Iterates over the slice `other`, clones each element, and then appends + /// it to this `Vec`. The `other` vector is traversed in-order. + /// + /// Note that this function is same as [`extend`] except that it is + /// specialized to work with slices instead. If and when Rust gets + /// specialization this function will likely be deprecated (but still + /// available). + /// + /// # Examples + /// + /// ``` + /// let mut vec = vec![1]; + /// vec.extend_from_slice(&[2, 3, 4]); + /// assert_eq!(vec, [1, 2, 3, 4]); + /// ``` + /// + /// [`extend`]: Vec::extend + #[stable(feature = "vec_extend_from_slice", since = "1.6.0")] + pub fn extend_from_slice(&mut self, other: &[T]) { + self.spec_extend(other.iter()) + } +} + +// This code generalizes `extend_with_{element,default}`. +trait ExtendWith { + fn next(&mut self) -> T; + fn last(self) -> T; +} + +struct ExtendElement(T); +impl ExtendWith for ExtendElement { + fn next(&mut self) -> T { + self.0.clone() + } + fn last(self) -> T { + self.0 + } +} + +struct ExtendDefault; +impl ExtendWith for ExtendDefault { + fn next(&mut self) -> T { + Default::default() + } + fn last(self) -> T { + Default::default() + } +} + +struct ExtendFunc(F); +impl T> ExtendWith for ExtendFunc { + fn next(&mut self) -> T { + (self.0)() + } + fn last(mut self) -> T { + (self.0)() + } +} + +impl Vec { + /// Extend the vector by `n` values, using the given generator. + fn extend_with>(&mut self, n: usize, mut value: E) { + self.reserve(n); + + unsafe { + let mut ptr = self.as_mut_ptr().add(self.len()); + // Use SetLenOnDrop to work around bug where compiler + // may not realize the store through `ptr` through self.set_len() + // don't alias. + let mut local_len = SetLenOnDrop::new(&mut self.len); + + // Write all elements except the last one + for _ in 1..n { + ptr::write(ptr, value.next()); + ptr = ptr.offset(1); + // Increment the length in every step in case next() panics + local_len.increment_len(1); + } + + if n > 0 { + // We can write the last element directly without cloning needlessly + ptr::write(ptr, value.last()); + local_len.increment_len(1); + } + + // len set by scope guard + } + } +} + +// Set the length of the vec when the `SetLenOnDrop` value goes out of scope. +// +// The idea is: The length field in SetLenOnDrop is a local variable +// that the optimizer will see does not alias with any stores through the Vec's data +// pointer. This is a workaround for alias analysis issue #32155 +struct SetLenOnDrop<'a> { + len: &'a mut usize, + local_len: usize, +} + +impl<'a> SetLenOnDrop<'a> { + #[inline] + fn new(len: &'a mut usize) -> Self { + SetLenOnDrop { local_len: *len, len } + } + + #[inline] + fn increment_len(&mut self, increment: usize) { + self.local_len += increment; + } +} + +impl Drop for SetLenOnDrop<'_> { + #[inline] + fn drop(&mut self) { + *self.len = self.local_len; + } +} + +impl Vec { + /// Removes consecutive repeated elements in the vector according to the + /// [`PartialEq`] trait implementation. + /// + /// If the vector is sorted, this removes all duplicates. + /// + /// # Examples + /// + /// ``` + /// let mut vec = vec![1, 2, 2, 3, 2]; + /// + /// vec.dedup(); + /// + /// assert_eq!(vec, [1, 2, 3, 2]); + /// ``` + #[stable(feature = "rust1", since = "1.0.0")] + #[inline] + pub fn dedup(&mut self) { + self.dedup_by(|a, b| a == b) + } +} + +impl Vec { + /// Removes the first instance of `item` from the vector if the item exists. + /// + /// This method will be removed soon. + #[unstable(feature = "vec_remove_item", reason = "recently added", issue = "40062")] + #[rustc_deprecated( + reason = "Removing the first item equal to a needle is already easily possible \ + with iterators and the current Vec methods. Furthermore, having a method for \ + one particular case of removal (linear search, only the first item, no swap remove) \ + but not for others is inconsistent. This method will be removed soon.", + since = "1.46.0" + )] + pub fn remove_item(&mut self, item: &V) -> Option + where + T: PartialEq, + { + let pos = self.iter().position(|x| *x == *item)?; + Some(self.remove(pos)) + } +} + +//////////////////////////////////////////////////////////////////////////////// +// Internal methods and functions +//////////////////////////////////////////////////////////////////////////////// + +#[doc(hidden)] +#[stable(feature = "rust1", since = "1.0.0")] +pub fn from_elem(elem: T, n: usize) -> Vec { + ::from_elem(elem, n, Global) +} + +#[doc(hidden)] +#[unstable(feature = "allocator_api", issue = "32838")] +pub fn from_elem_in(elem: T, n: usize, alloc: A) -> Vec { + ::from_elem(elem, n, alloc) +} + +// Specialization trait used for Vec::from_elem +trait SpecFromElem: Sized { + fn from_elem(elem: Self, n: usize, alloc: A) -> Vec; +} + +impl SpecFromElem for T { + default fn from_elem(elem: Self, n: usize, alloc: A) -> Vec { + let mut v = Vec::with_capacity_in(n, alloc); + v.extend_with(n, ExtendElement(elem)); + v + } +} + +impl SpecFromElem for i8 { + #[inline] + fn from_elem(elem: i8, n: usize, alloc: A) -> Vec { + if elem == 0 { + return Vec { buf: RawVec::with_capacity_zeroed_in(n, alloc), len: n }; + } + unsafe { + let mut v = Vec::with_capacity_in(n, alloc); + ptr::write_bytes(v.as_mut_ptr(), elem as u8, n); + v.set_len(n); + v + } + } +} + +impl SpecFromElem for u8 { + #[inline] + fn from_elem(elem: u8, n: usize, alloc: A) -> Vec { + if elem == 0 { + return Vec { buf: RawVec::with_capacity_zeroed_in(n, alloc), len: n }; + } + unsafe { + let mut v = Vec::with_capacity_in(n, alloc); + ptr::write_bytes(v.as_mut_ptr(), elem, n); + v.set_len(n); + v + } + } +} + +impl SpecFromElem for T { + #[inline] + fn from_elem(elem: T, n: usize, alloc: A) -> Vec { + if elem.is_zero() { + return Vec { buf: RawVec::with_capacity_zeroed_in(n, alloc), len: n }; + } + let mut v = Vec::with_capacity_in(n, alloc); + v.extend_with(n, ExtendElement(elem)); + v + } +} + +#[rustc_specialization_trait] +unsafe trait IsZero { + /// Whether this value is zero + fn is_zero(&self) -> bool; +} + +macro_rules! impl_is_zero { + ($t:ty, $is_zero:expr) => { + unsafe impl IsZero for $t { + #[inline] + fn is_zero(&self) -> bool { + $is_zero(*self) + } + } + }; +} + +impl_is_zero!(i16, |x| x == 0); +impl_is_zero!(i32, |x| x == 0); +impl_is_zero!(i64, |x| x == 0); +impl_is_zero!(i128, |x| x == 0); +impl_is_zero!(isize, |x| x == 0); + +impl_is_zero!(u16, |x| x == 0); +impl_is_zero!(u32, |x| x == 0); +impl_is_zero!(u64, |x| x == 0); +impl_is_zero!(u128, |x| x == 0); +impl_is_zero!(usize, |x| x == 0); + +impl_is_zero!(bool, |x| x == false); +impl_is_zero!(char, |x| x == '\0'); + +impl_is_zero!(f32, |x: f32| x.to_bits() == 0); +impl_is_zero!(f64, |x: f64| x.to_bits() == 0); + +unsafe impl IsZero for *const T { + #[inline] + fn is_zero(&self) -> bool { + (*self).is_null() + } +} + +unsafe impl IsZero for *mut T { + #[inline] + fn is_zero(&self) -> bool { + (*self).is_null() + } +} + +// `Option<&T>` and `Option>` are guaranteed to represent `None` as null. +// For fat pointers, the bytes that would be the pointer metadata in the `Some` +// variant are padding in the `None` variant, so ignoring them and +// zero-initializing instead is ok. +// `Option<&mut T>` never implements `Clone`, so there's no need for an impl of +// `SpecFromElem`. + +unsafe impl IsZero for Option<&T> { + #[inline] + fn is_zero(&self) -> bool { + self.is_none() + } +} + +unsafe impl IsZero for Option> { + #[inline] + fn is_zero(&self) -> bool { + self.is_none() + } +} + +//////////////////////////////////////////////////////////////////////////////// +// Common trait implementations for Vec +//////////////////////////////////////////////////////////////////////////////// + +#[stable(feature = "rust1", since = "1.0.0")] +impl ops::Deref for Vec { + type Target = [T]; + + fn deref(&self) -> &[T] { + unsafe { slice::from_raw_parts(self.as_ptr(), self.len) } + } +} + +#[stable(feature = "rust1", since = "1.0.0")] +impl ops::DerefMut for Vec { + fn deref_mut(&mut self) -> &mut [T] { + unsafe { slice::from_raw_parts_mut(self.as_mut_ptr(), self.len) } + } +} + +#[stable(feature = "rust1", since = "1.0.0")] +impl Clone for Vec { + #[cfg(not(test))] + fn clone(&self) -> Self { + let alloc = self.allocator().clone(); + <[T]>::to_vec_in(&**self, alloc) + } + + // HACK(japaric): with cfg(test) the inherent `[T]::to_vec` method, which is + // required for this method definition, is not available. Instead use the + // `slice::to_vec` function which is only available with cfg(test) + // NB see the slice::hack module in slice.rs for more information + #[cfg(test)] + fn clone(&self) -> Self { + let alloc = self.allocator().clone(); + crate::slice::to_vec(&**self, alloc) + } + + fn clone_from(&mut self, other: &Self) { + // drop anything that will not be overwritten + self.truncate(other.len()); + + // self.len <= other.len due to the truncate above, so the + // slices here are always in-bounds. + let (init, tail) = other.split_at(self.len()); + + // reuse the contained values' allocations/resources. + self.clone_from_slice(init); + self.extend_from_slice(tail); + } +} + +#[stable(feature = "rust1", since = "1.0.0")] +impl Hash for Vec { + #[inline] + fn hash(&self, state: &mut H) { + Hash::hash(&**self, state) + } +} + +#[stable(feature = "rust1", since = "1.0.0")] +#[rustc_on_unimplemented( + message = "vector indices are of type `usize` or ranges of `usize`", + label = "vector indices are of type `usize` or ranges of `usize`" +)] +impl, A: Allocator> Index for Vec { + type Output = I::Output; + + #[inline] + fn index(&self, index: I) -> &Self::Output { + Index::index(&**self, index) + } +} + +#[stable(feature = "rust1", since = "1.0.0")] +#[rustc_on_unimplemented( + message = "vector indices are of type `usize` or ranges of `usize`", + label = "vector indices are of type `usize` or ranges of `usize`" +)] +impl, A: Allocator> IndexMut for Vec { + #[inline] + fn index_mut(&mut self, index: I) -> &mut Self::Output { + IndexMut::index_mut(&mut **self, index) + } +} + +#[stable(feature = "rust1", since = "1.0.0")] +impl FromIterator for Vec { + #[inline] + fn from_iter>(iter: I) -> Vec { + >::from_iter(iter.into_iter()) + } +} + +#[stable(feature = "rust1", since = "1.0.0")] +impl IntoIterator for Vec { + type Item = T; + type IntoIter = IntoIter; + + /// Creates a consuming iterator, that is, one that moves each value out of + /// the vector (from start to end). The vector cannot be used after calling + /// this. + /// + /// # Examples + /// + /// ``` + /// let v = vec!["a".to_string(), "b".to_string()]; + /// for s in v.into_iter() { + /// // s has type String, not &String + /// println!("{}", s); + /// } + /// ``` + #[inline] + fn into_iter(self) -> IntoIter { + unsafe { + let mut me = ManuallyDrop::new(self); + let alloc = ptr::read(me.allocator()); + let begin = me.as_mut_ptr(); + let end = if mem::size_of::() == 0 { + arith_offset(begin as *const i8, me.len() as isize) as *const T + } else { + begin.add(me.len()) as *const T + }; + let cap = me.buf.capacity(); + IntoIter { + buf: NonNull::new_unchecked(begin), + phantom: PhantomData, + cap, + alloc, + ptr: begin, + end, + } + } + } +} + +#[stable(feature = "rust1", since = "1.0.0")] +impl<'a, T, A: Allocator> IntoIterator for &'a Vec { + type Item = &'a T; + type IntoIter = slice::Iter<'a, T>; + + fn into_iter(self) -> slice::Iter<'a, T> { + self.iter() + } +} + +#[stable(feature = "rust1", since = "1.0.0")] +impl<'a, T, A: Allocator> IntoIterator for &'a mut Vec { + type Item = &'a mut T; + type IntoIter = slice::IterMut<'a, T>; + + fn into_iter(self) -> slice::IterMut<'a, T> { + self.iter_mut() + } +} + +#[stable(feature = "rust1", since = "1.0.0")] +impl Extend for Vec { + #[inline] + fn extend>(&mut self, iter: I) { + >::spec_extend(self, iter.into_iter()) + } + + #[inline] + fn extend_one(&mut self, item: T) { + self.push(item); + } + + #[inline] + fn extend_reserve(&mut self, additional: usize) { + self.reserve(additional); + } +} + +/// Specialization trait used for Vec::from_iter +/// +/// ## The delegation graph: +/// +/// ```text +/// +-------------+ +/// |FromIterator | +/// +-+-----------+ +/// | +/// v +/// +-+-------------------------------+ +---------------------+ +/// |SpecFromIter +---->+SpecFromIterNested | +/// |where I: | | |where I: | +/// | Iterator (default)----------+ | | Iterator (default) | +/// | vec::IntoIter | | | TrustedLen | +/// | SourceIterMarker---fallback-+ | | | +/// | slice::Iter | | | +/// | Iterator | +---------------------+ +/// +---------------------------------+ +/// ``` +trait SpecFromIter { + fn from_iter(iter: I) -> Self; +} + +/// Another specialization trait for Vec::from_iter +/// necessary to manually prioritize overlapping specializations +/// see [`SpecFromIter`] for details. +trait SpecFromIterNested { + fn from_iter(iter: I) -> Self; +} + +impl SpecFromIterNested for Vec +where + I: Iterator, +{ + default fn from_iter(mut iterator: I) -> Self { + // Unroll the first iteration, as the vector is going to be + // expanded on this iteration in every case when the iterable is not + // empty, but the loop in extend_desugared() is not going to see the + // vector being full in the few subsequent loop iterations. + // So we get better branch prediction. + let mut vector = match iterator.next() { + None => return Vec::new(), + Some(element) => { + let (lower, _) = iterator.size_hint(); + let mut vector = Vec::with_capacity(lower.saturating_add(1)); + unsafe { + ptr::write(vector.as_mut_ptr(), element); + vector.set_len(1); + } + vector + } + }; + // must delegate to spec_extend() since extend() itself delegates + // to spec_from for empty Vecs + as SpecExtend>::spec_extend(&mut vector, iterator); + vector + } +} + +impl SpecFromIterNested for Vec +where + I: TrustedLen, +{ + fn from_iter(iterator: I) -> Self { + let mut vector = match iterator.size_hint() { + (_, Some(upper)) => Vec::with_capacity(upper), + _ => Vec::new(), + }; + // must delegate to spec_extend() since extend() itself delegates + // to spec_from for empty Vecs + vector.spec_extend(iterator); + vector + } +} + +impl SpecFromIter for Vec +where + I: Iterator, +{ + default fn from_iter(iterator: I) -> Self { + SpecFromIterNested::from_iter(iterator) + } +} + +// A helper struct for in-place iteration that drops the destination slice of iteration, +// i.e. the head. The source slice (the tail) is dropped by IntoIter. +struct InPlaceDrop { + inner: *mut T, + dst: *mut T, +} + +impl InPlaceDrop { + fn len(&self) -> usize { + unsafe { self.dst.offset_from(self.inner) as usize } + } +} + +impl Drop for InPlaceDrop { + #[inline] + fn drop(&mut self) { + unsafe { + ptr::drop_in_place(slice::from_raw_parts_mut(self.inner, self.len())); + } + } +} + +impl SpecFromIter> for Vec { + fn from_iter(iterator: IntoIter) -> Self { + // A common case is passing a vector into a function which immediately + // re-collects into a vector. We can short circuit this if the IntoIter + // has not been advanced at all. + // When it has been advanced We can also reuse the memory and move the data to the front. + // But we only do so when the resulting Vec wouldn't have more unused capacity + // than creating it through the generic FromIterator implementation would. That limitation + // is not strictly necessary as Vec's allocation behavior is intentionally unspecified. + // But it is a conservative choice. + let has_advanced = iterator.buf.as_ptr() as *const _ != iterator.ptr; + if !has_advanced || iterator.len() >= iterator.cap / 2 { + unsafe { + let it = ManuallyDrop::new(iterator); + if has_advanced { + ptr::copy(it.ptr, it.buf.as_ptr(), it.len()); + } + return Vec::from_raw_parts(it.buf.as_ptr(), it.len(), it.cap); + } + } + + let mut vec = Vec::new(); + // must delegate to spec_extend() since extend() itself delegates + // to spec_from for empty Vecs + vec.spec_extend(iterator); + vec + } +} + +fn write_in_place_with_drop( + src_end: *const T, +) -> impl FnMut(InPlaceDrop, T) -> Result, !> { + move |mut sink, item| { + unsafe { + // the InPlaceIterable contract cannot be verified precisely here since + // try_fold has an exclusive reference to the source pointer + // all we can do is check if it's still in range + debug_assert!(sink.dst as *const _ <= src_end, "InPlaceIterable contract violation"); + ptr::write(sink.dst, item); + sink.dst = sink.dst.add(1); + } + Ok(sink) + } +} + +/// Specialization marker for collecting an iterator pipeline into a Vec while reusing the +/// source allocation, i.e. executing the pipeline in place. +/// +/// The SourceIter parent trait is necessary for the specializing function to access the allocation +/// which is to be reused. But it is not sufficient for the specialization to be valid. See +/// additional bounds on the impl. +#[rustc_unsafe_specialization_marker] +trait SourceIterMarker: SourceIter {} + +// The std-internal SourceIter/InPlaceIterable traits are only implemented by chains of +// Adapter>> (all owned by core/std). Additional bounds +// on the adapter implementations (beyond `impl Trait for Adapter`) only depend on other +// traits already marked as specialization traits (Copy, TrustedRandomAccess, FusedIterator). +// I.e. the marker does not depend on lifetimes of user-supplied types. Modulo the Copy hole, which +// several other specializations already depend on. +impl SourceIterMarker for T where T: SourceIter + InPlaceIterable {} + +impl SpecFromIter for Vec +where + I: Iterator + SourceIterMarker, +{ + default fn from_iter(mut iterator: I) -> Self { + // Additional requirements which cannot expressed via trait bounds. We rely on const eval + // instead: + // a) no ZSTs as there would be no allocation to reuse and pointer arithmetic would panic + // b) size match as required by Alloc contract + // c) alignments match as required by Alloc contract + if mem::size_of::() == 0 + || mem::size_of::() + != mem::size_of::<<::Source as AsIntoIter>::Item>() + || mem::align_of::() + != mem::align_of::<<::Source as AsIntoIter>::Item>() + { + // fallback to more generic implementations + return SpecFromIterNested::from_iter(iterator); + } + + let (src_buf, src_ptr, dst_buf, dst_end, cap) = unsafe { + let inner = iterator.as_inner().as_into_iter(); + ( + inner.buf.as_ptr(), + inner.ptr, + inner.buf.as_ptr() as *mut T, + inner.end as *const T, + inner.cap, + ) + }; + + // use try-fold since + // - it vectorizes better for some iterator adapters + // - unlike most internal iteration methods, it only takes a &mut self + // - it lets us thread the write pointer through its innards and get it back in the end + let sink = InPlaceDrop { inner: dst_buf, dst: dst_buf }; + let sink = iterator + .try_fold::<_, _, Result<_, !>>(sink, write_in_place_with_drop(dst_end)) + .unwrap(); + // iteration succeeded, don't drop head + let dst = ManuallyDrop::new(sink).dst; + + let src = unsafe { iterator.as_inner().as_into_iter() }; + // check if SourceIter contract was upheld + // caveat: if they weren't we may not even make it to this point + debug_assert_eq!(src_buf, src.buf.as_ptr()); + // check InPlaceIterable contract. This is only possible if the iterator advanced the + // source pointer at all. If it uses unchecked access via TrustedRandomAccess + // then the source pointer will stay in its initial position and we can't use it as reference + if src.ptr != src_ptr { + debug_assert!( + dst as *const _ <= src.ptr, + "InPlaceIterable contract violation, write pointer advanced beyond read pointer" + ); + } + + // drop any remaining values at the tail of the source + src.drop_remaining(); + // but prevent drop of the allocation itself once IntoIter goes out of scope + src.forget_allocation(); + + let vec = unsafe { + let len = dst.offset_from(dst_buf) as usize; + Vec::from_raw_parts(dst_buf, len, cap) + }; + + vec + } +} + +impl<'a, T: 'a, I> SpecFromIter<&'a T, I> for Vec +where + I: Iterator, + T: Clone, +{ + default fn from_iter(iterator: I) -> Self { + SpecFromIter::from_iter(iterator.cloned()) + } +} + +// This utilizes `iterator.as_slice().to_vec()` since spec_extend +// must take more steps to reason about the final capacity + length +// and thus do more work. `to_vec()` directly allocates the correct amount +// and fills it exactly. +impl<'a, T: 'a + Clone> SpecFromIter<&'a T, slice::Iter<'a, T>> for Vec { + #[cfg(not(test))] + fn from_iter(iterator: slice::Iter<'a, T>) -> Self { + iterator.as_slice().to_vec() + } + + // HACK(japaric): with cfg(test) the inherent `[T]::to_vec` method, which is + // required for this method definition, is not available. Instead use the + // `slice::to_vec` function which is only available with cfg(test) + // NB see the slice::hack module in slice.rs for more information + #[cfg(test)] + fn from_iter(iterator: slice::Iter<'a, T>) -> Self { + crate::slice::to_vec(iterator.as_slice(), Global) + } +} + +// Specialization trait used for Vec::extend +trait SpecExtend { + fn spec_extend(&mut self, iter: I); +} + +impl SpecExtend for Vec +where + I: Iterator, +{ + default fn spec_extend(&mut self, iter: I) { + self.extend_desugared(iter) + } +} + +impl SpecExtend for Vec +where + I: TrustedLen, +{ + default fn spec_extend(&mut self, iterator: I) { + // This is the case for a TrustedLen iterator. + let (low, high) = iterator.size_hint(); + if let Some(high_value) = high { + debug_assert_eq!( + low, + high_value, + "TrustedLen iterator's size hint is not exact: {:?}", + (low, high) + ); + } + if let Some(additional) = high { + self.reserve(additional); + unsafe { + let mut ptr = self.as_mut_ptr().add(self.len()); + let mut local_len = SetLenOnDrop::new(&mut self.len); + iterator.for_each(move |element| { + ptr::write(ptr, element); + ptr = ptr.offset(1); + // NB can't overflow since we would have had to alloc the address space + local_len.increment_len(1); + }); + } + } else { + self.extend_desugared(iterator) + } + } +} + +impl SpecExtend> for Vec { + fn spec_extend(&mut self, mut iterator: IntoIter) { + unsafe { + self.append_elements(iterator.as_slice() as _); + } + iterator.ptr = iterator.end; + } +} + +impl<'a, T: 'a, I, A: Allocator + 'a> SpecExtend<&'a T, I> for Vec +where + I: Iterator, + T: Clone, +{ + default fn spec_extend(&mut self, iterator: I) { + self.spec_extend(iterator.cloned()) + } +} + +impl<'a, T: 'a, A: Allocator + 'a> SpecExtend<&'a T, slice::Iter<'a, T>> for Vec +where + T: Copy, +{ + fn spec_extend(&mut self, iterator: slice::Iter<'a, T>) { + let slice = iterator.as_slice(); + unsafe { self.append_elements(slice) }; + } +} + +impl Vec { + // leaf method to which various SpecFrom/SpecExtend implementations delegate when + // they have no further optimizations to apply + fn extend_desugared>(&mut self, mut iterator: I) { + // This is the case for a general iterator. + // + // This function should be the moral equivalent of: + // + // for item in iterator { + // self.push(item); + // } + while let Some(element) = iterator.next() { + let len = self.len(); + if len == self.capacity() { + let (lower, _) = iterator.size_hint(); + self.reserve(lower.saturating_add(1)); + } + unsafe { + ptr::write(self.as_mut_ptr().add(len), element); + // NB can't overflow since we would have had to alloc the address space + self.set_len(len + 1); + } + } + } + + /// Creates a splicing iterator that replaces the specified range in the vector + /// with the given `replace_with` iterator and yields the removed items. + /// `replace_with` does not need to be the same length as `range`. + /// + /// `range` is removed even if the iterator is not consumed until the end. + /// + /// It is unspecified how many elements are removed from the vector + /// if the `Splice` value is leaked. + /// + /// The input iterator `replace_with` is only consumed when the `Splice` value is dropped. + /// + /// This is optimal if: + /// + /// * The tail (elements in the vector after `range`) is empty, + /// * or `replace_with` yields fewer elements than `range`’s length + /// * or the lower bound of its `size_hint()` is exact. + /// + /// Otherwise, a temporary vector is allocated and the tail is moved twice. + /// + /// # Panics + /// + /// Panics if the starting point is greater than the end point or if + /// the end point is greater than the length of the vector. + /// + /// # Examples + /// + /// ``` + /// let mut v = vec![1, 2, 3]; + /// let new = [7, 8]; + /// let u: Vec<_> = v.splice(..2, new.iter().cloned()).collect(); + /// assert_eq!(v, &[7, 8, 3]); + /// assert_eq!(u, &[1, 2]); + /// ``` + #[inline] + #[stable(feature = "vec_splice", since = "1.21.0")] + pub fn splice(&mut self, range: R, replace_with: I) -> Splice<'_, I::IntoIter, A> + where + R: RangeBounds, + I: IntoIterator, + { + Splice { drain: self.drain(range), replace_with: replace_with.into_iter() } + } + + /// Creates an iterator which uses a closure to determine if an element should be removed. + /// + /// If the closure returns true, then the element is removed and yielded. + /// If the closure returns false, the element will remain in the vector and will not be yielded + /// by the iterator. + /// + /// Using this method is equivalent to the following code: + /// + /// ``` + /// # let some_predicate = |x: &mut i32| { *x == 2 || *x == 3 || *x == 6 }; + /// # let mut vec = vec![1, 2, 3, 4, 5, 6]; + /// let mut i = 0; + /// while i != vec.len() { + /// if some_predicate(&mut vec[i]) { + /// let val = vec.remove(i); + /// // your code here + /// } else { + /// i += 1; + /// } + /// } + /// + /// # assert_eq!(vec, vec![1, 4, 5]); + /// ``` + /// + /// But `drain_filter` is easier to use. `drain_filter` is also more efficient, + /// because it can backshift the elements of the array in bulk. + /// + /// Note that `drain_filter` also lets you mutate every element in the filter closure, + /// regardless of whether you choose to keep or remove it. + /// + /// # Examples + /// + /// Splitting an array into evens and odds, reusing the original allocation: + /// + /// ``` + /// #![feature(drain_filter)] + /// let mut numbers = vec![1, 2, 3, 4, 5, 6, 8, 9, 11, 13, 14, 15]; + /// + /// let evens = numbers.drain_filter(|x| *x % 2 == 0).collect::>(); + /// let odds = numbers; + /// + /// assert_eq!(evens, vec![2, 4, 6, 8, 14]); + /// assert_eq!(odds, 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, A> + where + F: FnMut(&mut T) -> bool, + { + let old_len = self.len(); + + // Guard against us getting leaked (leak amplification) + unsafe { + self.set_len(0); + } + + DrainFilter { vec: self, idx: 0, del: 0, old_len, pred: filter, panic_flag: false } + } +} + +/// Extend implementation that copies elements out of references before pushing them onto the Vec. +/// +/// This implementation is specialized for slice iterators, where it uses [`copy_from_slice`] to +/// append the entire slice at once. +/// +/// [`copy_from_slice`]: ../../std/primitive.slice.html#method.copy_from_slice +#[stable(feature = "extend_ref", since = "1.2.0")] +impl<'a, T: Copy + 'a, A: Allocator + 'a> Extend<&'a T> for Vec { + fn extend>(&mut self, iter: I) { + self.spec_extend(iter.into_iter()) + } + + #[inline] + fn extend_one(&mut self, &item: &'a T) { + self.push(item); + } + + #[inline] + fn extend_reserve(&mut self, additional: usize) { + self.reserve(additional); + } +} + +macro_rules! __impl_slice_eq1 { + ([$($vars:tt)*] $lhs:ty, $rhs:ty $(where $ty:ty: $bound:ident)?, #[$stability:meta]) => { + #[$stability] + impl PartialEq<$rhs> for $lhs + where + T: PartialEq, + $($ty: $bound)? + { + #[inline] + fn eq(&self, other: &$rhs) -> bool { self[..] == other[..] } + #[inline] + fn ne(&self, other: &$rhs) -> bool { self[..] != other[..] } + } + } +} + +__impl_slice_eq1! { [A: Allocator] Vec, Vec, #[stable(feature = "rust1", since = "1.0.0")] } +__impl_slice_eq1! { [A: Allocator] Vec, &[U], #[stable(feature = "rust1", since = "1.0.0")] } +__impl_slice_eq1! { [A: Allocator] Vec, &mut [U], #[stable(feature = "rust1", since = "1.0.0")] } +__impl_slice_eq1! { [A: Allocator] &[T], Vec, #[stable(feature = "partialeq_vec_for_ref_slice", since = "1.46.0")] } +__impl_slice_eq1! { [A: Allocator] &mut [T], Vec, #[stable(feature = "partialeq_vec_for_ref_slice", since = "1.46.0")] } +__impl_slice_eq1! { [A: Allocator] Vec, [U], #[stable(feature = "partialeq_vec_for_slice", since = "1.48.0")] } +__impl_slice_eq1! { [A: Allocator] [T], Vec, #[stable(feature = "partialeq_vec_for_slice", since = "1.48.0")] } +__impl_slice_eq1! { [A: Allocator] Cow<'_, [T]>, Vec where T: Clone, #[stable(feature = "rust1", since = "1.0.0")] } +__impl_slice_eq1! { [] Cow<'_, [T]>, &[U] where T: Clone, #[stable(feature = "rust1", since = "1.0.0")] } +__impl_slice_eq1! { [] Cow<'_, [T]>, &mut [U] where T: Clone, #[stable(feature = "rust1", since = "1.0.0")] } +__impl_slice_eq1! { [A: Allocator, const N: usize] Vec, [U; N], #[stable(feature = "rust1", since = "1.0.0")] } +__impl_slice_eq1! { [A: Allocator, const N: usize] Vec, &[U; N], #[stable(feature = "rust1", since = "1.0.0")] } + +// NOTE: some less important impls are omitted to reduce code bloat +// FIXME(Centril): Reconsider this? +//__impl_slice_eq1! { [const N: usize] Vec, &mut [B; N], } +//__impl_slice_eq1! { [const N: usize] [A; N], Vec, } +//__impl_slice_eq1! { [const N: usize] &[A; N], Vec, } +//__impl_slice_eq1! { [const N: usize] &mut [A; N], Vec, } +//__impl_slice_eq1! { [const N: usize] Cow<'a, [A]>, [B; N], } +//__impl_slice_eq1! { [const N: usize] Cow<'a, [A]>, &[B; N], } +//__impl_slice_eq1! { [const N: usize] Cow<'a, [A]>, &mut [B; N], } + +/// Implements comparison of vectors, [lexicographically](core::cmp::Ord#lexicographical-comparison). +#[stable(feature = "rust1", since = "1.0.0")] +impl PartialOrd for Vec { + #[inline] + fn partial_cmp(&self, other: &Self) -> Option { + PartialOrd::partial_cmp(&**self, &**other) + } +} + +#[stable(feature = "rust1", since = "1.0.0")] +impl Eq for Vec {} + +/// Implements ordering of vectors, [lexicographically](core::cmp::Ord#lexicographical-comparison). +#[stable(feature = "rust1", since = "1.0.0")] +impl Ord for Vec { + #[inline] + fn cmp(&self, other: &Self) -> Ordering { + Ord::cmp(&**self, &**other) + } +} + +#[stable(feature = "rust1", since = "1.0.0")] +unsafe impl<#[may_dangle] T, A: Allocator> Drop for Vec { + fn drop(&mut self) { + unsafe { + // use drop for [T] + // use a raw slice to refer to the elements of the vector as weakest necessary type; + // could avoid questions of validity in certain cases + ptr::drop_in_place(ptr::slice_from_raw_parts_mut(self.as_mut_ptr(), self.len)) + } + // RawVec handles deallocation + } +} + +#[stable(feature = "rust1", since = "1.0.0")] +impl Default for Vec { + /// Creates an empty `Vec`. + fn default() -> Vec { + Vec::new() + } +} + +#[stable(feature = "rust1", since = "1.0.0")] +impl fmt::Debug for Vec { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + fmt::Debug::fmt(&**self, f) + } +} + +#[stable(feature = "rust1", since = "1.0.0")] +impl AsRef> for Vec { + fn as_ref(&self) -> &Vec { + self + } +} + +#[stable(feature = "vec_as_mut", since = "1.5.0")] +impl AsMut> for Vec { + fn as_mut(&mut self) -> &mut Vec { + self + } +} + +#[stable(feature = "rust1", since = "1.0.0")] +impl AsRef<[T]> for Vec { + fn as_ref(&self) -> &[T] { + self + } +} + +#[stable(feature = "vec_as_mut", since = "1.5.0")] +impl AsMut<[T]> for Vec { + fn as_mut(&mut self) -> &mut [T] { + self + } +} + +#[stable(feature = "rust1", since = "1.0.0")] +impl From<&[T]> for Vec { + #[cfg(not(test))] + fn from(s: &[T]) -> Vec { + s.to_vec() + } + #[cfg(test)] + fn from(s: &[T]) -> Vec { + crate::slice::to_vec(s, Global) + } +} + +#[stable(feature = "vec_from_mut", since = "1.19.0")] +impl From<&mut [T]> for Vec { + #[cfg(not(test))] + fn from(s: &mut [T]) -> Vec { + s.to_vec() + } + #[cfg(test)] + fn from(s: &mut [T]) -> Vec { + crate::slice::to_vec(s, Global) + } +} + +#[stable(feature = "vec_from_array", since = "1.44.0")] +impl From<[T; N]> for Vec { + #[cfg(not(test))] + fn from(s: [T; N]) -> Vec { + <[T]>::into_vec(box s) + } + #[cfg(test)] + fn from(s: [T; N]) -> Vec { + crate::slice::into_vec(box s) + } +} + +#[stable(feature = "vec_from_cow_slice", since = "1.14.0")] +impl<'a, T> From> for Vec +where + [T]: ToOwned>, +{ + fn from(s: Cow<'a, [T]>) -> Vec { + s.into_owned() + } +} + +// note: test pulls in libstd, which causes errors here +#[cfg(not(test))] +#[stable(feature = "vec_from_box", since = "1.18.0")] +impl From> for Vec { + fn from(s: Box<[T], A>) -> Self { + let len = s.len(); + Self { buf: RawVec::from_box(s), len } + } +} + +// note: test pulls in libstd, which causes errors here +#[cfg(not(test))] +#[stable(feature = "box_from_vec", since = "1.20.0")] +impl From> for Box<[T], A> { + fn from(v: Vec) -> Self { + v.into_boxed_slice() + } +} + +#[stable(feature = "rust1", since = "1.0.0")] +impl From<&str> for Vec { + fn from(s: &str) -> Vec { + From::from(s.as_bytes()) + } +} + +#[stable(feature = "array_try_from_vec", since = "1.48.0")] +impl TryFrom> for [T; N] { + type Error = Vec; + + /// Gets the entire contents of the `Vec` as an array, + /// if its size exactly matches that of the requested array. + /// + /// # Examples + /// + /// ``` + /// use std::convert::TryInto; + /// assert_eq!(vec![1, 2, 3].try_into(), Ok([1, 2, 3])); + /// assert_eq!(>::new().try_into(), Ok([])); + /// ``` + /// + /// If the length doesn't match, the input comes back in `Err`: + /// ``` + /// use std::convert::TryInto; + /// let r: Result<[i32; 4], _> = (0..10).collect::>().try_into(); + /// assert_eq!(r, Err(vec![0, 1, 2, 3, 4, 5, 6, 7, 8, 9])); + /// ``` + /// + /// If you're fine with just getting a prefix of the `Vec`, + /// you can call [`.truncate(N)`](Vec::truncate) first. + /// ``` + /// use std::convert::TryInto; + /// let mut v = String::from("hello world").into_bytes(); + /// v.sort(); + /// v.truncate(2); + /// let [a, b]: [_; 2] = v.try_into().unwrap(); + /// assert_eq!(a, b' '); + /// assert_eq!(b, b'd'); + /// ``` + fn try_from(mut vec: Vec) -> Result<[T; N], Vec> { + if vec.len() != N { + return Err(vec); + } + + // SAFETY: `.set_len(0)` is always sound. + unsafe { vec.set_len(0) }; + + // SAFETY: A `Vec`'s pointer is always aligned properly, and + // the alignment the array needs is the same as the items. + // We checked earlier that we have sufficient items. + // The items will not double-drop as the `set_len` + // tells the `Vec` not to also drop them. + let array = unsafe { ptr::read(vec.as_ptr() as *const [T; N]) }; + Ok(array) + } +} + +//////////////////////////////////////////////////////////////////////////////// +// Clone-on-write +//////////////////////////////////////////////////////////////////////////////// + +#[stable(feature = "cow_from_vec", since = "1.8.0")] +impl<'a, T: Clone> From<&'a [T]> for Cow<'a, [T]> { + fn from(s: &'a [T]) -> Cow<'a, [T]> { + Cow::Borrowed(s) + } +} + +#[stable(feature = "cow_from_vec", since = "1.8.0")] +impl<'a, T: Clone> From> for Cow<'a, [T]> { + fn from(v: Vec) -> Cow<'a, [T]> { + Cow::Owned(v) + } +} + +#[stable(feature = "cow_from_vec_ref", since = "1.28.0")] +impl<'a, T: Clone> From<&'a Vec> for Cow<'a, [T]> { + fn from(v: &'a Vec) -> Cow<'a, [T]> { + Cow::Borrowed(v.as_slice()) + } +} + +#[stable(feature = "rust1", since = "1.0.0")] +impl<'a, T> FromIterator for Cow<'a, [T]> +where + T: Clone, +{ + fn from_iter>(it: I) -> Cow<'a, [T]> { + Cow::Owned(FromIterator::from_iter(it)) + } +} + +//////////////////////////////////////////////////////////////////////////////// +// Iterators +//////////////////////////////////////////////////////////////////////////////// + +/// An iterator that moves out of a vector. +/// +/// This `struct` is created by the `into_iter` method on [`Vec`] (provided +/// by the [`IntoIterator`] trait). +/// +/// # Example +/// +/// ``` +/// let v = vec![0, 1, 2]; +/// let iter: std::vec::IntoIter<_> = v.into_iter(); +/// ``` +#[stable(feature = "rust1", since = "1.0.0")] +pub struct IntoIter< + T, + #[unstable(feature = "allocator_api", issue = "32838")] A: Allocator = Global, +> { + buf: NonNull, + phantom: PhantomData, + cap: usize, + alloc: A, + ptr: *const T, + end: *const T, +} + +#[stable(feature = "vec_intoiter_debug", since = "1.13.0")] +impl fmt::Debug for IntoIter { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + f.debug_tuple("IntoIter").field(&self.as_slice()).finish() + } +} + +impl IntoIter { + /// Returns the remaining items of this iterator as a slice. + /// + /// # Examples + /// + /// ``` + /// let vec = vec!['a', 'b', 'c']; + /// let mut into_iter = vec.into_iter(); + /// assert_eq!(into_iter.as_slice(), &['a', 'b', 'c']); + /// let _ = into_iter.next().unwrap(); + /// assert_eq!(into_iter.as_slice(), &['b', 'c']); + /// ``` + #[stable(feature = "vec_into_iter_as_slice", since = "1.15.0")] + pub fn as_slice(&self) -> &[T] { + unsafe { slice::from_raw_parts(self.ptr, self.len()) } + } + + /// Returns the remaining items of this iterator as a mutable slice. + /// + /// # Examples + /// + /// ``` + /// let vec = vec!['a', 'b', 'c']; + /// let mut into_iter = vec.into_iter(); + /// assert_eq!(into_iter.as_slice(), &['a', 'b', 'c']); + /// into_iter.as_mut_slice()[2] = 'z'; + /// assert_eq!(into_iter.next().unwrap(), 'a'); + /// assert_eq!(into_iter.next().unwrap(), 'b'); + /// assert_eq!(into_iter.next().unwrap(), 'z'); + /// ``` + #[stable(feature = "vec_into_iter_as_slice", since = "1.15.0")] + pub fn as_mut_slice(&mut self) -> &mut [T] { + unsafe { &mut *self.as_raw_mut_slice() } + } + + /// Returns a reference to the underlying allocator. + #[unstable(feature = "allocator_api", issue = "32838")] + #[inline] + pub fn allocator(&self) -> &A { + &self.alloc + } + + fn as_raw_mut_slice(&mut self) -> *mut [T] { + ptr::slice_from_raw_parts_mut(self.ptr as *mut T, self.len()) + } + + fn drop_remaining(&mut self) { + unsafe { + ptr::drop_in_place(self.as_mut_slice()); + } + self.ptr = self.end; + } + + /// Relinquishes the backing allocation, equivalent to + /// `ptr::write(&mut self, Vec::new().into_iter())` + fn forget_allocation(&mut self) { + self.cap = 0; + self.buf = unsafe { NonNull::new_unchecked(RawVec::NEW.ptr()) }; + self.ptr = self.buf.as_ptr(); + self.end = self.buf.as_ptr(); + } +} + +#[stable(feature = "vec_intoiter_as_ref", since = "1.46.0")] +impl AsRef<[T]> for IntoIter { + fn as_ref(&self) -> &[T] { + self.as_slice() + } +} + +#[stable(feature = "rust1", since = "1.0.0")] +unsafe impl Send for IntoIter {} +#[stable(feature = "rust1", since = "1.0.0")] +unsafe impl Sync for IntoIter {} + +#[stable(feature = "rust1", since = "1.0.0")] +impl Iterator for IntoIter { + type Item = T; + + #[inline] + fn next(&mut self) -> Option { + if self.ptr as *const _ == self.end { + None + } else if mem::size_of::() == 0 { + // purposefully don't use 'ptr.offset' because for + // vectors with 0-size elements this would return the + // same pointer. + self.ptr = unsafe { arith_offset(self.ptr as *const i8, 1) as *mut T }; + + // Make up a value of this ZST. + Some(unsafe { mem::zeroed() }) + } else { + let old = self.ptr; + self.ptr = unsafe { self.ptr.offset(1) }; + + Some(unsafe { ptr::read(old) }) + } + } + + #[inline] + fn size_hint(&self) -> (usize, Option) { + let exact = if mem::size_of::() == 0 { + (self.end as usize).wrapping_sub(self.ptr as usize) + } else { + unsafe { self.end.offset_from(self.ptr) as usize } + }; + (exact, Some(exact)) + } + + #[inline] + fn count(self) -> usize { + self.len() + } + + unsafe fn __iterator_get_unchecked(&mut self, i: usize) -> Self::Item + where + Self: TrustedRandomAccess, + { + // SAFETY: the caller must guarantee that `i` is in bounds of the + // `Vec`, so `i` cannot overflow an `isize`, and the `self.ptr.add(i)` + // is guaranteed to pointer to an element of the `Vec` and + // thus guaranteed to be valid to dereference. + // + // Also note the implementation of `Self: TrustedRandomAccess` requires + // that `T: Copy` so reading elements from the buffer doesn't invalidate + // them for `Drop`. + unsafe { + if mem::size_of::() == 0 { mem::zeroed() } else { ptr::read(self.ptr.add(i)) } + } + } +} + +#[stable(feature = "rust1", since = "1.0.0")] +impl DoubleEndedIterator for IntoIter { + #[inline] + fn next_back(&mut self) -> Option { + if self.end == self.ptr { + None + } else if mem::size_of::() == 0 { + // See above for why 'ptr.offset' isn't used + self.end = unsafe { arith_offset(self.end as *const i8, -1) as *mut T }; + + // Make up a value of this ZST. + Some(unsafe { mem::zeroed() }) + } else { + self.end = unsafe { self.end.offset(-1) }; + + Some(unsafe { ptr::read(self.end) }) + } + } +} + +#[stable(feature = "rust1", since = "1.0.0")] +impl ExactSizeIterator for IntoIter { + fn is_empty(&self) -> bool { + self.ptr == self.end + } +} + +#[stable(feature = "fused", since = "1.26.0")] +impl FusedIterator for IntoIter {} + +#[unstable(feature = "trusted_len", issue = "37572")] +unsafe impl TrustedLen for IntoIter {} + +#[doc(hidden)] +#[unstable(issue = "none", feature = "std_internals")] +// T: Copy as approximation for !Drop since get_unchecked does not advance self.ptr +// and thus we can't implement drop-handling +unsafe impl TrustedRandomAccess for IntoIter +where + T: Copy, +{ + fn may_have_side_effect() -> bool { + false + } +} + +#[stable(feature = "vec_into_iter_clone", since = "1.8.0")] +impl Clone for IntoIter { + #[cfg(not(test))] + fn clone(&self) -> Self { + self.as_slice().to_vec_in(self.alloc.clone()).into_iter() + } + #[cfg(test)] + fn clone(&self) -> Self { + crate::slice::to_vec(self.as_slice(), self.alloc.clone()).into_iter() + } +} + +#[stable(feature = "rust1", since = "1.0.0")] +unsafe impl<#[may_dangle] T, A: Allocator> Drop for IntoIter { + fn drop(&mut self) { + struct DropGuard<'a, T, A: Allocator>(&'a mut IntoIter); + + impl Drop for DropGuard<'_, T, A> { + fn drop(&mut self) { + unsafe { + // `IntoIter::alloc` is not used anymore after this + let alloc = ptr::read(&self.0.alloc); + // RawVec handles deallocation + let _ = RawVec::from_raw_parts_in(self.0.buf.as_ptr(), self.0.cap, alloc); + } + } + } + + let guard = DropGuard(self); + // destroy the remaining elements + unsafe { + ptr::drop_in_place(guard.0.as_raw_mut_slice()); + } + // now `guard` will be dropped and do the rest + } +} + +#[unstable(issue = "none", feature = "inplace_iteration")] +unsafe impl InPlaceIterable for IntoIter {} + +#[unstable(issue = "none", feature = "inplace_iteration")] +unsafe impl SourceIter for IntoIter { + type Source = Self; + + #[inline] + unsafe fn as_inner(&mut self) -> &mut Self::Source { + self + } +} + +// internal helper trait for in-place iteration specialization. +#[rustc_specialization_trait] +pub(crate) trait AsIntoIter { + type Item; + fn as_into_iter(&mut self) -> &mut IntoIter; +} + +impl AsIntoIter for IntoIter { + type Item = T; + + fn as_into_iter(&mut self) -> &mut IntoIter { + self + } +} + +/// A draining iterator for `Vec`. +/// +/// This `struct` is created by [`Vec::drain`]. +/// See its documentation for more. +/// +/// # Example +/// +/// ``` +/// let mut v = vec![0, 1, 2]; +/// let iter: std::vec::Drain<_> = v.drain(..); +/// ``` +#[stable(feature = "drain", since = "1.6.0")] +pub struct Drain< + 'a, + T: 'a, + #[unstable(feature = "allocator_api", issue = "32838")] A: Allocator + 'a = Global, +> { + /// Index of tail to preserve + tail_start: usize, + /// Length of tail + tail_len: usize, + /// Current remaining range to remove + iter: slice::Iter<'a, T>, + vec: NonNull>, +} + +#[stable(feature = "collection_debug", since = "1.17.0")] +impl fmt::Debug for Drain<'_, T, A> { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + f.debug_tuple("Drain").field(&self.iter.as_slice()).finish() + } +} + +impl<'a, T, A: Allocator> Drain<'a, T, A> { + /// Returns the remaining items of this iterator as a slice. + /// + /// # Examples + /// + /// ``` + /// let mut vec = vec!['a', 'b', 'c']; + /// let mut drain = vec.drain(..); + /// assert_eq!(drain.as_slice(), &['a', 'b', 'c']); + /// let _ = drain.next().unwrap(); + /// assert_eq!(drain.as_slice(), &['b', 'c']); + /// ``` + #[stable(feature = "vec_drain_as_slice", since = "1.46.0")] + pub fn as_slice(&self) -> &[T] { + self.iter.as_slice() + } + + /// Returns a reference to the underlying allocator. + #[unstable(feature = "allocator_api", issue = "32838")] + #[inline] + pub fn allocator(&self) -> &A { + unsafe { self.vec.as_ref().allocator() } + } +} + +#[stable(feature = "vec_drain_as_slice", since = "1.46.0")] +impl<'a, T, A: Allocator> AsRef<[T]> for Drain<'a, T, A> { + fn as_ref(&self) -> &[T] { + self.as_slice() + } +} + +#[stable(feature = "drain", since = "1.6.0")] +unsafe impl Sync for Drain<'_, T, A> {} +#[stable(feature = "drain", since = "1.6.0")] +unsafe impl Send for Drain<'_, T, A> {} + +#[stable(feature = "drain", since = "1.6.0")] +impl Iterator for Drain<'_, T, A> { + type Item = T; + + #[inline] + fn next(&mut self) -> Option { + self.iter.next().map(|elt| unsafe { ptr::read(elt as *const _) }) + } + + fn size_hint(&self) -> (usize, Option) { + self.iter.size_hint() + } +} + +#[stable(feature = "drain", since = "1.6.0")] +impl DoubleEndedIterator for Drain<'_, T, A> { + #[inline] + fn next_back(&mut self) -> Option { + self.iter.next_back().map(|elt| unsafe { ptr::read(elt as *const _) }) + } +} + +#[stable(feature = "drain", since = "1.6.0")] +impl Drop for Drain<'_, T, A> { + fn drop(&mut self) { + /// Continues dropping the remaining elements in the `Drain`, then moves back the + /// un-`Drain`ed elements to restore the original `Vec`. + struct DropGuard<'r, 'a, T, A: Allocator>(&'r mut Drain<'a, T, A>); + + impl<'r, 'a, T, A: Allocator> Drop for DropGuard<'r, 'a, T, A> { + fn drop(&mut self) { + // Continue the same loop we have below. If the loop already finished, this does + // nothing. + self.0.for_each(drop); + + if self.0.tail_len > 0 { + unsafe { + let source_vec = self.0.vec.as_mut(); + // memmove back untouched tail, update to new length + let start = source_vec.len(); + let tail = self.0.tail_start; + if tail != start { + let src = source_vec.as_ptr().add(tail); + let dst = source_vec.as_mut_ptr().add(start); + ptr::copy(src, dst, self.0.tail_len); + } + source_vec.set_len(start + self.0.tail_len); + } + } + } + } + + // exhaust self first + while let Some(item) = self.next() { + let guard = DropGuard(self); + drop(item); + mem::forget(guard); + } + + // Drop a `DropGuard` to move back the non-drained tail of `self`. + DropGuard(self); + } +} + +#[stable(feature = "drain", since = "1.6.0")] +impl ExactSizeIterator for Drain<'_, T, A> { + fn is_empty(&self) -> bool { + self.iter.is_empty() + } +} + +#[unstable(feature = "trusted_len", issue = "37572")] +unsafe impl TrustedLen for Drain<'_, T, A> {} + +#[stable(feature = "fused", since = "1.26.0")] +impl FusedIterator for Drain<'_, T, A> {} + +/// A splicing iterator for `Vec`. +/// +/// This struct is created by [`Vec::splice()`]. +/// See its documentation for more. +/// +/// # Example +/// +/// ``` +/// let mut v = vec![0, 1, 2]; +/// let new = [7, 8]; +/// let iter: std::vec::Splice<_> = v.splice(1.., new.iter().cloned()); +/// ``` +#[derive(Debug)] +#[stable(feature = "vec_splice", since = "1.21.0")] +pub struct Splice< + 'a, + I: Iterator + 'a, + #[unstable(feature = "allocator_api", issue = "32838")] A: Allocator + 'a = Global, +> { + drain: Drain<'a, I::Item, A>, + replace_with: I, +} + +#[stable(feature = "vec_splice", since = "1.21.0")] +impl Iterator for Splice<'_, I, A> { + type Item = I::Item; + + fn next(&mut self) -> Option { + self.drain.next() + } + + fn size_hint(&self) -> (usize, Option) { + self.drain.size_hint() + } +} + +#[stable(feature = "vec_splice", since = "1.21.0")] +impl DoubleEndedIterator for Splice<'_, I, A> { + fn next_back(&mut self) -> Option { + self.drain.next_back() + } +} + +#[stable(feature = "vec_splice", since = "1.21.0")] +impl ExactSizeIterator for Splice<'_, I, A> {} + +#[stable(feature = "vec_splice", since = "1.21.0")] +impl Drop for Splice<'_, I, A> { + fn drop(&mut self) { + self.drain.by_ref().for_each(drop); + + unsafe { + if self.drain.tail_len == 0 { + self.drain.vec.as_mut().extend(self.replace_with.by_ref()); + return; + } + + // First fill the range left by drain(). + if !self.drain.fill(&mut self.replace_with) { + return; + } + + // There may be more elements. Use the lower bound as an estimate. + // FIXME: Is the upper bound a better guess? Or something else? + let (lower_bound, _upper_bound) = self.replace_with.size_hint(); + if lower_bound > 0 { + self.drain.move_tail(lower_bound); + if !self.drain.fill(&mut self.replace_with) { + return; + } + } + + // Collect any remaining elements. + // This is a zero-length vector which does not allocate if `lower_bound` was exact. + let mut collected = self.replace_with.by_ref().collect::>().into_iter(); + // Now we have an exact count. + if collected.len() > 0 { + self.drain.move_tail(collected.len()); + let filled = self.drain.fill(&mut collected); + debug_assert!(filled); + debug_assert_eq!(collected.len(), 0); + } + } + // Let `Drain::drop` move the tail back if necessary and restore `vec.len`. + } +} + +/// Private helper methods for `Splice::drop` +impl Drain<'_, T, A> { + /// The range from `self.vec.len` to `self.tail_start` contains elements + /// that have been moved out. + /// Fill that range as much as possible with new elements from the `replace_with` iterator. + /// Returns `true` if we filled the entire range. (`replace_with.next()` didn’t return `None`.) + unsafe fn fill>(&mut self, replace_with: &mut I) -> bool { + let vec = unsafe { self.vec.as_mut() }; + let range_start = vec.len; + let range_end = self.tail_start; + let range_slice = unsafe { + slice::from_raw_parts_mut(vec.as_mut_ptr().add(range_start), range_end - range_start) + }; + + for place in range_slice { + if let Some(new_item) = replace_with.next() { + unsafe { ptr::write(place, new_item) }; + vec.len += 1; + } else { + return false; + } + } + true + } + + /// Makes room for inserting more elements before the tail. + unsafe fn move_tail(&mut self, additional: usize) { + let vec = unsafe { self.vec.as_mut() }; + let len = self.tail_start + self.tail_len; + vec.buf.reserve(len, additional); + + let new_tail_start = self.tail_start + additional; + unsafe { + let src = vec.as_ptr().add(self.tail_start); + let dst = vec.as_mut_ptr().add(new_tail_start); + ptr::copy(src, dst, self.tail_len); + } + self.tail_start = new_tail_start; + } +} + +/// An iterator which uses a closure to determine if an element should be removed. +/// +/// This struct is created by [`Vec::drain_filter`]. +/// See its documentation for more. +/// +/// # Example +/// +/// ``` +/// #![feature(drain_filter)] +/// +/// let mut v = vec![0, 1, 2]; +/// let iter: std::vec::DrainFilter<_, _> = v.drain_filter(|x| *x % 2 == 0); +/// ``` +#[unstable(feature = "drain_filter", reason = "recently added", issue = "43244")] +#[derive(Debug)] +pub struct DrainFilter< + 'a, + T, + F, + #[unstable(feature = "allocator_api", issue = "32838")] A: Allocator = Global, +> where + F: FnMut(&mut T) -> bool, +{ + vec: &'a mut Vec, + /// The index of the item that will be inspected by the next call to `next`. + idx: usize, + /// The number of items that have been drained (removed) thus far. + del: usize, + /// The original length of `vec` prior to draining. + old_len: usize, + /// The filter test predicate. + pred: F, + /// A flag that indicates a panic has occurred in the filter test predicate. + /// This is used as a hint in the drop implementation to prevent consumption + /// of the remainder of the `DrainFilter`. Any unprocessed items will be + /// backshifted in the `vec`, but no further items will be dropped or + /// tested by the filter predicate. + panic_flag: bool, +} + +impl DrainFilter<'_, T, F, A> +where + F: FnMut(&mut T) -> bool, +{ + /// Returns a reference to the underlying allocator. + #[unstable(feature = "allocator_api", issue = "32838")] + #[inline] + pub fn allocator(&self) -> &A { + self.vec.allocator() + } +} + +#[unstable(feature = "drain_filter", reason = "recently added", issue = "43244")] +impl Iterator for DrainFilter<'_, T, F, A> +where + F: FnMut(&mut T) -> bool, +{ + type Item = T; + + fn next(&mut self) -> Option { + unsafe { + while self.idx < self.old_len { + let i = self.idx; + let v = slice::from_raw_parts_mut(self.vec.as_mut_ptr(), self.old_len); + self.panic_flag = true; + let drained = (self.pred)(&mut v[i]); + self.panic_flag = false; + // Update the index *after* the predicate is called. If the index + // is updated prior and the predicate panics, the element at this + // index would be leaked. + self.idx += 1; + if drained { + self.del += 1; + return Some(ptr::read(&v[i])); + } else if self.del > 0 { + let del = self.del; + let src: *const T = &v[i]; + let dst: *mut T = &mut v[i - del]; + ptr::copy_nonoverlapping(src, dst, 1); + } + } + None + } + } + + fn size_hint(&self) -> (usize, Option) { + (0, Some(self.old_len - self.idx)) + } +} + +#[unstable(feature = "drain_filter", reason = "recently added", issue = "43244")] +impl Drop for DrainFilter<'_, T, F, A> +where + F: FnMut(&mut T) -> bool, +{ + fn drop(&mut self) { + struct BackshiftOnDrop<'a, 'b, T, F, A: Allocator> + where + F: FnMut(&mut T) -> bool, + { + drain: &'b mut DrainFilter<'a, T, F, A>, + } + + impl<'a, 'b, T, F, A: Allocator> Drop for BackshiftOnDrop<'a, 'b, T, F, A> + where + F: FnMut(&mut T) -> bool, + { + fn drop(&mut self) { + unsafe { + if self.drain.idx < self.drain.old_len && self.drain.del > 0 { + // This is a pretty messed up state, and there isn't really an + // obviously right thing to do. We don't want to keep trying + // to execute `pred`, so we just backshift all the unprocessed + // elements and tell the vec that they still exist. The backshift + // is required to prevent a double-drop of the last successfully + // drained item prior to a panic in the predicate. + let ptr = self.drain.vec.as_mut_ptr(); + let src = ptr.add(self.drain.idx); + let dst = src.sub(self.drain.del); + let tail_len = self.drain.old_len - self.drain.idx; + src.copy_to(dst, tail_len); + } + self.drain.vec.set_len(self.drain.old_len - self.drain.del); + } + } + } + + let backshift = BackshiftOnDrop { drain: self }; + + // Attempt to consume any remaining elements if the filter predicate + // has not yet panicked. We'll backshift any remaining elements + // whether we've already panicked or if the consumption here panics. + if !backshift.drain.panic_flag { + backshift.drain.for_each(drop); + } + } +} -- cgit 1.4.1-3-g733a5 From 434e5d142204d9b3019cfedc049d39b0affd08e7 Mon Sep 17 00:00:00 2001 From: C Date: Fri, 4 Dec 2020 23:58:11 +0000 Subject: refactor: moving DrainFilter into drain_filter.rs --- library/alloc/src/vec/drain_filter.rs | 143 ++++++++++++++++++++++++++++++++++ library/alloc/src/vec/mod.rs | 143 ++-------------------------------- 2 files changed, 148 insertions(+), 138 deletions(-) create mode 100644 library/alloc/src/vec/drain_filter.rs (limited to 'library/alloc/src') diff --git a/library/alloc/src/vec/drain_filter.rs b/library/alloc/src/vec/drain_filter.rs new file mode 100644 index 00000000000..9d898c7c756 --- /dev/null +++ b/library/alloc/src/vec/drain_filter.rs @@ -0,0 +1,143 @@ +use core::ptr::{self}; +use core::slice::{self}; +use crate::alloc::{Allocator, Global}; + +use super::{Vec}; + +/// An iterator which uses a closure to determine if an element should be removed. +/// +/// This struct is created by [`Vec::drain_filter`]. +/// See its documentation for more. +/// +/// # Example +/// +/// ``` +/// #![feature(drain_filter)] +/// +/// let mut v = vec![0, 1, 2]; +/// let iter: std::vec::DrainFilter<_, _> = v.drain_filter(|x| *x % 2 == 0); +/// ``` +#[unstable(feature = "drain_filter", reason = "recently added", issue = "43244")] +#[derive(Debug)] +pub struct DrainFilter< + 'a, + T, + F, + #[unstable(feature = "allocator_api", issue = "32838")] A: Allocator = Global, +> where + F: FnMut(&mut T) -> bool, +{ + pub(super) vec: &'a mut Vec, + /// The index of the item that will be inspected by the next call to `next`. + pub(super) idx: usize, + /// The number of items that have been drained (removed) thus far. + pub(super) del: usize, + /// The original length of `vec` prior to draining. + pub(super) old_len: usize, + /// The filter test predicate. + pub(super) pred: F, + /// A flag that indicates a panic has occurred in the filter test predicate. + /// This is used as a hint in the drop implementation to prevent consumption + /// of the remainder of the `DrainFilter`. Any unprocessed items will be + /// backshifted in the `vec`, but no further items will be dropped or + /// tested by the filter predicate. + pub(super) panic_flag: bool, +} + +impl DrainFilter<'_, T, F, A> + where + F: FnMut(&mut T) -> bool, +{ + /// Returns a reference to the underlying allocator. + #[unstable(feature = "allocator_api", issue = "32838")] + #[inline] + pub fn allocator(&self) -> &A { + self.vec.allocator() + } +} + +#[unstable(feature = "drain_filter", reason = "recently added", issue = "43244")] +impl Iterator for DrainFilter<'_, T, F, A> + where + F: FnMut(&mut T) -> bool, +{ + type Item = T; + + fn next(&mut self) -> Option { + unsafe { + while self.idx < self.old_len { + let i = self.idx; + let v = slice::from_raw_parts_mut(self.vec.as_mut_ptr(), self.old_len); + self.panic_flag = true; + let drained = (self.pred)(&mut v[i]); + self.panic_flag = false; + // Update the index *after* the predicate is called. If the index + // is updated prior and the predicate panics, the element at this + // index would be leaked. + self.idx += 1; + if drained { + self.del += 1; + return Some(ptr::read(&v[i])); + } else if self.del > 0 { + let del = self.del; + let src: *const T = &v[i]; + let dst: *mut T = &mut v[i - del]; + ptr::copy_nonoverlapping(src, dst, 1); + } + } + None + } + } + + fn size_hint(&self) -> (usize, Option) { + (0, Some(self.old_len - self.idx)) + } +} + +#[unstable(feature = "drain_filter", reason = "recently added", issue = "43244")] +impl Drop for DrainFilter<'_, T, F, A> + where + F: FnMut(&mut T) -> bool, +{ + fn drop(&mut self) { + struct BackshiftOnDrop<'a, 'b, T, F, A: Allocator> + where + F: FnMut(&mut T) -> bool, + { + drain: &'b mut DrainFilter<'a, T, F, A>, + } + + impl<'a, 'b, T, F, A: Allocator> Drop for BackshiftOnDrop<'a, 'b, T, F, A> + where + F: FnMut(&mut T) -> bool, + { + fn drop(&mut self) { + unsafe { + if self.drain.idx < self.drain.old_len && self.drain.del > 0 { + // This is a pretty messed up state, and there isn't really an + // obviously right thing to do. We don't want to keep trying + // to execute `pred`, so we just backshift all the unprocessed + // elements and tell the vec that they still exist. The backshift + // is required to prevent a double-drop of the last successfully + // drained item prior to a panic in the predicate. + let ptr = self.drain.vec.as_mut_ptr(); + let src = ptr.add(self.drain.idx); + let dst = src.sub(self.drain.del); + let tail_len = self.drain.old_len - self.drain.idx; + src.copy_to(dst, tail_len); + } + self.drain.vec.set_len(self.drain.old_len - self.drain.del); + } + } + } + + let backshift = BackshiftOnDrop { drain: self }; + + // Attempt to consume any remaining elements if the filter predicate + // has not yet panicked. We'll backshift any remaining elements + // whether we've already panicked or if the consumption here panics. + if !backshift.drain.panic_flag { + backshift.drain.for_each(drop); + } + } +} \ No newline at end of file diff --git a/library/alloc/src/vec/mod.rs b/library/alloc/src/vec/mod.rs index c9fa41138cd..2fb1fe0d5cb 100644 --- a/library/alloc/src/vec/mod.rs +++ b/library/alloc/src/vec/mod.rs @@ -74,6 +74,11 @@ use crate::boxed::Box; use crate::collections::TryReserveError; use crate::raw_vec::RawVec; +#[unstable(feature = "drain_filter", reason = "recently added", issue = "43244")] +pub use self::drain_filter::DrainFilter; + +mod drain_filter; + /// A contiguous growable array type, written `Vec` but pronounced 'vector'. /// /// # Examples @@ -3585,141 +3590,3 @@ impl Drain<'_, T, A> { self.tail_start = new_tail_start; } } - -/// An iterator which uses a closure to determine if an element should be removed. -/// -/// This struct is created by [`Vec::drain_filter`]. -/// See its documentation for more. -/// -/// # Example -/// -/// ``` -/// #![feature(drain_filter)] -/// -/// let mut v = vec![0, 1, 2]; -/// let iter: std::vec::DrainFilter<_, _> = v.drain_filter(|x| *x % 2 == 0); -/// ``` -#[unstable(feature = "drain_filter", reason = "recently added", issue = "43244")] -#[derive(Debug)] -pub struct DrainFilter< - 'a, - T, - F, - #[unstable(feature = "allocator_api", issue = "32838")] A: Allocator = Global, -> where - F: FnMut(&mut T) -> bool, -{ - vec: &'a mut Vec, - /// The index of the item that will be inspected by the next call to `next`. - idx: usize, - /// The number of items that have been drained (removed) thus far. - del: usize, - /// The original length of `vec` prior to draining. - old_len: usize, - /// The filter test predicate. - pred: F, - /// A flag that indicates a panic has occurred in the filter test predicate. - /// This is used as a hint in the drop implementation to prevent consumption - /// of the remainder of the `DrainFilter`. Any unprocessed items will be - /// backshifted in the `vec`, but no further items will be dropped or - /// tested by the filter predicate. - panic_flag: bool, -} - -impl DrainFilter<'_, T, F, A> -where - F: FnMut(&mut T) -> bool, -{ - /// Returns a reference to the underlying allocator. - #[unstable(feature = "allocator_api", issue = "32838")] - #[inline] - pub fn allocator(&self) -> &A { - self.vec.allocator() - } -} - -#[unstable(feature = "drain_filter", reason = "recently added", issue = "43244")] -impl Iterator for DrainFilter<'_, T, F, A> -where - F: FnMut(&mut T) -> bool, -{ - type Item = T; - - fn next(&mut self) -> Option { - unsafe { - while self.idx < self.old_len { - let i = self.idx; - let v = slice::from_raw_parts_mut(self.vec.as_mut_ptr(), self.old_len); - self.panic_flag = true; - let drained = (self.pred)(&mut v[i]); - self.panic_flag = false; - // Update the index *after* the predicate is called. If the index - // is updated prior and the predicate panics, the element at this - // index would be leaked. - self.idx += 1; - if drained { - self.del += 1; - return Some(ptr::read(&v[i])); - } else if self.del > 0 { - let del = self.del; - let src: *const T = &v[i]; - let dst: *mut T = &mut v[i - del]; - ptr::copy_nonoverlapping(src, dst, 1); - } - } - None - } - } - - fn size_hint(&self) -> (usize, Option) { - (0, Some(self.old_len - self.idx)) - } -} - -#[unstable(feature = "drain_filter", reason = "recently added", issue = "43244")] -impl Drop for DrainFilter<'_, T, F, A> -where - F: FnMut(&mut T) -> bool, -{ - fn drop(&mut self) { - struct BackshiftOnDrop<'a, 'b, T, F, A: Allocator> - where - F: FnMut(&mut T) -> bool, - { - drain: &'b mut DrainFilter<'a, T, F, A>, - } - - impl<'a, 'b, T, F, A: Allocator> Drop for BackshiftOnDrop<'a, 'b, T, F, A> - where - F: FnMut(&mut T) -> bool, - { - fn drop(&mut self) { - unsafe { - if self.drain.idx < self.drain.old_len && self.drain.del > 0 { - // This is a pretty messed up state, and there isn't really an - // obviously right thing to do. We don't want to keep trying - // to execute `pred`, so we just backshift all the unprocessed - // elements and tell the vec that they still exist. The backshift - // is required to prevent a double-drop of the last successfully - // drained item prior to a panic in the predicate. - let ptr = self.drain.vec.as_mut_ptr(); - let src = ptr.add(self.drain.idx); - let dst = src.sub(self.drain.del); - let tail_len = self.drain.old_len - self.drain.idx; - src.copy_to(dst, tail_len); - } - self.drain.vec.set_len(self.drain.old_len - self.drain.del); - } - } - } - - let backshift = BackshiftOnDrop { drain: self }; - - // Attempt to consume any remaining elements if the filter predicate - // has not yet panicked. We'll backshift any remaining elements - // whether we've already panicked or if the consumption here panics. - if !backshift.drain.panic_flag { - backshift.drain.for_each(drop); - } - } -} -- cgit 1.4.1-3-g733a5 From 17593f258b5bc8a4778df35bf9a82950738b70e8 Mon Sep 17 00:00:00 2001 From: C Date: Sat, 5 Dec 2020 00:04:32 +0000 Subject: refactor: moving Splice into splice.rs --- library/alloc/src/vec/mod.rs | 133 ++-------------------------------------- library/alloc/src/vec/splice.rs | 133 ++++++++++++++++++++++++++++++++++++++++ 2 files changed, 138 insertions(+), 128 deletions(-) create mode 100644 library/alloc/src/vec/splice.rs (limited to 'library/alloc/src') diff --git a/library/alloc/src/vec/mod.rs b/library/alloc/src/vec/mod.rs index 2fb1fe0d5cb..924b04a8fe1 100644 --- a/library/alloc/src/vec/mod.rs +++ b/library/alloc/src/vec/mod.rs @@ -79,6 +79,11 @@ pub use self::drain_filter::DrainFilter; mod drain_filter; +#[stable(feature = "vec_splice", since = "1.21.0")] +pub use self::splice::Splice; + +mod splice; + /// A contiguous growable array type, written `Vec` but pronounced 'vector'. /// /// # Examples @@ -3462,131 +3467,3 @@ unsafe impl TrustedLen for Drain<'_, T, A> {} #[stable(feature = "fused", since = "1.26.0")] impl FusedIterator for Drain<'_, T, A> {} - -/// A splicing iterator for `Vec`. -/// -/// This struct is created by [`Vec::splice()`]. -/// See its documentation for more. -/// -/// # Example -/// -/// ``` -/// let mut v = vec![0, 1, 2]; -/// let new = [7, 8]; -/// let iter: std::vec::Splice<_> = v.splice(1.., new.iter().cloned()); -/// ``` -#[derive(Debug)] -#[stable(feature = "vec_splice", since = "1.21.0")] -pub struct Splice< - 'a, - I: Iterator + 'a, - #[unstable(feature = "allocator_api", issue = "32838")] A: Allocator + 'a = Global, -> { - drain: Drain<'a, I::Item, A>, - replace_with: I, -} - -#[stable(feature = "vec_splice", since = "1.21.0")] -impl Iterator for Splice<'_, I, A> { - type Item = I::Item; - - fn next(&mut self) -> Option { - self.drain.next() - } - - fn size_hint(&self) -> (usize, Option) { - self.drain.size_hint() - } -} - -#[stable(feature = "vec_splice", since = "1.21.0")] -impl DoubleEndedIterator for Splice<'_, I, A> { - fn next_back(&mut self) -> Option { - self.drain.next_back() - } -} - -#[stable(feature = "vec_splice", since = "1.21.0")] -impl ExactSizeIterator for Splice<'_, I, A> {} - -#[stable(feature = "vec_splice", since = "1.21.0")] -impl Drop for Splice<'_, I, A> { - fn drop(&mut self) { - self.drain.by_ref().for_each(drop); - - unsafe { - if self.drain.tail_len == 0 { - self.drain.vec.as_mut().extend(self.replace_with.by_ref()); - return; - } - - // First fill the range left by drain(). - if !self.drain.fill(&mut self.replace_with) { - return; - } - - // There may be more elements. Use the lower bound as an estimate. - // FIXME: Is the upper bound a better guess? Or something else? - let (lower_bound, _upper_bound) = self.replace_with.size_hint(); - if lower_bound > 0 { - self.drain.move_tail(lower_bound); - if !self.drain.fill(&mut self.replace_with) { - return; - } - } - - // Collect any remaining elements. - // This is a zero-length vector which does not allocate if `lower_bound` was exact. - let mut collected = self.replace_with.by_ref().collect::>().into_iter(); - // Now we have an exact count. - if collected.len() > 0 { - self.drain.move_tail(collected.len()); - let filled = self.drain.fill(&mut collected); - debug_assert!(filled); - debug_assert_eq!(collected.len(), 0); - } - } - // Let `Drain::drop` move the tail back if necessary and restore `vec.len`. - } -} - -/// Private helper methods for `Splice::drop` -impl Drain<'_, T, A> { - /// The range from `self.vec.len` to `self.tail_start` contains elements - /// that have been moved out. - /// Fill that range as much as possible with new elements from the `replace_with` iterator. - /// Returns `true` if we filled the entire range. (`replace_with.next()` didn’t return `None`.) - unsafe fn fill>(&mut self, replace_with: &mut I) -> bool { - let vec = unsafe { self.vec.as_mut() }; - let range_start = vec.len; - let range_end = self.tail_start; - let range_slice = unsafe { - slice::from_raw_parts_mut(vec.as_mut_ptr().add(range_start), range_end - range_start) - }; - - for place in range_slice { - if let Some(new_item) = replace_with.next() { - unsafe { ptr::write(place, new_item) }; - vec.len += 1; - } else { - return false; - } - } - true - } - - /// Makes room for inserting more elements before the tail. - unsafe fn move_tail(&mut self, additional: usize) { - let vec = unsafe { self.vec.as_mut() }; - let len = self.tail_start + self.tail_len; - vec.buf.reserve(len, additional); - - let new_tail_start = self.tail_start + additional; - unsafe { - let src = vec.as_ptr().add(self.tail_start); - let dst = vec.as_mut_ptr().add(new_tail_start); - ptr::copy(src, dst, self.tail_len); - } - self.tail_start = new_tail_start; - } -} diff --git a/library/alloc/src/vec/splice.rs b/library/alloc/src/vec/splice.rs new file mode 100644 index 00000000000..86b2fa0968e --- /dev/null +++ b/library/alloc/src/vec/splice.rs @@ -0,0 +1,133 @@ +use crate::alloc::{Allocator, Global}; +use core::ptr::{self}; +use core::slice::{self}; + +use super::{Vec, Drain}; + +/// A splicing iterator for `Vec`. +/// +/// This struct is created by [`Vec::splice()`]. +/// See its documentation for more. +/// +/// # Example +/// +/// ``` +/// let mut v = vec![0, 1, 2]; +/// let new = [7, 8]; +/// let iter: std::vec::Splice<_> = v.splice(1.., new.iter().cloned()); +/// ``` +#[derive(Debug)] +#[stable(feature = "vec_splice", since = "1.21.0")] +pub struct Splice< + 'a, + I: Iterator + 'a, + #[unstable(feature = "allocator_api", issue = "32838")] A: Allocator + 'a = Global, +> { + pub(super) drain: Drain<'a, I::Item, A>, + pub(super) replace_with: I, +} + +#[stable(feature = "vec_splice", since = "1.21.0")] +impl Iterator for Splice<'_, I, A> { + type Item = I::Item; + + fn next(&mut self) -> Option { + self.drain.next() + } + + fn size_hint(&self) -> (usize, Option) { + self.drain.size_hint() + } +} + +#[stable(feature = "vec_splice", since = "1.21.0")] +impl DoubleEndedIterator for Splice<'_, I, A> { + fn next_back(&mut self) -> Option { + self.drain.next_back() + } +} + +#[stable(feature = "vec_splice", since = "1.21.0")] +impl ExactSizeIterator for Splice<'_, I, A> {} + +#[stable(feature = "vec_splice", since = "1.21.0")] +impl Drop for Splice<'_, I, A> { + fn drop(&mut self) { + self.drain.by_ref().for_each(drop); + + unsafe { + if self.drain.tail_len == 0 { + self.drain.vec.as_mut().extend(self.replace_with.by_ref()); + return; + } + + // First fill the range left by drain(). + if !self.drain.fill(&mut self.replace_with) { + return; + } + + // There may be more elements. Use the lower bound as an estimate. + // FIXME: Is the upper bound a better guess? Or something else? + let (lower_bound, _upper_bound) = self.replace_with.size_hint(); + if lower_bound > 0 { + self.drain.move_tail(lower_bound); + if !self.drain.fill(&mut self.replace_with) { + return; + } + } + + // Collect any remaining elements. + // This is a zero-length vector which does not allocate if `lower_bound` was exact. + let mut collected = self.replace_with.by_ref().collect::>().into_iter(); + // Now we have an exact count. + if collected.len() > 0 { + self.drain.move_tail(collected.len()); + let filled = self.drain.fill(&mut collected); + debug_assert!(filled); + debug_assert_eq!(collected.len(), 0); + } + } + // Let `Drain::drop` move the tail back if necessary and restore `vec.len`. + } +} + +/// Private helper methods for `Splice::drop` +impl Drain<'_, T, A> { + /// The range from `self.vec.len` to `self.tail_start` contains elements + /// that have been moved out. + /// Fill that range as much as possible with new elements from the `replace_with` iterator. + /// Returns `true` if we filled the entire range. (`replace_with.next()` didn’t return `None`.) + unsafe fn fill>(&mut self, replace_with: &mut I) -> bool { + let vec = unsafe { self.vec.as_mut() }; + let range_start = vec.len; + let range_end = self.tail_start; + let range_slice = unsafe { + slice::from_raw_parts_mut(vec.as_mut_ptr().add(range_start), range_end - range_start) + }; + + for place in range_slice { + if let Some(new_item) = replace_with.next() { + unsafe { ptr::write(place, new_item) }; + vec.len += 1; + } else { + return false; + } + } + true + } + + /// Makes room for inserting more elements before the tail. + unsafe fn move_tail(&mut self, additional: usize) { + let vec = unsafe { self.vec.as_mut() }; + let len = self.tail_start + self.tail_len; + vec.buf.reserve(len, additional); + + let new_tail_start = self.tail_start + additional; + unsafe { + let src = vec.as_ptr().add(self.tail_start); + let dst = vec.as_mut_ptr().add(new_tail_start); + ptr::copy(src, dst, self.tail_len); + } + self.tail_start = new_tail_start; + } +} \ No newline at end of file -- cgit 1.4.1-3-g733a5 From 6bf9608f9fd22c10f8ba37b416b6a0d4431ef59a Mon Sep 17 00:00:00 2001 From: C Date: Sat, 5 Dec 2020 00:12:42 +0000 Subject: refactor: moving Drain into drain.rs --- library/alloc/src/vec/drain.rs | 157 +++++++++++++++++++++++++++++++++++++++++ library/alloc/src/vec/mod.rs | 152 ++------------------------------------- 2 files changed, 162 insertions(+), 147 deletions(-) create mode 100644 library/alloc/src/vec/drain.rs (limited to 'library/alloc/src') diff --git a/library/alloc/src/vec/drain.rs b/library/alloc/src/vec/drain.rs new file mode 100644 index 00000000000..e61f17a1c30 --- /dev/null +++ b/library/alloc/src/vec/drain.rs @@ -0,0 +1,157 @@ +use crate::alloc::{Allocator, Global}; +use core::iter::{ + FusedIterator, TrustedLen, +}; +use core::mem::{self}; +use core::ptr::{self, NonNull}; +use core::slice::{self}; +use core::fmt; + +use super::{Vec}; + +/// A draining iterator for `Vec`. +/// +/// This `struct` is created by [`Vec::drain`]. +/// See its documentation for more. +/// +/// # Example +/// +/// ``` +/// let mut v = vec![0, 1, 2]; +/// let iter: std::vec::Drain<_> = v.drain(..); +/// ``` +#[stable(feature = "drain", since = "1.6.0")] +pub struct Drain< + 'a, + T: 'a, + #[unstable(feature = "allocator_api", issue = "32838")] A: Allocator + 'a = Global, +> { + /// Index of tail to preserve + pub(super) tail_start: usize, + /// Length of tail + pub(super) tail_len: usize, + /// Current remaining range to remove + pub(super) iter: slice::Iter<'a, T>, + pub(super) vec: NonNull>, +} + +#[stable(feature = "collection_debug", since = "1.17.0")] +impl fmt::Debug for Drain<'_, T, A> { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + f.debug_tuple("Drain").field(&self.iter.as_slice()).finish() + } +} + +impl<'a, T, A: Allocator> Drain<'a, T, A> { + /// Returns the remaining items of this iterator as a slice. + /// + /// # Examples + /// + /// ``` + /// let mut vec = vec!['a', 'b', 'c']; + /// let mut drain = vec.drain(..); + /// assert_eq!(drain.as_slice(), &['a', 'b', 'c']); + /// let _ = drain.next().unwrap(); + /// assert_eq!(drain.as_slice(), &['b', 'c']); + /// ``` + #[stable(feature = "vec_drain_as_slice", since = "1.46.0")] + pub fn as_slice(&self) -> &[T] { + self.iter.as_slice() + } + + /// Returns a reference to the underlying allocator. + #[unstable(feature = "allocator_api", issue = "32838")] + #[inline] + pub fn allocator(&self) -> &A { + unsafe { self.vec.as_ref().allocator() } + } +} + +#[stable(feature = "vec_drain_as_slice", since = "1.46.0")] +impl<'a, T, A: Allocator> AsRef<[T]> for Drain<'a, T, A> { + fn as_ref(&self) -> &[T] { + self.as_slice() + } +} + +#[stable(feature = "drain", since = "1.6.0")] +unsafe impl Sync for Drain<'_, T, A> {} +#[stable(feature = "drain", since = "1.6.0")] +unsafe impl Send for Drain<'_, T, A> {} + +#[stable(feature = "drain", since = "1.6.0")] +impl Iterator for Drain<'_, T, A> { + type Item = T; + + #[inline] + fn next(&mut self) -> Option { + self.iter.next().map(|elt| unsafe { ptr::read(elt as *const _) }) + } + + fn size_hint(&self) -> (usize, Option) { + self.iter.size_hint() + } +} + +#[stable(feature = "drain", since = "1.6.0")] +impl DoubleEndedIterator for Drain<'_, T, A> { + #[inline] + fn next_back(&mut self) -> Option { + self.iter.next_back().map(|elt| unsafe { ptr::read(elt as *const _) }) + } +} + +#[stable(feature = "drain", since = "1.6.0")] +impl Drop for Drain<'_, T, A> { + fn drop(&mut self) { + /// Continues dropping the remaining elements in the `Drain`, then moves back the + /// un-`Drain`ed elements to restore the original `Vec`. + struct DropGuard<'r, 'a, T, A: Allocator>(&'r mut Drain<'a, T, A>); + + impl<'r, 'a, T, A: Allocator> Drop for DropGuard<'r, 'a, T, A> { + fn drop(&mut self) { + // Continue the same loop we have below. If the loop already finished, this does + // nothing. + self.0.for_each(drop); + + if self.0.tail_len > 0 { + unsafe { + let source_vec = self.0.vec.as_mut(); + // memmove back untouched tail, update to new length + let start = source_vec.len(); + let tail = self.0.tail_start; + if tail != start { + let src = source_vec.as_ptr().add(tail); + let dst = source_vec.as_mut_ptr().add(start); + ptr::copy(src, dst, self.0.tail_len); + } + source_vec.set_len(start + self.0.tail_len); + } + } + } + } + + // exhaust self first + while let Some(item) = self.next() { + let guard = DropGuard(self); + drop(item); + mem::forget(guard); + } + + // Drop a `DropGuard` to move back the non-drained tail of `self`. + DropGuard(self); + } +} + +#[stable(feature = "drain", since = "1.6.0")] +impl ExactSizeIterator for Drain<'_, T, A> { + fn is_empty(&self) -> bool { + self.iter.is_empty() + } +} + +#[unstable(feature = "trusted_len", issue = "37572")] +unsafe impl TrustedLen for Drain<'_, T, A> {} + +#[stable(feature = "fused", since = "1.26.0")] +impl FusedIterator for Drain<'_, T, A> {} diff --git a/library/alloc/src/vec/mod.rs b/library/alloc/src/vec/mod.rs index 924b04a8fe1..1553e367c87 100644 --- a/library/alloc/src/vec/mod.rs +++ b/library/alloc/src/vec/mod.rs @@ -84,6 +84,11 @@ pub use self::splice::Splice; mod splice; +#[stable(feature = "drain", since = "1.6.0")] +pub use self::drain::Drain; + +mod drain; + /// A contiguous growable array type, written `Vec` but pronounced 'vector'. /// /// # Examples @@ -3320,150 +3325,3 @@ impl AsIntoIter for IntoIter { self } } - -/// A draining iterator for `Vec`. -/// -/// This `struct` is created by [`Vec::drain`]. -/// See its documentation for more. -/// -/// # Example -/// -/// ``` -/// let mut v = vec![0, 1, 2]; -/// let iter: std::vec::Drain<_> = v.drain(..); -/// ``` -#[stable(feature = "drain", since = "1.6.0")] -pub struct Drain< - 'a, - T: 'a, - #[unstable(feature = "allocator_api", issue = "32838")] A: Allocator + 'a = Global, -> { - /// Index of tail to preserve - tail_start: usize, - /// Length of tail - tail_len: usize, - /// Current remaining range to remove - iter: slice::Iter<'a, T>, - vec: NonNull>, -} - -#[stable(feature = "collection_debug", since = "1.17.0")] -impl fmt::Debug for Drain<'_, T, A> { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - f.debug_tuple("Drain").field(&self.iter.as_slice()).finish() - } -} - -impl<'a, T, A: Allocator> Drain<'a, T, A> { - /// Returns the remaining items of this iterator as a slice. - /// - /// # Examples - /// - /// ``` - /// let mut vec = vec!['a', 'b', 'c']; - /// let mut drain = vec.drain(..); - /// assert_eq!(drain.as_slice(), &['a', 'b', 'c']); - /// let _ = drain.next().unwrap(); - /// assert_eq!(drain.as_slice(), &['b', 'c']); - /// ``` - #[stable(feature = "vec_drain_as_slice", since = "1.46.0")] - pub fn as_slice(&self) -> &[T] { - self.iter.as_slice() - } - - /// Returns a reference to the underlying allocator. - #[unstable(feature = "allocator_api", issue = "32838")] - #[inline] - pub fn allocator(&self) -> &A { - unsafe { self.vec.as_ref().allocator() } - } -} - -#[stable(feature = "vec_drain_as_slice", since = "1.46.0")] -impl<'a, T, A: Allocator> AsRef<[T]> for Drain<'a, T, A> { - fn as_ref(&self) -> &[T] { - self.as_slice() - } -} - -#[stable(feature = "drain", since = "1.6.0")] -unsafe impl Sync for Drain<'_, T, A> {} -#[stable(feature = "drain", since = "1.6.0")] -unsafe impl Send for Drain<'_, T, A> {} - -#[stable(feature = "drain", since = "1.6.0")] -impl Iterator for Drain<'_, T, A> { - type Item = T; - - #[inline] - fn next(&mut self) -> Option { - self.iter.next().map(|elt| unsafe { ptr::read(elt as *const _) }) - } - - fn size_hint(&self) -> (usize, Option) { - self.iter.size_hint() - } -} - -#[stable(feature = "drain", since = "1.6.0")] -impl DoubleEndedIterator for Drain<'_, T, A> { - #[inline] - fn next_back(&mut self) -> Option { - self.iter.next_back().map(|elt| unsafe { ptr::read(elt as *const _) }) - } -} - -#[stable(feature = "drain", since = "1.6.0")] -impl Drop for Drain<'_, T, A> { - fn drop(&mut self) { - /// Continues dropping the remaining elements in the `Drain`, then moves back the - /// un-`Drain`ed elements to restore the original `Vec`. - struct DropGuard<'r, 'a, T, A: Allocator>(&'r mut Drain<'a, T, A>); - - impl<'r, 'a, T, A: Allocator> Drop for DropGuard<'r, 'a, T, A> { - fn drop(&mut self) { - // Continue the same loop we have below. If the loop already finished, this does - // nothing. - self.0.for_each(drop); - - if self.0.tail_len > 0 { - unsafe { - let source_vec = self.0.vec.as_mut(); - // memmove back untouched tail, update to new length - let start = source_vec.len(); - let tail = self.0.tail_start; - if tail != start { - let src = source_vec.as_ptr().add(tail); - let dst = source_vec.as_mut_ptr().add(start); - ptr::copy(src, dst, self.0.tail_len); - } - source_vec.set_len(start + self.0.tail_len); - } - } - } - } - - // exhaust self first - while let Some(item) = self.next() { - let guard = DropGuard(self); - drop(item); - mem::forget(guard); - } - - // Drop a `DropGuard` to move back the non-drained tail of `self`. - DropGuard(self); - } -} - -#[stable(feature = "drain", since = "1.6.0")] -impl ExactSizeIterator for Drain<'_, T, A> { - fn is_empty(&self) -> bool { - self.iter.is_empty() - } -} - -#[unstable(feature = "trusted_len", issue = "37572")] -unsafe impl TrustedLen for Drain<'_, T, A> {} - -#[stable(feature = "fused", since = "1.26.0")] -impl FusedIterator for Drain<'_, T, A> {} -- cgit 1.4.1-3-g733a5 From 2580822b919257c8b7c81d3343c43733c216e26c Mon Sep 17 00:00:00 2001 From: C Date: Sat, 5 Dec 2020 00:17:25 +0000 Subject: refactor: moved Vec impl Cow into cow.rs --- library/alloc/src/vec/cow.rs | 35 +++++++++++++++++++++++++++++++++++ library/alloc/src/vec/mod.rs | 37 ++----------------------------------- 2 files changed, 37 insertions(+), 35 deletions(-) create mode 100644 library/alloc/src/vec/cow.rs (limited to 'library/alloc/src') diff --git a/library/alloc/src/vec/cow.rs b/library/alloc/src/vec/cow.rs new file mode 100644 index 00000000000..15942f9892d --- /dev/null +++ b/library/alloc/src/vec/cow.rs @@ -0,0 +1,35 @@ +use crate::borrow::Cow; +use core::iter::{FromIterator}; + +use super::{Vec}; + +#[stable(feature = "cow_from_vec", since = "1.8.0")] +impl<'a, T: Clone> From<&'a [T]> for Cow<'a, [T]> { + fn from(s: &'a [T]) -> Cow<'a, [T]> { + Cow::Borrowed(s) + } +} + +#[stable(feature = "cow_from_vec", since = "1.8.0")] +impl<'a, T: Clone> From> for Cow<'a, [T]> { + fn from(v: Vec) -> Cow<'a, [T]> { + Cow::Owned(v) + } +} + +#[stable(feature = "cow_from_vec_ref", since = "1.28.0")] +impl<'a, T: Clone> From<&'a Vec> for Cow<'a, [T]> { + fn from(v: &'a Vec) -> Cow<'a, [T]> { + Cow::Borrowed(v.as_slice()) + } +} + +#[stable(feature = "rust1", since = "1.0.0")] +impl<'a, T> FromIterator for Cow<'a, [T]> + where + T: Clone, +{ + fn from_iter>(it: I) -> Cow<'a, [T]> { + Cow::Owned(FromIterator::from_iter(it)) + } +} \ No newline at end of file diff --git a/library/alloc/src/vec/mod.rs b/library/alloc/src/vec/mod.rs index 1553e367c87..8d3f8b0bfd8 100644 --- a/library/alloc/src/vec/mod.rs +++ b/library/alloc/src/vec/mod.rs @@ -89,6 +89,8 @@ pub use self::drain::Drain; mod drain; +mod cow; + /// A contiguous growable array type, written `Vec` but pronounced 'vector'. /// /// # Examples @@ -3013,41 +3015,6 @@ impl TryFrom> for [T; N] { } } -//////////////////////////////////////////////////////////////////////////////// -// Clone-on-write -//////////////////////////////////////////////////////////////////////////////// - -#[stable(feature = "cow_from_vec", since = "1.8.0")] -impl<'a, T: Clone> From<&'a [T]> for Cow<'a, [T]> { - fn from(s: &'a [T]) -> Cow<'a, [T]> { - Cow::Borrowed(s) - } -} - -#[stable(feature = "cow_from_vec", since = "1.8.0")] -impl<'a, T: Clone> From> for Cow<'a, [T]> { - fn from(v: Vec) -> Cow<'a, [T]> { - Cow::Owned(v) - } -} - -#[stable(feature = "cow_from_vec_ref", since = "1.28.0")] -impl<'a, T: Clone> From<&'a Vec> for Cow<'a, [T]> { - fn from(v: &'a Vec) -> Cow<'a, [T]> { - Cow::Borrowed(v.as_slice()) - } -} - -#[stable(feature = "rust1", since = "1.0.0")] -impl<'a, T> FromIterator for Cow<'a, [T]> -where - T: Clone, -{ - fn from_iter>(it: I) -> Cow<'a, [T]> { - Cow::Owned(FromIterator::from_iter(it)) - } -} - //////////////////////////////////////////////////////////////////////////////// // Iterators //////////////////////////////////////////////////////////////////////////////// -- cgit 1.4.1-3-g733a5 From 93613901d004ccf0b8a240bf328559a4128ac3b2 Mon Sep 17 00:00:00 2001 From: C Date: Sat, 5 Dec 2020 00:45:20 +0000 Subject: refactor: moved IntoIter into into_iter.rs --- library/alloc/src/vec/into_iter.rs | 270 +++++++++++++++++++++++++++++++++++++ library/alloc/src/vec/mod.rs | 270 +------------------------------------ 2 files changed, 276 insertions(+), 264 deletions(-) create mode 100644 library/alloc/src/vec/into_iter.rs (limited to 'library/alloc/src') diff --git a/library/alloc/src/vec/into_iter.rs b/library/alloc/src/vec/into_iter.rs new file mode 100644 index 00000000000..623792a6316 --- /dev/null +++ b/library/alloc/src/vec/into_iter.rs @@ -0,0 +1,270 @@ +use crate::alloc::{Allocator, Global}; +use crate::raw_vec::RawVec; +use core::marker::PhantomData; +use core::intrinsics::{arith_offset}; +use core::mem::{self}; +use core::fmt; +use core::ptr::{self, NonNull}; +use core::slice::{self}; +use core::iter::{ + FusedIterator, InPlaceIterable, SourceIter, TrustedLen, TrustedRandomAccess, +}; + +/// An iterator that moves out of a vector. +/// +/// This `struct` is created by the `into_iter` method on [`Vec`] (provided +/// by the [`IntoIterator`] trait). +/// +/// # Example +/// +/// ``` +/// let v = vec![0, 1, 2]; +/// let iter: std::vec::IntoIter<_> = v.into_iter(); +/// ``` +#[stable(feature = "rust1", since = "1.0.0")] +pub struct IntoIter< + T, + #[unstable(feature = "allocator_api", issue = "32838")] A: Allocator = Global, +> { + pub(super) buf: NonNull, + pub(super) phantom: PhantomData, + pub(super) cap: usize, + pub(super) alloc: A, + pub(super) ptr: *const T, + pub(super) end: *const T, +} + +#[stable(feature = "vec_intoiter_debug", since = "1.13.0")] +impl fmt::Debug for IntoIter { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + f.debug_tuple("IntoIter").field(&self.as_slice()).finish() + } +} + +impl IntoIter { + /// Returns the remaining items of this iterator as a slice. + /// + /// # Examples + /// + /// ``` + /// let vec = vec!['a', 'b', 'c']; + /// let mut into_iter = vec.into_iter(); + /// assert_eq!(into_iter.as_slice(), &['a', 'b', 'c']); + /// let _ = into_iter.next().unwrap(); + /// assert_eq!(into_iter.as_slice(), &['b', 'c']); + /// ``` + #[stable(feature = "vec_into_iter_as_slice", since = "1.15.0")] + pub fn as_slice(&self) -> &[T] { + unsafe { slice::from_raw_parts(self.ptr, self.len()) } + } + + /// Returns the remaining items of this iterator as a mutable slice. + /// + /// # Examples + /// + /// ``` + /// let vec = vec!['a', 'b', 'c']; + /// let mut into_iter = vec.into_iter(); + /// assert_eq!(into_iter.as_slice(), &['a', 'b', 'c']); + /// into_iter.as_mut_slice()[2] = 'z'; + /// assert_eq!(into_iter.next().unwrap(), 'a'); + /// assert_eq!(into_iter.next().unwrap(), 'b'); + /// assert_eq!(into_iter.next().unwrap(), 'z'); + /// ``` + #[stable(feature = "vec_into_iter_as_slice", since = "1.15.0")] + pub fn as_mut_slice(&mut self) -> &mut [T] { + unsafe { &mut *self.as_raw_mut_slice() } + } + + /// Returns a reference to the underlying allocator. + #[unstable(feature = "allocator_api", issue = "32838")] + #[inline] + pub fn allocator(&self) -> &A { + &self.alloc + } + + fn as_raw_mut_slice(&mut self) -> *mut [T] { + ptr::slice_from_raw_parts_mut(self.ptr as *mut T, self.len()) + } + + pub(super) fn drop_remaining(&mut self) { + unsafe { + ptr::drop_in_place(self.as_mut_slice()); + } + self.ptr = self.end; + } + + /// Relinquishes the backing allocation, equivalent to + /// `ptr::write(&mut self, Vec::new().into_iter())` + pub(super) fn forget_allocation(&mut self) { + self.cap = 0; + self.buf = unsafe { NonNull::new_unchecked(RawVec::NEW.ptr()) }; + self.ptr = self.buf.as_ptr(); + self.end = self.buf.as_ptr(); + } +} + +#[stable(feature = "vec_intoiter_as_ref", since = "1.46.0")] +impl AsRef<[T]> for IntoIter { + fn as_ref(&self) -> &[T] { + self.as_slice() + } +} + +#[stable(feature = "rust1", since = "1.0.0")] +unsafe impl Send for IntoIter {} +#[stable(feature = "rust1", since = "1.0.0")] +unsafe impl Sync for IntoIter {} + +#[stable(feature = "rust1", since = "1.0.0")] +impl Iterator for IntoIter { + type Item = T; + + #[inline] + fn next(&mut self) -> Option { + if self.ptr as *const _ == self.end { + None + } else if mem::size_of::() == 0 { + // purposefully don't use 'ptr.offset' because for + // vectors with 0-size elements this would return the + // same pointer. + self.ptr = unsafe { arith_offset(self.ptr as *const i8, 1) as *mut T }; + + // Make up a value of this ZST. + Some(unsafe { mem::zeroed() }) + } else { + let old = self.ptr; + self.ptr = unsafe { self.ptr.offset(1) }; + + Some(unsafe { ptr::read(old) }) + } + } + + #[inline] + fn size_hint(&self) -> (usize, Option) { + let exact = if mem::size_of::() == 0 { + (self.end as usize).wrapping_sub(self.ptr as usize) + } else { + unsafe { self.end.offset_from(self.ptr) as usize } + }; + (exact, Some(exact)) + } + + #[inline] + fn count(self) -> usize { + self.len() + } + + unsafe fn __iterator_get_unchecked(&mut self, i: usize) -> Self::Item + where + Self: TrustedRandomAccess, + { + // SAFETY: the caller must guarantee that `i` is in bounds of the + // `Vec`, so `i` cannot overflow an `isize`, and the `self.ptr.add(i)` + // is guaranteed to pointer to an element of the `Vec` and + // thus guaranteed to be valid to dereference. + // + // Also note the implementation of `Self: TrustedRandomAccess` requires + // that `T: Copy` so reading elements from the buffer doesn't invalidate + // them for `Drop`. + unsafe { + if mem::size_of::() == 0 { mem::zeroed() } else { ptr::read(self.ptr.add(i)) } + } + } +} + +#[stable(feature = "rust1", since = "1.0.0")] +impl DoubleEndedIterator for IntoIter { + #[inline] + fn next_back(&mut self) -> Option { + if self.end == self.ptr { + None + } else if mem::size_of::() == 0 { + // See above for why 'ptr.offset' isn't used + self.end = unsafe { arith_offset(self.end as *const i8, -1) as *mut T }; + + // Make up a value of this ZST. + Some(unsafe { mem::zeroed() }) + } else { + self.end = unsafe { self.end.offset(-1) }; + + Some(unsafe { ptr::read(self.end) }) + } + } +} + +#[stable(feature = "rust1", since = "1.0.0")] +impl ExactSizeIterator for IntoIter { + fn is_empty(&self) -> bool { + self.ptr == self.end + } +} + +#[stable(feature = "fused", since = "1.26.0")] +impl FusedIterator for IntoIter {} + +#[unstable(feature = "trusted_len", issue = "37572")] +unsafe impl TrustedLen for IntoIter {} + +#[doc(hidden)] +#[unstable(issue = "none", feature = "std_internals")] +// T: Copy as approximation for !Drop since get_unchecked does not advance self.ptr +// and thus we can't implement drop-handling +unsafe impl TrustedRandomAccess for IntoIter + where + T: Copy, +{ + fn may_have_side_effect() -> bool { + false + } +} + +#[stable(feature = "vec_into_iter_clone", since = "1.8.0")] +impl Clone for IntoIter { + #[cfg(not(test))] + fn clone(&self) -> Self { + self.as_slice().to_vec_in(self.alloc.clone()).into_iter() + } + #[cfg(test)] + fn clone(&self) -> Self { + crate::slice::to_vec(self.as_slice(), self.alloc.clone()).into_iter() + } +} + +#[stable(feature = "rust1", since = "1.0.0")] +unsafe impl<#[may_dangle] T, A: Allocator> Drop for IntoIter { + fn drop(&mut self) { + struct DropGuard<'a, T, A: Allocator>(&'a mut IntoIter); + + impl Drop for DropGuard<'_, T, A> { + fn drop(&mut self) { + unsafe { + // `IntoIter::alloc` is not used anymore after this + let alloc = ptr::read(&self.0.alloc); + // RawVec handles deallocation + let _ = RawVec::from_raw_parts_in(self.0.buf.as_ptr(), self.0.cap, alloc); + } + } + } + + let guard = DropGuard(self); + // destroy the remaining elements + unsafe { + ptr::drop_in_place(guard.0.as_raw_mut_slice()); + } + // now `guard` will be dropped and do the rest + } +} + +#[unstable(issue = "none", feature = "inplace_iteration")] +unsafe impl InPlaceIterable for IntoIter {} + +#[unstable(issue = "none", feature = "inplace_iteration")] +unsafe impl SourceIter for IntoIter { + type Source = Self; + + #[inline] + unsafe fn as_inner(&mut self) -> &mut Self::Source { + self + } +} diff --git a/library/alloc/src/vec/mod.rs b/library/alloc/src/vec/mod.rs index 8d3f8b0bfd8..b6508bfea08 100644 --- a/library/alloc/src/vec/mod.rs +++ b/library/alloc/src/vec/mod.rs @@ -60,7 +60,7 @@ use core::fmt; use core::hash::{Hash, Hasher}; use core::intrinsics::{arith_offset, assume}; use core::iter::{ - FromIterator, FusedIterator, InPlaceIterable, SourceIter, TrustedLen, TrustedRandomAccess, + FromIterator, InPlaceIterable, SourceIter, TrustedLen, }; use core::marker::PhantomData; use core::mem::{self, ManuallyDrop, MaybeUninit}; @@ -91,6 +91,11 @@ mod drain; mod cow; +#[stable(feature = "rust1", since = "1.0.0")] +pub use self::into_iter::IntoIter; + +mod into_iter; + /// A contiguous growable array type, written `Vec` but pronounced 'vector'. /// /// # Examples @@ -3015,269 +3020,6 @@ impl TryFrom> for [T; N] { } } -//////////////////////////////////////////////////////////////////////////////// -// Iterators -//////////////////////////////////////////////////////////////////////////////// - -/// An iterator that moves out of a vector. -/// -/// This `struct` is created by the `into_iter` method on [`Vec`] (provided -/// by the [`IntoIterator`] trait). -/// -/// # Example -/// -/// ``` -/// let v = vec![0, 1, 2]; -/// let iter: std::vec::IntoIter<_> = v.into_iter(); -/// ``` -#[stable(feature = "rust1", since = "1.0.0")] -pub struct IntoIter< - T, - #[unstable(feature = "allocator_api", issue = "32838")] A: Allocator = Global, -> { - buf: NonNull, - phantom: PhantomData, - cap: usize, - alloc: A, - ptr: *const T, - end: *const T, -} - -#[stable(feature = "vec_intoiter_debug", since = "1.13.0")] -impl fmt::Debug for IntoIter { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - f.debug_tuple("IntoIter").field(&self.as_slice()).finish() - } -} - -impl IntoIter { - /// Returns the remaining items of this iterator as a slice. - /// - /// # Examples - /// - /// ``` - /// let vec = vec!['a', 'b', 'c']; - /// let mut into_iter = vec.into_iter(); - /// assert_eq!(into_iter.as_slice(), &['a', 'b', 'c']); - /// let _ = into_iter.next().unwrap(); - /// assert_eq!(into_iter.as_slice(), &['b', 'c']); - /// ``` - #[stable(feature = "vec_into_iter_as_slice", since = "1.15.0")] - pub fn as_slice(&self) -> &[T] { - unsafe { slice::from_raw_parts(self.ptr, self.len()) } - } - - /// Returns the remaining items of this iterator as a mutable slice. - /// - /// # Examples - /// - /// ``` - /// let vec = vec!['a', 'b', 'c']; - /// let mut into_iter = vec.into_iter(); - /// assert_eq!(into_iter.as_slice(), &['a', 'b', 'c']); - /// into_iter.as_mut_slice()[2] = 'z'; - /// assert_eq!(into_iter.next().unwrap(), 'a'); - /// assert_eq!(into_iter.next().unwrap(), 'b'); - /// assert_eq!(into_iter.next().unwrap(), 'z'); - /// ``` - #[stable(feature = "vec_into_iter_as_slice", since = "1.15.0")] - pub fn as_mut_slice(&mut self) -> &mut [T] { - unsafe { &mut *self.as_raw_mut_slice() } - } - - /// Returns a reference to the underlying allocator. - #[unstable(feature = "allocator_api", issue = "32838")] - #[inline] - pub fn allocator(&self) -> &A { - &self.alloc - } - - fn as_raw_mut_slice(&mut self) -> *mut [T] { - ptr::slice_from_raw_parts_mut(self.ptr as *mut T, self.len()) - } - - fn drop_remaining(&mut self) { - unsafe { - ptr::drop_in_place(self.as_mut_slice()); - } - self.ptr = self.end; - } - - /// Relinquishes the backing allocation, equivalent to - /// `ptr::write(&mut self, Vec::new().into_iter())` - fn forget_allocation(&mut self) { - self.cap = 0; - self.buf = unsafe { NonNull::new_unchecked(RawVec::NEW.ptr()) }; - self.ptr = self.buf.as_ptr(); - self.end = self.buf.as_ptr(); - } -} - -#[stable(feature = "vec_intoiter_as_ref", since = "1.46.0")] -impl AsRef<[T]> for IntoIter { - fn as_ref(&self) -> &[T] { - self.as_slice() - } -} - -#[stable(feature = "rust1", since = "1.0.0")] -unsafe impl Send for IntoIter {} -#[stable(feature = "rust1", since = "1.0.0")] -unsafe impl Sync for IntoIter {} - -#[stable(feature = "rust1", since = "1.0.0")] -impl Iterator for IntoIter { - type Item = T; - - #[inline] - fn next(&mut self) -> Option { - if self.ptr as *const _ == self.end { - None - } else if mem::size_of::() == 0 { - // purposefully don't use 'ptr.offset' because for - // vectors with 0-size elements this would return the - // same pointer. - self.ptr = unsafe { arith_offset(self.ptr as *const i8, 1) as *mut T }; - - // Make up a value of this ZST. - Some(unsafe { mem::zeroed() }) - } else { - let old = self.ptr; - self.ptr = unsafe { self.ptr.offset(1) }; - - Some(unsafe { ptr::read(old) }) - } - } - - #[inline] - fn size_hint(&self) -> (usize, Option) { - let exact = if mem::size_of::() == 0 { - (self.end as usize).wrapping_sub(self.ptr as usize) - } else { - unsafe { self.end.offset_from(self.ptr) as usize } - }; - (exact, Some(exact)) - } - - #[inline] - fn count(self) -> usize { - self.len() - } - - unsafe fn __iterator_get_unchecked(&mut self, i: usize) -> Self::Item - where - Self: TrustedRandomAccess, - { - // SAFETY: the caller must guarantee that `i` is in bounds of the - // `Vec`, so `i` cannot overflow an `isize`, and the `self.ptr.add(i)` - // is guaranteed to pointer to an element of the `Vec` and - // thus guaranteed to be valid to dereference. - // - // Also note the implementation of `Self: TrustedRandomAccess` requires - // that `T: Copy` so reading elements from the buffer doesn't invalidate - // them for `Drop`. - unsafe { - if mem::size_of::() == 0 { mem::zeroed() } else { ptr::read(self.ptr.add(i)) } - } - } -} - -#[stable(feature = "rust1", since = "1.0.0")] -impl DoubleEndedIterator for IntoIter { - #[inline] - fn next_back(&mut self) -> Option { - if self.end == self.ptr { - None - } else if mem::size_of::() == 0 { - // See above for why 'ptr.offset' isn't used - self.end = unsafe { arith_offset(self.end as *const i8, -1) as *mut T }; - - // Make up a value of this ZST. - Some(unsafe { mem::zeroed() }) - } else { - self.end = unsafe { self.end.offset(-1) }; - - Some(unsafe { ptr::read(self.end) }) - } - } -} - -#[stable(feature = "rust1", since = "1.0.0")] -impl ExactSizeIterator for IntoIter { - fn is_empty(&self) -> bool { - self.ptr == self.end - } -} - -#[stable(feature = "fused", since = "1.26.0")] -impl FusedIterator for IntoIter {} - -#[unstable(feature = "trusted_len", issue = "37572")] -unsafe impl TrustedLen for IntoIter {} - -#[doc(hidden)] -#[unstable(issue = "none", feature = "std_internals")] -// T: Copy as approximation for !Drop since get_unchecked does not advance self.ptr -// and thus we can't implement drop-handling -unsafe impl TrustedRandomAccess for IntoIter -where - T: Copy, -{ - fn may_have_side_effect() -> bool { - false - } -} - -#[stable(feature = "vec_into_iter_clone", since = "1.8.0")] -impl Clone for IntoIter { - #[cfg(not(test))] - fn clone(&self) -> Self { - self.as_slice().to_vec_in(self.alloc.clone()).into_iter() - } - #[cfg(test)] - fn clone(&self) -> Self { - crate::slice::to_vec(self.as_slice(), self.alloc.clone()).into_iter() - } -} - -#[stable(feature = "rust1", since = "1.0.0")] -unsafe impl<#[may_dangle] T, A: Allocator> Drop for IntoIter { - fn drop(&mut self) { - struct DropGuard<'a, T, A: Allocator>(&'a mut IntoIter); - - impl Drop for DropGuard<'_, T, A> { - fn drop(&mut self) { - unsafe { - // `IntoIter::alloc` is not used anymore after this - let alloc = ptr::read(&self.0.alloc); - // RawVec handles deallocation - let _ = RawVec::from_raw_parts_in(self.0.buf.as_ptr(), self.0.cap, alloc); - } - } - } - - let guard = DropGuard(self); - // destroy the remaining elements - unsafe { - ptr::drop_in_place(guard.0.as_raw_mut_slice()); - } - // now `guard` will be dropped and do the rest - } -} - -#[unstable(issue = "none", feature = "inplace_iteration")] -unsafe impl InPlaceIterable for IntoIter {} - -#[unstable(issue = "none", feature = "inplace_iteration")] -unsafe impl SourceIter for IntoIter { - type Source = Self; - - #[inline] - unsafe fn as_inner(&mut self) -> &mut Self::Source { - self - } -} - // internal helper trait for in-place iteration specialization. #[rustc_specialization_trait] pub(crate) trait AsIntoIter { -- cgit 1.4.1-3-g733a5 From 2a1248976a00429994d5965bb31d6dcc1b7dcd68 Mon Sep 17 00:00:00 2001 From: C Date: Sat, 5 Dec 2020 00:47:54 +0000 Subject: refactor: moving AsIntoIter into into_iter.rs --- library/alloc/src/vec/into_iter.rs | 15 +++++++++++++++ library/alloc/src/vec/mod.rs | 16 +--------------- 2 files changed, 16 insertions(+), 15 deletions(-) (limited to 'library/alloc/src') diff --git a/library/alloc/src/vec/into_iter.rs b/library/alloc/src/vec/into_iter.rs index 623792a6316..c4330df4ad9 100644 --- a/library/alloc/src/vec/into_iter.rs +++ b/library/alloc/src/vec/into_iter.rs @@ -268,3 +268,18 @@ unsafe impl SourceIter for IntoIter { self } } + +// internal helper trait for in-place iteration specialization. +#[rustc_specialization_trait] +pub(crate) trait AsIntoIter { + type Item; + fn as_into_iter(&mut self) -> &mut IntoIter; +} + +impl AsIntoIter for IntoIter { + type Item = T; + + fn as_into_iter(&mut self) -> &mut IntoIter { + self + } +} diff --git a/library/alloc/src/vec/mod.rs b/library/alloc/src/vec/mod.rs index b6508bfea08..1f410e3c028 100644 --- a/library/alloc/src/vec/mod.rs +++ b/library/alloc/src/vec/mod.rs @@ -93,6 +93,7 @@ mod cow; #[stable(feature = "rust1", since = "1.0.0")] pub use self::into_iter::IntoIter; +pub (crate) use self::into_iter::AsIntoIter; mod into_iter; @@ -3019,18 +3020,3 @@ impl TryFrom> for [T; N] { Ok(array) } } - -// internal helper trait for in-place iteration specialization. -#[rustc_specialization_trait] -pub(crate) trait AsIntoIter { - type Item; - fn as_into_iter(&mut self) -> &mut IntoIter; -} - -impl AsIntoIter for IntoIter { - type Item = T; - - fn as_into_iter(&mut self) -> &mut IntoIter { - self - } -} -- cgit 1.4.1-3-g733a5 From 840c4e2873476a7d6101f71e4f63b3024245ccd1 Mon Sep 17 00:00:00 2001 From: C Date: Sat, 5 Dec 2020 00:52:48 +0000 Subject: refactor: moved IsZero into is_zero.rs --- library/alloc/src/vec/is_zero.rs | 71 ++++++++++++++++++++++++++++++++++++++ library/alloc/src/vec/mod.rs | 74 +++------------------------------------- 2 files changed, 75 insertions(+), 70 deletions(-) create mode 100644 library/alloc/src/vec/is_zero.rs (limited to 'library/alloc/src') diff --git a/library/alloc/src/vec/is_zero.rs b/library/alloc/src/vec/is_zero.rs new file mode 100644 index 00000000000..961f6ca171b --- /dev/null +++ b/library/alloc/src/vec/is_zero.rs @@ -0,0 +1,71 @@ +use crate::boxed::Box; + +#[rustc_specialization_trait] +pub(super) unsafe trait IsZero { + /// Whether this value is zero + fn is_zero(&self) -> bool; +} + +macro_rules! impl_is_zero { + ($t:ty, $is_zero:expr) => { + unsafe impl IsZero for $t { + #[inline] + fn is_zero(&self) -> bool { + $is_zero(*self) + } + } + }; +} + +impl_is_zero!(i16, |x| x == 0); +impl_is_zero!(i32, |x| x == 0); +impl_is_zero!(i64, |x| x == 0); +impl_is_zero!(i128, |x| x == 0); +impl_is_zero!(isize, |x| x == 0); + +impl_is_zero!(u16, |x| x == 0); +impl_is_zero!(u32, |x| x == 0); +impl_is_zero!(u64, |x| x == 0); +impl_is_zero!(u128, |x| x == 0); +impl_is_zero!(usize, |x| x == 0); + +impl_is_zero!(bool, |x| x == false); +impl_is_zero!(char, |x| x == '\0'); + +impl_is_zero!(f32, |x: f32| x.to_bits() == 0); +impl_is_zero!(f64, |x: f64| x.to_bits() == 0); + +unsafe impl IsZero for *const T { + #[inline] + fn is_zero(&self) -> bool { + (*self).is_null() + } +} + +unsafe impl IsZero for *mut T { + #[inline] + fn is_zero(&self) -> bool { + (*self).is_null() + } +} + +// `Option<&T>` and `Option>` are guaranteed to represent `None` as null. +// For fat pointers, the bytes that would be the pointer metadata in the `Some` +// variant are padding in the `None` variant, so ignoring them and +// zero-initializing instead is ok. +// `Option<&mut T>` never implements `Clone`, so there's no need for an impl of +// `SpecFromElem`. + +unsafe impl IsZero for Option<&T> { + #[inline] + fn is_zero(&self) -> bool { + self.is_none() + } +} + +unsafe impl IsZero for Option> { + #[inline] + fn is_zero(&self) -> bool { + self.is_none() + } +} \ No newline at end of file diff --git a/library/alloc/src/vec/mod.rs b/library/alloc/src/vec/mod.rs index 1f410e3c028..69fcfaa6a7e 100644 --- a/library/alloc/src/vec/mod.rs +++ b/library/alloc/src/vec/mod.rs @@ -97,6 +97,10 @@ pub (crate) use self::into_iter::AsIntoIter; mod into_iter; +use self::is_zero::IsZero; + +mod is_zero; + /// A contiguous growable array type, written `Vec` but pronounced 'vector'. /// /// # Examples @@ -2042,76 +2046,6 @@ impl SpecFromElem for T { } } -#[rustc_specialization_trait] -unsafe trait IsZero { - /// Whether this value is zero - fn is_zero(&self) -> bool; -} - -macro_rules! impl_is_zero { - ($t:ty, $is_zero:expr) => { - unsafe impl IsZero for $t { - #[inline] - fn is_zero(&self) -> bool { - $is_zero(*self) - } - } - }; -} - -impl_is_zero!(i16, |x| x == 0); -impl_is_zero!(i32, |x| x == 0); -impl_is_zero!(i64, |x| x == 0); -impl_is_zero!(i128, |x| x == 0); -impl_is_zero!(isize, |x| x == 0); - -impl_is_zero!(u16, |x| x == 0); -impl_is_zero!(u32, |x| x == 0); -impl_is_zero!(u64, |x| x == 0); -impl_is_zero!(u128, |x| x == 0); -impl_is_zero!(usize, |x| x == 0); - -impl_is_zero!(bool, |x| x == false); -impl_is_zero!(char, |x| x == '\0'); - -impl_is_zero!(f32, |x: f32| x.to_bits() == 0); -impl_is_zero!(f64, |x: f64| x.to_bits() == 0); - -unsafe impl IsZero for *const T { - #[inline] - fn is_zero(&self) -> bool { - (*self).is_null() - } -} - -unsafe impl IsZero for *mut T { - #[inline] - fn is_zero(&self) -> bool { - (*self).is_null() - } -} - -// `Option<&T>` and `Option>` are guaranteed to represent `None` as null. -// For fat pointers, the bytes that would be the pointer metadata in the `Some` -// variant are padding in the `None` variant, so ignoring them and -// zero-initializing instead is ok. -// `Option<&mut T>` never implements `Clone`, so there's no need for an impl of -// `SpecFromElem`. - -unsafe impl IsZero for Option<&T> { - #[inline] - fn is_zero(&self) -> bool { - self.is_none() - } -} - -unsafe impl IsZero for Option> { - #[inline] - fn is_zero(&self) -> bool { - self.is_none() - } -} - //////////////////////////////////////////////////////////////////////////////// // Common trait implementations for Vec //////////////////////////////////////////////////////////////////////////////// -- cgit 1.4.1-3-g733a5 From 5ac6709b95bb0cce4cffa9bd87d241928bc7f3f6 Mon Sep 17 00:00:00 2001 From: C Date: Sat, 5 Dec 2020 01:04:06 +0000 Subject: refactor: moving SourceIterMarker into source_iter_marker.rs --- library/alloc/src/vec/mod.rs | 107 +-------------------------- library/alloc/src/vec/source_iter_marker.rs | 110 ++++++++++++++++++++++++++++ 2 files changed, 113 insertions(+), 104 deletions(-) create mode 100644 library/alloc/src/vec/source_iter_marker.rs (limited to 'library/alloc/src') diff --git a/library/alloc/src/vec/mod.rs b/library/alloc/src/vec/mod.rs index 69fcfaa6a7e..bd71d7004b9 100644 --- a/library/alloc/src/vec/mod.rs +++ b/library/alloc/src/vec/mod.rs @@ -60,7 +60,7 @@ use core::fmt; use core::hash::{Hash, Hasher}; use core::intrinsics::{arith_offset, assume}; use core::iter::{ - FromIterator, InPlaceIterable, SourceIter, TrustedLen, + FromIterator, TrustedLen, }; use core::marker::PhantomData; use core::mem::{self, ManuallyDrop, MaybeUninit}; @@ -101,6 +101,8 @@ use self::is_zero::IsZero; mod is_zero; +mod source_iter_marker; + /// A contiguous growable array type, written `Vec` but pronounced 'vector'. /// /// # Examples @@ -2356,109 +2358,6 @@ impl SpecFromIter> for Vec { } } -fn write_in_place_with_drop( - src_end: *const T, -) -> impl FnMut(InPlaceDrop, T) -> Result, !> { - move |mut sink, item| { - unsafe { - // the InPlaceIterable contract cannot be verified precisely here since - // try_fold has an exclusive reference to the source pointer - // all we can do is check if it's still in range - debug_assert!(sink.dst as *const _ <= src_end, "InPlaceIterable contract violation"); - ptr::write(sink.dst, item); - sink.dst = sink.dst.add(1); - } - Ok(sink) - } -} - -/// Specialization marker for collecting an iterator pipeline into a Vec while reusing the -/// source allocation, i.e. executing the pipeline in place. -/// -/// The SourceIter parent trait is necessary for the specializing function to access the allocation -/// which is to be reused. But it is not sufficient for the specialization to be valid. See -/// additional bounds on the impl. -#[rustc_unsafe_specialization_marker] -trait SourceIterMarker: SourceIter {} - -// The std-internal SourceIter/InPlaceIterable traits are only implemented by chains of -// Adapter>> (all owned by core/std). Additional bounds -// on the adapter implementations (beyond `impl Trait for Adapter`) only depend on other -// traits already marked as specialization traits (Copy, TrustedRandomAccess, FusedIterator). -// I.e. the marker does not depend on lifetimes of user-supplied types. Modulo the Copy hole, which -// several other specializations already depend on. -impl SourceIterMarker for T where T: SourceIter + InPlaceIterable {} - -impl SpecFromIter for Vec -where - I: Iterator + SourceIterMarker, -{ - default fn from_iter(mut iterator: I) -> Self { - // Additional requirements which cannot expressed via trait bounds. We rely on const eval - // instead: - // a) no ZSTs as there would be no allocation to reuse and pointer arithmetic would panic - // b) size match as required by Alloc contract - // c) alignments match as required by Alloc contract - if mem::size_of::() == 0 - || mem::size_of::() - != mem::size_of::<<::Source as AsIntoIter>::Item>() - || mem::align_of::() - != mem::align_of::<<::Source as AsIntoIter>::Item>() - { - // fallback to more generic implementations - return SpecFromIterNested::from_iter(iterator); - } - - let (src_buf, src_ptr, dst_buf, dst_end, cap) = unsafe { - let inner = iterator.as_inner().as_into_iter(); - ( - inner.buf.as_ptr(), - inner.ptr, - inner.buf.as_ptr() as *mut T, - inner.end as *const T, - inner.cap, - ) - }; - - // use try-fold since - // - it vectorizes better for some iterator adapters - // - unlike most internal iteration methods, it only takes a &mut self - // - it lets us thread the write pointer through its innards and get it back in the end - let sink = InPlaceDrop { inner: dst_buf, dst: dst_buf }; - let sink = iterator - .try_fold::<_, _, Result<_, !>>(sink, write_in_place_with_drop(dst_end)) - .unwrap(); - // iteration succeeded, don't drop head - let dst = ManuallyDrop::new(sink).dst; - - let src = unsafe { iterator.as_inner().as_into_iter() }; - // check if SourceIter contract was upheld - // caveat: if they weren't we may not even make it to this point - debug_assert_eq!(src_buf, src.buf.as_ptr()); - // check InPlaceIterable contract. This is only possible if the iterator advanced the - // source pointer at all. If it uses unchecked access via TrustedRandomAccess - // then the source pointer will stay in its initial position and we can't use it as reference - if src.ptr != src_ptr { - debug_assert!( - dst as *const _ <= src.ptr, - "InPlaceIterable contract violation, write pointer advanced beyond read pointer" - ); - } - - // drop any remaining values at the tail of the source - src.drop_remaining(); - // but prevent drop of the allocation itself once IntoIter goes out of scope - src.forget_allocation(); - - let vec = unsafe { - let len = dst.offset_from(dst_buf) as usize; - Vec::from_raw_parts(dst_buf, len, cap) - }; - - vec - } -} - impl<'a, T: 'a, I> SpecFromIter<&'a T, I> for Vec where I: Iterator, diff --git a/library/alloc/src/vec/source_iter_marker.rs b/library/alloc/src/vec/source_iter_marker.rs new file mode 100644 index 00000000000..eb3ae01a47e --- /dev/null +++ b/library/alloc/src/vec/source_iter_marker.rs @@ -0,0 +1,110 @@ +use core::iter::{ + InPlaceIterable, SourceIter, +}; +use core::mem::{self, ManuallyDrop}; +use core::ptr::{self}; + +use super::{Vec, InPlaceDrop, AsIntoIter, SpecFromIter, SpecFromIterNested}; + +/// Specialization marker for collecting an iterator pipeline into a Vec while reusing the +/// source allocation, i.e. executing the pipeline in place. +/// +/// The SourceIter parent trait is necessary for the specializing function to access the allocation +/// which is to be reused. But it is not sufficient for the specialization to be valid. See +/// additional bounds on the impl. +#[rustc_unsafe_specialization_marker] +pub (super) trait SourceIterMarker: SourceIter {} + +// The std-internal SourceIter/InPlaceIterable traits are only implemented by chains of +// Adapter>> (all owned by core/std). Additional bounds +// on the adapter implementations (beyond `impl Trait for Adapter`) only depend on other +// traits already marked as specialization traits (Copy, TrustedRandomAccess, FusedIterator). +// I.e. the marker does not depend on lifetimes of user-supplied types. Modulo the Copy hole, which +// several other specializations already depend on. +impl SourceIterMarker for T where T: SourceIter + InPlaceIterable {} + +impl SpecFromIter for Vec + where + I: Iterator + SourceIterMarker, +{ + default fn from_iter(mut iterator: I) -> Self { + // Additional requirements which cannot expressed via trait bounds. We rely on const eval + // instead: + // a) no ZSTs as there would be no allocation to reuse and pointer arithmetic would panic + // b) size match as required by Alloc contract + // c) alignments match as required by Alloc contract + if mem::size_of::() == 0 + || mem::size_of::() + != mem::size_of::<<::Source as AsIntoIter>::Item>() + || mem::align_of::() + != mem::align_of::<<::Source as AsIntoIter>::Item>() + { + // fallback to more generic implementations + return SpecFromIterNested::from_iter(iterator); + } + + let (src_buf, src_ptr, dst_buf, dst_end, cap) = unsafe { + let inner = iterator.as_inner().as_into_iter(); + ( + inner.buf.as_ptr(), + inner.ptr, + inner.buf.as_ptr() as *mut T, + inner.end as *const T, + inner.cap, + ) + }; + + // use try-fold since + // - it vectorizes better for some iterator adapters + // - unlike most internal iteration methods, it only takes a &mut self + // - it lets us thread the write pointer through its innards and get it back in the end + let sink = InPlaceDrop { inner: dst_buf, dst: dst_buf }; + let sink = iterator + .try_fold::<_, _, Result<_, !>>(sink, write_in_place_with_drop(dst_end)) + .unwrap(); + // iteration succeeded, don't drop head + let dst = ManuallyDrop::new(sink).dst; + + let src = unsafe { iterator.as_inner().as_into_iter() }; + // check if SourceIter contract was upheld + // caveat: if they weren't we may not even make it to this point + debug_assert_eq!(src_buf, src.buf.as_ptr()); + // check InPlaceIterable contract. This is only possible if the iterator advanced the + // source pointer at all. If it uses unchecked access via TrustedRandomAccess + // then the source pointer will stay in its initial position and we can't use it as reference + if src.ptr != src_ptr { + debug_assert!( + dst as *const _ <= src.ptr, + "InPlaceIterable contract violation, write pointer advanced beyond read pointer" + ); + } + + // drop any remaining values at the tail of the source + src.drop_remaining(); + // but prevent drop of the allocation itself once IntoIter goes out of scope + src.forget_allocation(); + + let vec = unsafe { + let len = dst.offset_from(dst_buf) as usize; + Vec::from_raw_parts(dst_buf, len, cap) + }; + + vec + } +} + +fn write_in_place_with_drop( + src_end: *const T, +) -> impl FnMut(InPlaceDrop, T) -> Result, !> { + move |mut sink, item| { + unsafe { + // the InPlaceIterable contract cannot be verified precisely here since + // try_fold has an exclusive reference to the source pointer + // all we can do is check if it's still in range + debug_assert!(sink.dst as *const _ <= src_end, "InPlaceIterable contract violation"); + ptr::write(sink.dst, item); + sink.dst = sink.dst.add(1); + } + Ok(sink) + } +} -- cgit 1.4.1-3-g733a5 From dc46013248ecb8b0d3d29581c1734dd2ecd42b0d Mon Sep 17 00:00:00 2001 From: C Date: Sat, 5 Dec 2020 01:07:34 +0000 Subject: refactor: moved PartialEq into partial_eq --- library/alloc/src/vec/mod.rs | 41 ++--------------------------------- library/alloc/src/vec/partial_eq.rs | 43 +++++++++++++++++++++++++++++++++++++ 2 files changed, 45 insertions(+), 39 deletions(-) create mode 100644 library/alloc/src/vec/partial_eq.rs (limited to 'library/alloc/src') diff --git a/library/alloc/src/vec/mod.rs b/library/alloc/src/vec/mod.rs index bd71d7004b9..a862a979d3b 100644 --- a/library/alloc/src/vec/mod.rs +++ b/library/alloc/src/vec/mod.rs @@ -103,6 +103,8 @@ mod is_zero; mod source_iter_marker; +mod partial_eq; + /// A contiguous growable array type, written `Vec` but pronounced 'vector'. /// /// # Examples @@ -2615,45 +2617,6 @@ impl<'a, T: Copy + 'a, A: Allocator + 'a> Extend<&'a T> for Vec { } } -macro_rules! __impl_slice_eq1 { - ([$($vars:tt)*] $lhs:ty, $rhs:ty $(where $ty:ty: $bound:ident)?, #[$stability:meta]) => { - #[$stability] - impl PartialEq<$rhs> for $lhs - where - T: PartialEq, - $($ty: $bound)? - { - #[inline] - fn eq(&self, other: &$rhs) -> bool { self[..] == other[..] } - #[inline] - fn ne(&self, other: &$rhs) -> bool { self[..] != other[..] } - } - } -} - -__impl_slice_eq1! { [A: Allocator] Vec, Vec, #[stable(feature = "rust1", since = "1.0.0")] } -__impl_slice_eq1! { [A: Allocator] Vec, &[U], #[stable(feature = "rust1", since = "1.0.0")] } -__impl_slice_eq1! { [A: Allocator] Vec, &mut [U], #[stable(feature = "rust1", since = "1.0.0")] } -__impl_slice_eq1! { [A: Allocator] &[T], Vec, #[stable(feature = "partialeq_vec_for_ref_slice", since = "1.46.0")] } -__impl_slice_eq1! { [A: Allocator] &mut [T], Vec, #[stable(feature = "partialeq_vec_for_ref_slice", since = "1.46.0")] } -__impl_slice_eq1! { [A: Allocator] Vec, [U], #[stable(feature = "partialeq_vec_for_slice", since = "1.48.0")] } -__impl_slice_eq1! { [A: Allocator] [T], Vec, #[stable(feature = "partialeq_vec_for_slice", since = "1.48.0")] } -__impl_slice_eq1! { [A: Allocator] Cow<'_, [T]>, Vec where T: Clone, #[stable(feature = "rust1", since = "1.0.0")] } -__impl_slice_eq1! { [] Cow<'_, [T]>, &[U] where T: Clone, #[stable(feature = "rust1", since = "1.0.0")] } -__impl_slice_eq1! { [] Cow<'_, [T]>, &mut [U] where T: Clone, #[stable(feature = "rust1", since = "1.0.0")] } -__impl_slice_eq1! { [A: Allocator, const N: usize] Vec, [U; N], #[stable(feature = "rust1", since = "1.0.0")] } -__impl_slice_eq1! { [A: Allocator, const N: usize] Vec, &[U; N], #[stable(feature = "rust1", since = "1.0.0")] } - -// NOTE: some less important impls are omitted to reduce code bloat -// FIXME(Centril): Reconsider this? -//__impl_slice_eq1! { [const N: usize] Vec, &mut [B; N], } -//__impl_slice_eq1! { [const N: usize] [A; N], Vec, } -//__impl_slice_eq1! { [const N: usize] &[A; N], Vec, } -//__impl_slice_eq1! { [const N: usize] &mut [A; N], Vec, } -//__impl_slice_eq1! { [const N: usize] Cow<'a, [A]>, [B; N], } -//__impl_slice_eq1! { [const N: usize] Cow<'a, [A]>, &[B; N], } -//__impl_slice_eq1! { [const N: usize] Cow<'a, [A]>, &mut [B; N], } - /// Implements comparison of vectors, [lexicographically](core::cmp::Ord#lexicographical-comparison). #[stable(feature = "rust1", since = "1.0.0")] impl PartialOrd for Vec { diff --git a/library/alloc/src/vec/partial_eq.rs b/library/alloc/src/vec/partial_eq.rs new file mode 100644 index 00000000000..617f0404439 --- /dev/null +++ b/library/alloc/src/vec/partial_eq.rs @@ -0,0 +1,43 @@ +use crate::alloc::{Allocator}; +use crate::borrow::Cow; + +use super::{Vec}; + +macro_rules! __impl_slice_eq1 { + ([$($vars:tt)*] $lhs:ty, $rhs:ty $(where $ty:ty: $bound:ident)?, #[$stability:meta]) => { + #[$stability] + impl PartialEq<$rhs> for $lhs + where + T: PartialEq, + $($ty: $bound)? + { + #[inline] + fn eq(&self, other: &$rhs) -> bool { self[..] == other[..] } + #[inline] + fn ne(&self, other: &$rhs) -> bool { self[..] != other[..] } + } + } +} + +__impl_slice_eq1! { [A: Allocator] Vec, Vec, #[stable(feature = "rust1", since = "1.0.0")] } +__impl_slice_eq1! { [A: Allocator] Vec, &[U], #[stable(feature = "rust1", since = "1.0.0")] } +__impl_slice_eq1! { [A: Allocator] Vec, &mut [U], #[stable(feature = "rust1", since = "1.0.0")] } +__impl_slice_eq1! { [A: Allocator] &[T], Vec, #[stable(feature = "partialeq_vec_for_ref_slice", since = "1.46.0")] } +__impl_slice_eq1! { [A: Allocator] &mut [T], Vec, #[stable(feature = "partialeq_vec_for_ref_slice", since = "1.46.0")] } +__impl_slice_eq1! { [A: Allocator] Vec, [U], #[stable(feature = "partialeq_vec_for_slice", since = "1.48.0")] } +__impl_slice_eq1! { [A: Allocator] [T], Vec, #[stable(feature = "partialeq_vec_for_slice", since = "1.48.0")] } +__impl_slice_eq1! { [A: Allocator] Cow<'_, [T]>, Vec where T: Clone, #[stable(feature = "rust1", since = "1.0.0")] } +__impl_slice_eq1! { [] Cow<'_, [T]>, &[U] where T: Clone, #[stable(feature = "rust1", since = "1.0.0")] } +__impl_slice_eq1! { [] Cow<'_, [T]>, &mut [U] where T: Clone, #[stable(feature = "rust1", since = "1.0.0")] } +__impl_slice_eq1! { [A: Allocator, const N: usize] Vec, [U; N], #[stable(feature = "rust1", since = "1.0.0")] } +__impl_slice_eq1! { [A: Allocator, const N: usize] Vec, &[U; N], #[stable(feature = "rust1", since = "1.0.0")] } + +// NOTE: some less important impls are omitted to reduce code bloat +// FIXME(Centril): Reconsider this? +//__impl_slice_eq1! { [const N: usize] Vec, &mut [B; N], } +//__impl_slice_eq1! { [const N: usize] [A; N], Vec, } +//__impl_slice_eq1! { [const N: usize] &[A; N], Vec, } +//__impl_slice_eq1! { [const N: usize] &mut [A; N], Vec, } +//__impl_slice_eq1! { [const N: usize] Cow<'a, [A]>, [B; N], } +//__impl_slice_eq1! { [const N: usize] Cow<'a, [A]>, &[B; N], } +//__impl_slice_eq1! { [const N: usize] Cow<'a, [A]>, &mut [B; N], } -- cgit 1.4.1-3-g733a5 From a2f4bc0d181f6aaee7b43fc37e7f16bd400d6b2c Mon Sep 17 00:00:00 2001 From: C Date: Sat, 5 Dec 2020 01:14:31 +0000 Subject: refactor: moved SpecFromElem to spec_from_elem.rs --- library/alloc/src/vec/mod.rs | 59 +++----------------------------- library/alloc/src/vec/spec_from_elem.rs | 60 +++++++++++++++++++++++++++++++++ 2 files changed, 64 insertions(+), 55 deletions(-) create mode 100644 library/alloc/src/vec/spec_from_elem.rs (limited to 'library/alloc/src') diff --git a/library/alloc/src/vec/mod.rs b/library/alloc/src/vec/mod.rs index a862a979d3b..ae1736d8d3c 100644 --- a/library/alloc/src/vec/mod.rs +++ b/library/alloc/src/vec/mod.rs @@ -105,6 +105,10 @@ mod source_iter_marker; mod partial_eq; +use self::spec_from_elem::SpecFromElem; + +mod spec_from_elem; + /// A contiguous growable array type, written `Vec` but pronounced 'vector'. /// /// # Examples @@ -1995,61 +1999,6 @@ pub fn from_elem_in(elem: T, n: usize, alloc: A) -> Vec< ::from_elem(elem, n, alloc) } -// Specialization trait used for Vec::from_elem -trait SpecFromElem: Sized { - fn from_elem(elem: Self, n: usize, alloc: A) -> Vec; -} - -impl SpecFromElem for T { - default fn from_elem(elem: Self, n: usize, alloc: A) -> Vec { - let mut v = Vec::with_capacity_in(n, alloc); - v.extend_with(n, ExtendElement(elem)); - v - } -} - -impl SpecFromElem for i8 { - #[inline] - fn from_elem(elem: i8, n: usize, alloc: A) -> Vec { - if elem == 0 { - return Vec { buf: RawVec::with_capacity_zeroed_in(n, alloc), len: n }; - } - unsafe { - let mut v = Vec::with_capacity_in(n, alloc); - ptr::write_bytes(v.as_mut_ptr(), elem as u8, n); - v.set_len(n); - v - } - } -} - -impl SpecFromElem for u8 { - #[inline] - fn from_elem(elem: u8, n: usize, alloc: A) -> Vec { - if elem == 0 { - return Vec { buf: RawVec::with_capacity_zeroed_in(n, alloc), len: n }; - } - unsafe { - let mut v = Vec::with_capacity_in(n, alloc); - ptr::write_bytes(v.as_mut_ptr(), elem, n); - v.set_len(n); - v - } - } -} - -impl SpecFromElem for T { - #[inline] - fn from_elem(elem: T, n: usize, alloc: A) -> Vec { - if elem.is_zero() { - return Vec { buf: RawVec::with_capacity_zeroed_in(n, alloc), len: n }; - } - let mut v = Vec::with_capacity_in(n, alloc); - v.extend_with(n, ExtendElement(elem)); - v - } -} - //////////////////////////////////////////////////////////////////////////////// // Common trait implementations for Vec //////////////////////////////////////////////////////////////////////////////// diff --git a/library/alloc/src/vec/spec_from_elem.rs b/library/alloc/src/vec/spec_from_elem.rs new file mode 100644 index 00000000000..ef89054ea13 --- /dev/null +++ b/library/alloc/src/vec/spec_from_elem.rs @@ -0,0 +1,60 @@ +use crate::alloc::{Allocator}; +use crate::raw_vec::RawVec; +use core::ptr::{self}; + +use super::{Vec, IsZero, ExtendElement}; + +// Specialization trait used for Vec::from_elem +pub(super) trait SpecFromElem: Sized { + fn from_elem(elem: Self, n: usize, alloc: A) -> Vec; +} + +impl SpecFromElem for T { + default fn from_elem(elem: Self, n: usize, alloc: A) -> Vec { + let mut v = Vec::with_capacity_in(n, alloc); + v.extend_with(n, ExtendElement(elem)); + v + } +} + +impl SpecFromElem for i8 { + #[inline] + fn from_elem(elem: i8, n: usize, alloc: A) -> Vec { + if elem == 0 { + return Vec { buf: RawVec::with_capacity_zeroed_in(n, alloc), len: n }; + } + unsafe { + let mut v = Vec::with_capacity_in(n, alloc); + ptr::write_bytes(v.as_mut_ptr(), elem as u8, n); + v.set_len(n); + v + } + } +} + +impl SpecFromElem for u8 { + #[inline] + fn from_elem(elem: u8, n: usize, alloc: A) -> Vec { + if elem == 0 { + return Vec { buf: RawVec::with_capacity_zeroed_in(n, alloc), len: n }; + } + unsafe { + let mut v = Vec::with_capacity_in(n, alloc); + ptr::write_bytes(v.as_mut_ptr(), elem, n); + v.set_len(n); + v + } + } +} + +impl SpecFromElem for T { + #[inline] + fn from_elem(elem: T, n: usize, alloc: A) -> Vec { + if elem.is_zero() { + return Vec { buf: RawVec::with_capacity_zeroed_in(n, alloc), len: n }; + } + let mut v = Vec::with_capacity_in(n, alloc); + v.extend_with(n, ExtendElement(elem)); + v + } +} \ No newline at end of file -- cgit 1.4.1-3-g733a5 From a3f3fc5aedc9636ea580d8241746e06db6031270 Mon Sep 17 00:00:00 2001 From: C Date: Sat, 5 Dec 2020 01:21:51 +0000 Subject: refactor: moved SetLenOnDrop to set_len_on_drop --- library/alloc/src/vec/mod.rs | 33 ++++---------------------------- library/alloc/src/vec/set_len_on_drop.rs | 28 +++++++++++++++++++++++++++ 2 files changed, 32 insertions(+), 29 deletions(-) create mode 100644 library/alloc/src/vec/set_len_on_drop.rs (limited to 'library/alloc/src') diff --git a/library/alloc/src/vec/mod.rs b/library/alloc/src/vec/mod.rs index ae1736d8d3c..62ca5b950ce 100644 --- a/library/alloc/src/vec/mod.rs +++ b/library/alloc/src/vec/mod.rs @@ -109,6 +109,10 @@ use self::spec_from_elem::SpecFromElem; mod spec_from_elem; +use self::set_len_on_drop::SetLenOnDrop; + +mod set_len_on_drop; + /// A contiguous growable array type, written `Vec` but pronounced 'vector'. /// /// # Examples @@ -1911,35 +1915,6 @@ impl Vec { } } -// Set the length of the vec when the `SetLenOnDrop` value goes out of scope. -// -// The idea is: The length field in SetLenOnDrop is a local variable -// that the optimizer will see does not alias with any stores through the Vec's data -// pointer. This is a workaround for alias analysis issue #32155 -struct SetLenOnDrop<'a> { - len: &'a mut usize, - local_len: usize, -} - -impl<'a> SetLenOnDrop<'a> { - #[inline] - fn new(len: &'a mut usize) -> Self { - SetLenOnDrop { local_len: *len, len } - } - - #[inline] - fn increment_len(&mut self, increment: usize) { - self.local_len += increment; - } -} - -impl Drop for SetLenOnDrop<'_> { - #[inline] - fn drop(&mut self) { - *self.len = self.local_len; - } -} - impl Vec { /// Removes consecutive repeated elements in the vector according to the /// [`PartialEq`] trait implementation. diff --git a/library/alloc/src/vec/set_len_on_drop.rs b/library/alloc/src/vec/set_len_on_drop.rs new file mode 100644 index 00000000000..8b66bc81212 --- /dev/null +++ b/library/alloc/src/vec/set_len_on_drop.rs @@ -0,0 +1,28 @@ +// Set the length of the vec when the `SetLenOnDrop` value goes out of scope. +// +// The idea is: The length field in SetLenOnDrop is a local variable +// that the optimizer will see does not alias with any stores through the Vec's data +// pointer. This is a workaround for alias analysis issue #32155 +pub(super) struct SetLenOnDrop<'a> { + len: &'a mut usize, + local_len: usize, +} + +impl<'a> SetLenOnDrop<'a> { + #[inline] + pub(super) fn new(len: &'a mut usize) -> Self { + SetLenOnDrop { local_len: *len, len } + } + + #[inline] + pub(super) fn increment_len(&mut self, increment: usize) { + self.local_len += increment; + } +} + +impl Drop for SetLenOnDrop<'_> { + #[inline] + fn drop(&mut self) { + *self.len = self.local_len; + } +} -- cgit 1.4.1-3-g733a5 From 9e08ce7190dd63afc3e5a12f89134c760566513a Mon Sep 17 00:00:00 2001 From: C Date: Sat, 5 Dec 2020 01:26:52 +0000 Subject: refactor: moved InPlaceDrop into in_place_drop.rs --- library/alloc/src/vec/in_place_drop.rs | 24 ++++++++++++++++++++++++ library/alloc/src/vec/mod.rs | 26 ++++---------------------- 2 files changed, 28 insertions(+), 22 deletions(-) create mode 100644 library/alloc/src/vec/in_place_drop.rs (limited to 'library/alloc/src') diff --git a/library/alloc/src/vec/in_place_drop.rs b/library/alloc/src/vec/in_place_drop.rs new file mode 100644 index 00000000000..3a0ecc529c0 --- /dev/null +++ b/library/alloc/src/vec/in_place_drop.rs @@ -0,0 +1,24 @@ +use core::ptr::{self}; +use core::slice::{self}; + +// A helper struct for in-place iteration that drops the destination slice of iteration, +// i.e. the head. The source slice (the tail) is dropped by IntoIter. +pub (super) struct InPlaceDrop { + pub (super) inner: *mut T, + pub (super) dst: *mut T, +} + +impl InPlaceDrop { + fn len(&self) -> usize { + unsafe { self.dst.offset_from(self.inner) as usize } + } +} + +impl Drop for InPlaceDrop { + #[inline] + fn drop(&mut self) { + unsafe { + ptr::drop_in_place(slice::from_raw_parts_mut(self.inner, self.len())); + } + } +} diff --git a/library/alloc/src/vec/mod.rs b/library/alloc/src/vec/mod.rs index 62ca5b950ce..08a920a9c60 100644 --- a/library/alloc/src/vec/mod.rs +++ b/library/alloc/src/vec/mod.rs @@ -113,6 +113,10 @@ use self::set_len_on_drop::SetLenOnDrop; mod set_len_on_drop; +use self::in_place_drop::InPlaceDrop; + +mod in_place_drop; + /// A contiguous growable array type, written `Vec` but pronounced 'vector'. /// /// # Examples @@ -2233,28 +2237,6 @@ where } } -// A helper struct for in-place iteration that drops the destination slice of iteration, -// i.e. the head. The source slice (the tail) is dropped by IntoIter. -struct InPlaceDrop { - inner: *mut T, - dst: *mut T, -} - -impl InPlaceDrop { - fn len(&self) -> usize { - unsafe { self.dst.offset_from(self.inner) as usize } - } -} - -impl Drop for InPlaceDrop { - #[inline] - fn drop(&mut self) { - unsafe { - ptr::drop_in_place(slice::from_raw_parts_mut(self.inner, self.len())); - } - } -} - impl SpecFromIter> for Vec { fn from_iter(iterator: IntoIter) -> Self { // A common case is passing a vector into a function which immediately -- cgit 1.4.1-3-g733a5 From 56d82b3dcc73e227dd2fa4dd4a8ef8d96ce75805 Mon Sep 17 00:00:00 2001 From: C Date: Sat, 5 Dec 2020 01:30:20 +0000 Subject: refactor: moved SpecFromIterNested to spec_from_iter_nested.rs --- library/alloc/src/vec/mod.rs | 56 ++------------------------ library/alloc/src/vec/spec_from_iter_nested.rs | 56 ++++++++++++++++++++++++++ 2 files changed, 60 insertions(+), 52 deletions(-) create mode 100644 library/alloc/src/vec/spec_from_iter_nested.rs (limited to 'library/alloc/src') diff --git a/library/alloc/src/vec/mod.rs b/library/alloc/src/vec/mod.rs index 08a920a9c60..438246ab4cb 100644 --- a/library/alloc/src/vec/mod.rs +++ b/library/alloc/src/vec/mod.rs @@ -117,6 +117,10 @@ use self::in_place_drop::InPlaceDrop; mod in_place_drop; +use self::spec_from_iter_nested::SpecFromIterNested; + +mod spec_from_iter_nested; + /// A contiguous growable array type, written `Vec` but pronounced 'vector'. /// /// # Examples @@ -2176,58 +2180,6 @@ trait SpecFromIter { fn from_iter(iter: I) -> Self; } -/// Another specialization trait for Vec::from_iter -/// necessary to manually prioritize overlapping specializations -/// see [`SpecFromIter`] for details. -trait SpecFromIterNested { - fn from_iter(iter: I) -> Self; -} - -impl SpecFromIterNested for Vec -where - I: Iterator, -{ - default fn from_iter(mut iterator: I) -> Self { - // Unroll the first iteration, as the vector is going to be - // expanded on this iteration in every case when the iterable is not - // empty, but the loop in extend_desugared() is not going to see the - // vector being full in the few subsequent loop iterations. - // So we get better branch prediction. - let mut vector = match iterator.next() { - None => return Vec::new(), - Some(element) => { - let (lower, _) = iterator.size_hint(); - let mut vector = Vec::with_capacity(lower.saturating_add(1)); - unsafe { - ptr::write(vector.as_mut_ptr(), element); - vector.set_len(1); - } - vector - } - }; - // must delegate to spec_extend() since extend() itself delegates - // to spec_from for empty Vecs - as SpecExtend>::spec_extend(&mut vector, iterator); - vector - } -} - -impl SpecFromIterNested for Vec -where - I: TrustedLen, -{ - fn from_iter(iterator: I) -> Self { - let mut vector = match iterator.size_hint() { - (_, Some(upper)) => Vec::with_capacity(upper), - _ => Vec::new(), - }; - // must delegate to spec_extend() since extend() itself delegates - // to spec_from for empty Vecs - vector.spec_extend(iterator); - vector - } -} - impl SpecFromIter for Vec where I: Iterator, diff --git a/library/alloc/src/vec/spec_from_iter_nested.rs b/library/alloc/src/vec/spec_from_iter_nested.rs new file mode 100644 index 00000000000..0da42844c96 --- /dev/null +++ b/library/alloc/src/vec/spec_from_iter_nested.rs @@ -0,0 +1,56 @@ +use core::ptr::{self}; +use core::iter::{TrustedLen}; + +use super::{Vec, SpecExtend}; + +/// Another specialization trait for Vec::from_iter +/// necessary to manually prioritize overlapping specializations +/// see [`SpecFromIter`] for details. +pub(super) trait SpecFromIterNested { + fn from_iter(iter: I) -> Self; +} + +impl SpecFromIterNested for Vec + where + I: Iterator, +{ + default fn from_iter(mut iterator: I) -> Self { + // Unroll the first iteration, as the vector is going to be + // expanded on this iteration in every case when the iterable is not + // empty, but the loop in extend_desugared() is not going to see the + // vector being full in the few subsequent loop iterations. + // So we get better branch prediction. + let mut vector = match iterator.next() { + None => return Vec::new(), + Some(element) => { + let (lower, _) = iterator.size_hint(); + let mut vector = Vec::with_capacity(lower.saturating_add(1)); + unsafe { + ptr::write(vector.as_mut_ptr(), element); + vector.set_len(1); + } + vector + } + }; + // must delegate to spec_extend() since extend() itself delegates + // to spec_from for empty Vecs + as SpecExtend>::spec_extend(&mut vector, iterator); + vector + } +} + +impl SpecFromIterNested for Vec + where + I: TrustedLen, +{ + fn from_iter(iterator: I) -> Self { + let mut vector = match iterator.size_hint() { + (_, Some(upper)) => Vec::with_capacity(upper), + _ => Vec::new(), + }; + // must delegate to spec_extend() since extend() itself delegates + // to spec_from for empty Vecs + vector.spec_extend(iterator); + vector + } +} -- cgit 1.4.1-3-g733a5 From d24a27797df96bb1dbc886f0997138965c5d7b50 Mon Sep 17 00:00:00 2001 From: C Date: Sat, 5 Dec 2020 01:37:10 +0000 Subject: refactor: moving SpecFromIter into spec_from_iter.rs --- library/alloc/src/vec/mod.rs | 96 ++------------------------------ library/alloc/src/vec/spec_from_iter.rs | 98 +++++++++++++++++++++++++++++++++ 2 files changed, 102 insertions(+), 92 deletions(-) create mode 100644 library/alloc/src/vec/spec_from_iter.rs (limited to 'library/alloc/src') diff --git a/library/alloc/src/vec/mod.rs b/library/alloc/src/vec/mod.rs index 438246ab4cb..dfb837d54f5 100644 --- a/library/alloc/src/vec/mod.rs +++ b/library/alloc/src/vec/mod.rs @@ -121,6 +121,10 @@ use self::spec_from_iter_nested::SpecFromIterNested; mod spec_from_iter_nested; +use self::spec_from_iter::SpecFromIter; + +mod spec_from_iter; + /// A contiguous growable array type, written `Vec` but pronounced 'vector'. /// /// # Examples @@ -2156,98 +2160,6 @@ impl Extend for Vec { } } -/// Specialization trait used for Vec::from_iter -/// -/// ## The delegation graph: -/// -/// ```text -/// +-------------+ -/// |FromIterator | -/// +-+-----------+ -/// | -/// v -/// +-+-------------------------------+ +---------------------+ -/// |SpecFromIter +---->+SpecFromIterNested | -/// |where I: | | |where I: | -/// | Iterator (default)----------+ | | Iterator (default) | -/// | vec::IntoIter | | | TrustedLen | -/// | SourceIterMarker---fallback-+ | | | -/// | slice::Iter | | | -/// | Iterator | +---------------------+ -/// +---------------------------------+ -/// ``` -trait SpecFromIter { - fn from_iter(iter: I) -> Self; -} - -impl SpecFromIter for Vec -where - I: Iterator, -{ - default fn from_iter(iterator: I) -> Self { - SpecFromIterNested::from_iter(iterator) - } -} - -impl SpecFromIter> for Vec { - fn from_iter(iterator: IntoIter) -> Self { - // A common case is passing a vector into a function which immediately - // re-collects into a vector. We can short circuit this if the IntoIter - // has not been advanced at all. - // When it has been advanced We can also reuse the memory and move the data to the front. - // But we only do so when the resulting Vec wouldn't have more unused capacity - // than creating it through the generic FromIterator implementation would. That limitation - // is not strictly necessary as Vec's allocation behavior is intentionally unspecified. - // But it is a conservative choice. - let has_advanced = iterator.buf.as_ptr() as *const _ != iterator.ptr; - if !has_advanced || iterator.len() >= iterator.cap / 2 { - unsafe { - let it = ManuallyDrop::new(iterator); - if has_advanced { - ptr::copy(it.ptr, it.buf.as_ptr(), it.len()); - } - return Vec::from_raw_parts(it.buf.as_ptr(), it.len(), it.cap); - } - } - - let mut vec = Vec::new(); - // must delegate to spec_extend() since extend() itself delegates - // to spec_from for empty Vecs - vec.spec_extend(iterator); - vec - } -} - -impl<'a, T: 'a, I> SpecFromIter<&'a T, I> for Vec -where - I: Iterator, - T: Clone, -{ - default fn from_iter(iterator: I) -> Self { - SpecFromIter::from_iter(iterator.cloned()) - } -} - -// This utilizes `iterator.as_slice().to_vec()` since spec_extend -// must take more steps to reason about the final capacity + length -// and thus do more work. `to_vec()` directly allocates the correct amount -// and fills it exactly. -impl<'a, T: 'a + Clone> SpecFromIter<&'a T, slice::Iter<'a, T>> for Vec { - #[cfg(not(test))] - fn from_iter(iterator: slice::Iter<'a, T>) -> Self { - iterator.as_slice().to_vec() - } - - // HACK(japaric): with cfg(test) the inherent `[T]::to_vec` method, which is - // required for this method definition, is not available. Instead use the - // `slice::to_vec` function which is only available with cfg(test) - // NB see the slice::hack module in slice.rs for more information - #[cfg(test)] - fn from_iter(iterator: slice::Iter<'a, T>) -> Self { - crate::slice::to_vec(iterator.as_slice(), Global) - } -} - // Specialization trait used for Vec::extend trait SpecExtend { fn spec_extend(&mut self, iter: I); diff --git a/library/alloc/src/vec/spec_from_iter.rs b/library/alloc/src/vec/spec_from_iter.rs new file mode 100644 index 00000000000..bf07fc97f89 --- /dev/null +++ b/library/alloc/src/vec/spec_from_iter.rs @@ -0,0 +1,98 @@ +use crate::alloc::Global; +use core::mem::{ManuallyDrop}; +use core::ptr::{self}; +use core::slice::{self}; + +use super::{Vec, IntoIter, SpecFromIterNested, SpecExtend}; + +/// Specialization trait used for Vec::from_iter +/// +/// ## The delegation graph: +/// +/// ```text +/// +-------------+ +/// |FromIterator | +/// +-+-----------+ +/// | +/// v +/// +-+-------------------------------+ +---------------------+ +/// |SpecFromIter +---->+SpecFromIterNested | +/// |where I: | | |where I: | +/// | Iterator (default)----------+ | | Iterator (default) | +/// | vec::IntoIter | | | TrustedLen | +/// | SourceIterMarker---fallback-+ | | | +/// | slice::Iter | | | +/// | Iterator | +---------------------+ +/// +---------------------------------+ +/// ``` +pub(super) trait SpecFromIter { + fn from_iter(iter: I) -> Self; +} + +impl SpecFromIter for Vec + where + I: Iterator, +{ + default fn from_iter(iterator: I) -> Self { + SpecFromIterNested::from_iter(iterator) + } +} + +impl SpecFromIter> for Vec { + fn from_iter(iterator: IntoIter) -> Self { + // A common case is passing a vector into a function which immediately + // re-collects into a vector. We can short circuit this if the IntoIter + // has not been advanced at all. + // When it has been advanced We can also reuse the memory and move the data to the front. + // But we only do so when the resulting Vec wouldn't have more unused capacity + // than creating it through the generic FromIterator implementation would. That limitation + // is not strictly necessary as Vec's allocation behavior is intentionally unspecified. + // But it is a conservative choice. + let has_advanced = iterator.buf.as_ptr() as *const _ != iterator.ptr; + if !has_advanced || iterator.len() >= iterator.cap / 2 { + unsafe { + let it = ManuallyDrop::new(iterator); + if has_advanced { + ptr::copy(it.ptr, it.buf.as_ptr(), it.len()); + } + return Vec::from_raw_parts(it.buf.as_ptr(), it.len(), it.cap); + } + } + + let mut vec = Vec::new(); + // must delegate to spec_extend() since extend() itself delegates + // to spec_from for empty Vecs + vec.spec_extend(iterator); + vec + } +} + +impl<'a, T: 'a, I> SpecFromIter<&'a T, I> for Vec + where + I: Iterator, + T: Clone, +{ + default fn from_iter(iterator: I) -> Self { + SpecFromIter::from_iter(iterator.cloned()) + } +} + +// This utilizes `iterator.as_slice().to_vec()` since spec_extend +// must take more steps to reason about the final capacity + length +// and thus do more work. `to_vec()` directly allocates the correct amount +// and fills it exactly. +impl<'a, T: 'a + Clone> SpecFromIter<&'a T, slice::Iter<'a, T>> for Vec { + #[cfg(not(test))] + fn from_iter(iterator: slice::Iter<'a, T>) -> Self { + iterator.as_slice().to_vec() + } + + // HACK(japaric): with cfg(test) the inherent `[T]::to_vec` method, which is + // required for this method definition, is not available. Instead use the + // `slice::to_vec` function which is only available with cfg(test) + // NB see the slice::hack module in slice.rs for more information + #[cfg(test)] + fn from_iter(iterator: slice::Iter<'a, T>) -> Self { + crate::slice::to_vec(iterator.as_slice(), Global) + } +} -- cgit 1.4.1-3-g733a5 From bd49a60f2943c313adae8582f266b875c9b7eaa9 Mon Sep 17 00:00:00 2001 From: C Date: Sat, 5 Dec 2020 01:41:44 +0000 Subject: refactor: moved SpecExtend into spec_extend.rs --- library/alloc/src/vec/mod.rs | 84 +++--------------------------------- library/alloc/src/vec/spec_extend.rs | 82 +++++++++++++++++++++++++++++++++++ 2 files changed, 87 insertions(+), 79 deletions(-) create mode 100644 library/alloc/src/vec/spec_extend.rs (limited to 'library/alloc/src') diff --git a/library/alloc/src/vec/mod.rs b/library/alloc/src/vec/mod.rs index dfb837d54f5..32470941755 100644 --- a/library/alloc/src/vec/mod.rs +++ b/library/alloc/src/vec/mod.rs @@ -59,9 +59,7 @@ use core::convert::TryFrom; use core::fmt; use core::hash::{Hash, Hasher}; use core::intrinsics::{arith_offset, assume}; -use core::iter::{ - FromIterator, TrustedLen, -}; +use core::iter::{FromIterator}; use core::marker::PhantomData; use core::mem::{self, ManuallyDrop, MaybeUninit}; use core::ops::{self, Index, IndexMut, Range, RangeBounds}; @@ -125,6 +123,10 @@ use self::spec_from_iter::SpecFromIter; mod spec_from_iter; +use self::spec_extend::SpecExtend; + +mod spec_extend; + /// A contiguous growable array type, written `Vec` but pronounced 'vector'. /// /// # Examples @@ -2160,82 +2162,6 @@ impl Extend for Vec { } } -// Specialization trait used for Vec::extend -trait SpecExtend { - fn spec_extend(&mut self, iter: I); -} - -impl SpecExtend for Vec -where - I: Iterator, -{ - default fn spec_extend(&mut self, iter: I) { - self.extend_desugared(iter) - } -} - -impl SpecExtend for Vec -where - I: TrustedLen, -{ - default fn spec_extend(&mut self, iterator: I) { - // This is the case for a TrustedLen iterator. - let (low, high) = iterator.size_hint(); - if let Some(high_value) = high { - debug_assert_eq!( - low, - high_value, - "TrustedLen iterator's size hint is not exact: {:?}", - (low, high) - ); - } - if let Some(additional) = high { - self.reserve(additional); - unsafe { - let mut ptr = self.as_mut_ptr().add(self.len()); - let mut local_len = SetLenOnDrop::new(&mut self.len); - iterator.for_each(move |element| { - ptr::write(ptr, element); - ptr = ptr.offset(1); - // NB can't overflow since we would have had to alloc the address space - local_len.increment_len(1); - }); - } - } else { - self.extend_desugared(iterator) - } - } -} - -impl SpecExtend> for Vec { - fn spec_extend(&mut self, mut iterator: IntoIter) { - unsafe { - self.append_elements(iterator.as_slice() as _); - } - iterator.ptr = iterator.end; - } -} - -impl<'a, T: 'a, I, A: Allocator + 'a> SpecExtend<&'a T, I> for Vec -where - I: Iterator, - T: Clone, -{ - default fn spec_extend(&mut self, iterator: I) { - self.spec_extend(iterator.cloned()) - } -} - -impl<'a, T: 'a, A: Allocator + 'a> SpecExtend<&'a T, slice::Iter<'a, T>> for Vec -where - T: Copy, -{ - fn spec_extend(&mut self, iterator: slice::Iter<'a, T>) { - let slice = iterator.as_slice(); - unsafe { self.append_elements(slice) }; - } -} - impl Vec { // leaf method to which various SpecFrom/SpecExtend implementations delegate when // they have no further optimizations to apply diff --git a/library/alloc/src/vec/spec_extend.rs b/library/alloc/src/vec/spec_extend.rs new file mode 100644 index 00000000000..6959733d074 --- /dev/null +++ b/library/alloc/src/vec/spec_extend.rs @@ -0,0 +1,82 @@ +use crate::alloc::{Allocator}; +use core::iter::{TrustedLen}; +use core::slice::{self}; +use core::ptr::{self}; + +use super::{Vec, IntoIter, SetLenOnDrop}; + +// Specialization trait used for Vec::extend +pub(super) trait SpecExtend { + fn spec_extend(&mut self, iter: I); +} + +impl SpecExtend for Vec + where + I: Iterator, +{ + default fn spec_extend(&mut self, iter: I) { + self.extend_desugared(iter) + } +} + +impl SpecExtend for Vec + where + I: TrustedLen, +{ + default fn spec_extend(&mut self, iterator: I) { + // This is the case for a TrustedLen iterator. + let (low, high) = iterator.size_hint(); + if let Some(high_value) = high { + debug_assert_eq!( + low, + high_value, + "TrustedLen iterator's size hint is not exact: {:?}", + (low, high) + ); + } + if let Some(additional) = high { + self.reserve(additional); + unsafe { + let mut ptr = self.as_mut_ptr().add(self.len()); + let mut local_len = SetLenOnDrop::new(&mut self.len); + iterator.for_each(move |element| { + ptr::write(ptr, element); + ptr = ptr.offset(1); + // NB can't overflow since we would have had to alloc the address space + local_len.increment_len(1); + }); + } + } else { + self.extend_desugared(iterator) + } + } +} + +impl SpecExtend> for Vec { + fn spec_extend(&mut self, mut iterator: IntoIter) { + unsafe { + self.append_elements(iterator.as_slice() as _); + } + iterator.ptr = iterator.end; + } +} + +impl<'a, T: 'a, I, A: Allocator + 'a> SpecExtend<&'a T, I> for Vec + where + I: Iterator, + T: Clone, +{ + default fn spec_extend(&mut self, iterator: I) { + self.spec_extend(iterator.cloned()) + } +} + +impl<'a, T: 'a, A: Allocator + 'a> SpecExtend<&'a T, slice::Iter<'a, T>> for Vec + where + T: Copy, +{ + fn spec_extend(&mut self, iterator: slice::Iter<'a, T>) { + let slice = iterator.as_slice(); + unsafe { self.append_elements(slice) }; + } +} -- cgit 1.4.1-3-g733a5 From 6002b280f119a12631da0d1bb7e6adad53cefc95 Mon Sep 17 00:00:00 2001 From: C Date: Sat, 5 Dec 2020 01:42:29 +0000 Subject: refactor: removing // ignore-tidy-filelength --- library/alloc/src/vec/mod.rs | 1 - 1 file changed, 1 deletion(-) (limited to 'library/alloc/src') diff --git a/library/alloc/src/vec/mod.rs b/library/alloc/src/vec/mod.rs index 32470941755..2947c6a299f 100644 --- a/library/alloc/src/vec/mod.rs +++ b/library/alloc/src/vec/mod.rs @@ -1,4 +1,3 @@ -// ignore-tidy-filelength //! A contiguous growable array type with heap-allocated contents, written //! `Vec`. //! -- cgit 1.4.1-3-g733a5 From 2de8356f60a7a9800809ab60e813fcfd4a7accf2 Mon Sep 17 00:00:00 2001 From: C Date: Sat, 5 Dec 2020 01:44:07 +0000 Subject: style: applying Rust style --- library/alloc/src/vec/cow.rs | 10 +++++----- library/alloc/src/vec/drain.rs | 8 +++----- library/alloc/src/vec/drain_filter.rs | 26 +++++++++++++------------- library/alloc/src/vec/in_place_drop.rs | 6 +++--- library/alloc/src/vec/into_iter.rs | 16 +++++++--------- library/alloc/src/vec/is_zero.rs | 2 +- library/alloc/src/vec/mod.rs | 4 ++-- library/alloc/src/vec/partial_eq.rs | 4 ++-- library/alloc/src/vec/source_iter_marker.rs | 16 +++++++--------- library/alloc/src/vec/spec_extend.rs | 26 +++++++++++++------------- library/alloc/src/vec/spec_from_elem.rs | 6 +++--- library/alloc/src/vec/spec_from_iter.rs | 14 +++++++------- library/alloc/src/vec/spec_from_iter_nested.rs | 12 ++++++------ library/alloc/src/vec/splice.rs | 4 ++-- 14 files changed, 74 insertions(+), 80 deletions(-) (limited to 'library/alloc/src') diff --git a/library/alloc/src/vec/cow.rs b/library/alloc/src/vec/cow.rs index 15942f9892d..73d15d30647 100644 --- a/library/alloc/src/vec/cow.rs +++ b/library/alloc/src/vec/cow.rs @@ -1,7 +1,7 @@ use crate::borrow::Cow; -use core::iter::{FromIterator}; +use core::iter::FromIterator; -use super::{Vec}; +use super::Vec; #[stable(feature = "cow_from_vec", since = "1.8.0")] impl<'a, T: Clone> From<&'a [T]> for Cow<'a, [T]> { @@ -26,10 +26,10 @@ impl<'a, T: Clone> From<&'a Vec> for Cow<'a, [T]> { #[stable(feature = "rust1", since = "1.0.0")] impl<'a, T> FromIterator for Cow<'a, [T]> - where - T: Clone, +where + T: Clone, { fn from_iter>(it: I) -> Cow<'a, [T]> { Cow::Owned(FromIterator::from_iter(it)) } -} \ No newline at end of file +} diff --git a/library/alloc/src/vec/drain.rs b/library/alloc/src/vec/drain.rs index e61f17a1c30..fb32d144f87 100644 --- a/library/alloc/src/vec/drain.rs +++ b/library/alloc/src/vec/drain.rs @@ -1,13 +1,11 @@ use crate::alloc::{Allocator, Global}; -use core::iter::{ - FusedIterator, TrustedLen, -}; +use core::fmt; +use core::iter::{FusedIterator, TrustedLen}; use core::mem::{self}; use core::ptr::{self, NonNull}; use core::slice::{self}; -use core::fmt; -use super::{Vec}; +use super::Vec; /// A draining iterator for `Vec`. /// diff --git a/library/alloc/src/vec/drain_filter.rs b/library/alloc/src/vec/drain_filter.rs index 9d898c7c756..3c37c92ae44 100644 --- a/library/alloc/src/vec/drain_filter.rs +++ b/library/alloc/src/vec/drain_filter.rs @@ -1,8 +1,8 @@ +use crate::alloc::{Allocator, Global}; use core::ptr::{self}; use core::slice::{self}; -use crate::alloc::{Allocator, Global}; -use super::{Vec}; +use super::Vec; /// An iterator which uses a closure to determine if an element should be removed. /// @@ -45,8 +45,8 @@ pub struct DrainFilter< } impl DrainFilter<'_, T, F, A> - where - F: FnMut(&mut T) -> bool, +where + F: FnMut(&mut T) -> bool, { /// Returns a reference to the underlying allocator. #[unstable(feature = "allocator_api", issue = "32838")] @@ -58,8 +58,8 @@ impl DrainFilter<'_, T, F, A> #[unstable(feature = "drain_filter", reason = "recently added", issue = "43244")] impl Iterator for DrainFilter<'_, T, F, A> - where - F: FnMut(&mut T) -> bool, +where + F: FnMut(&mut T) -> bool, { type Item = T; @@ -96,20 +96,20 @@ impl Iterator for DrainFilter<'_, T, F, A> #[unstable(feature = "drain_filter", reason = "recently added", issue = "43244")] impl Drop for DrainFilter<'_, T, F, A> - where - F: FnMut(&mut T) -> bool, +where + F: FnMut(&mut T) -> bool, { fn drop(&mut self) { struct BackshiftOnDrop<'a, 'b, T, F, A: Allocator> - where - F: FnMut(&mut T) -> bool, + where + F: FnMut(&mut T) -> bool, { drain: &'b mut DrainFilter<'a, T, F, A>, } impl<'a, 'b, T, F, A: Allocator> Drop for BackshiftOnDrop<'a, 'b, T, F, A> - where - F: FnMut(&mut T) -> bool, + where + F: FnMut(&mut T) -> bool, { fn drop(&mut self) { unsafe { @@ -140,4 +140,4 @@ impl Drop for DrainFilter<'_, T, F, A> backshift.drain.for_each(drop); } } -} \ No newline at end of file +} diff --git a/library/alloc/src/vec/in_place_drop.rs b/library/alloc/src/vec/in_place_drop.rs index 3a0ecc529c0..354d25c2389 100644 --- a/library/alloc/src/vec/in_place_drop.rs +++ b/library/alloc/src/vec/in_place_drop.rs @@ -3,9 +3,9 @@ use core::slice::{self}; // A helper struct for in-place iteration that drops the destination slice of iteration, // i.e. the head. The source slice (the tail) is dropped by IntoIter. -pub (super) struct InPlaceDrop { - pub (super) inner: *mut T, - pub (super) dst: *mut T, +pub(super) struct InPlaceDrop { + pub(super) inner: *mut T, + pub(super) dst: *mut T, } impl InPlaceDrop { diff --git a/library/alloc/src/vec/into_iter.rs b/library/alloc/src/vec/into_iter.rs index c4330df4ad9..1788690d96b 100644 --- a/library/alloc/src/vec/into_iter.rs +++ b/library/alloc/src/vec/into_iter.rs @@ -1,14 +1,12 @@ use crate::alloc::{Allocator, Global}; use crate::raw_vec::RawVec; +use core::fmt; +use core::intrinsics::arith_offset; +use core::iter::{FusedIterator, InPlaceIterable, SourceIter, TrustedLen, TrustedRandomAccess}; use core::marker::PhantomData; -use core::intrinsics::{arith_offset}; use core::mem::{self}; -use core::fmt; use core::ptr::{self, NonNull}; use core::slice::{self}; -use core::iter::{ - FusedIterator, InPlaceIterable, SourceIter, TrustedLen, TrustedRandomAccess, -}; /// An iterator that moves out of a vector. /// @@ -156,8 +154,8 @@ impl Iterator for IntoIter { } unsafe fn __iterator_get_unchecked(&mut self, i: usize) -> Self::Item - where - Self: TrustedRandomAccess, + where + Self: TrustedRandomAccess, { // SAFETY: the caller must guarantee that `i` is in bounds of the // `Vec`, so `i` cannot overflow an `isize`, and the `self.ptr.add(i)` @@ -211,8 +209,8 @@ unsafe impl TrustedLen for IntoIter {} // T: Copy as approximation for !Drop since get_unchecked does not advance self.ptr // and thus we can't implement drop-handling unsafe impl TrustedRandomAccess for IntoIter - where - T: Copy, +where + T: Copy, { fn may_have_side_effect() -> bool { false diff --git a/library/alloc/src/vec/is_zero.rs b/library/alloc/src/vec/is_zero.rs index 961f6ca171b..b5739970b6e 100644 --- a/library/alloc/src/vec/is_zero.rs +++ b/library/alloc/src/vec/is_zero.rs @@ -68,4 +68,4 @@ unsafe impl IsZero for Option> { fn is_zero(&self) -> bool { self.is_none() } -} \ No newline at end of file +} diff --git a/library/alloc/src/vec/mod.rs b/library/alloc/src/vec/mod.rs index 2947c6a299f..2a83eb33fe3 100644 --- a/library/alloc/src/vec/mod.rs +++ b/library/alloc/src/vec/mod.rs @@ -58,7 +58,7 @@ use core::convert::TryFrom; use core::fmt; use core::hash::{Hash, Hasher}; use core::intrinsics::{arith_offset, assume}; -use core::iter::{FromIterator}; +use core::iter::FromIterator; use core::marker::PhantomData; use core::mem::{self, ManuallyDrop, MaybeUninit}; use core::ops::{self, Index, IndexMut, Range, RangeBounds}; @@ -88,9 +88,9 @@ mod drain; mod cow; +pub(crate) use self::into_iter::AsIntoIter; #[stable(feature = "rust1", since = "1.0.0")] pub use self::into_iter::IntoIter; -pub (crate) use self::into_iter::AsIntoIter; mod into_iter; diff --git a/library/alloc/src/vec/partial_eq.rs b/library/alloc/src/vec/partial_eq.rs index 617f0404439..ff90b6caf46 100644 --- a/library/alloc/src/vec/partial_eq.rs +++ b/library/alloc/src/vec/partial_eq.rs @@ -1,7 +1,7 @@ -use crate::alloc::{Allocator}; +use crate::alloc::Allocator; use crate::borrow::Cow; -use super::{Vec}; +use super::Vec; macro_rules! __impl_slice_eq1 { ([$($vars:tt)*] $lhs:ty, $rhs:ty $(where $ty:ty: $bound:ident)?, #[$stability:meta]) => { diff --git a/library/alloc/src/vec/source_iter_marker.rs b/library/alloc/src/vec/source_iter_marker.rs index eb3ae01a47e..8c0e95559fa 100644 --- a/library/alloc/src/vec/source_iter_marker.rs +++ b/library/alloc/src/vec/source_iter_marker.rs @@ -1,10 +1,8 @@ -use core::iter::{ - InPlaceIterable, SourceIter, -}; +use core::iter::{InPlaceIterable, SourceIter}; use core::mem::{self, ManuallyDrop}; use core::ptr::{self}; -use super::{Vec, InPlaceDrop, AsIntoIter, SpecFromIter, SpecFromIterNested}; +use super::{AsIntoIter, InPlaceDrop, SpecFromIter, SpecFromIterNested, Vec}; /// Specialization marker for collecting an iterator pipeline into a Vec while reusing the /// source allocation, i.e. executing the pipeline in place. @@ -13,7 +11,7 @@ use super::{Vec, InPlaceDrop, AsIntoIter, SpecFromIter, SpecFromIterNested}; /// which is to be reused. But it is not sufficient for the specialization to be valid. See /// additional bounds on the impl. #[rustc_unsafe_specialization_marker] -pub (super) trait SourceIterMarker: SourceIter {} +pub(super) trait SourceIterMarker: SourceIter {} // The std-internal SourceIter/InPlaceIterable traits are only implemented by chains of // Adapter>> (all owned by core/std). Additional bounds @@ -24,8 +22,8 @@ pub (super) trait SourceIterMarker: SourceIter {} impl SourceIterMarker for T where T: SourceIter + InPlaceIterable {} impl SpecFromIter for Vec - where - I: Iterator + SourceIterMarker, +where + I: Iterator + SourceIterMarker, { default fn from_iter(mut iterator: I) -> Self { // Additional requirements which cannot expressed via trait bounds. We rely on const eval @@ -35,9 +33,9 @@ impl SpecFromIter for Vec // c) alignments match as required by Alloc contract if mem::size_of::() == 0 || mem::size_of::() - != mem::size_of::<<::Source as AsIntoIter>::Item>() + != mem::size_of::<<::Source as AsIntoIter>::Item>() || mem::align_of::() - != mem::align_of::<<::Source as AsIntoIter>::Item>() + != mem::align_of::<<::Source as AsIntoIter>::Item>() { // fallback to more generic implementations return SpecFromIterNested::from_iter(iterator); diff --git a/library/alloc/src/vec/spec_extend.rs b/library/alloc/src/vec/spec_extend.rs index 6959733d074..b6186a7ebaf 100644 --- a/library/alloc/src/vec/spec_extend.rs +++ b/library/alloc/src/vec/spec_extend.rs @@ -1,9 +1,9 @@ -use crate::alloc::{Allocator}; -use core::iter::{TrustedLen}; -use core::slice::{self}; +use crate::alloc::Allocator; +use core::iter::TrustedLen; use core::ptr::{self}; +use core::slice::{self}; -use super::{Vec, IntoIter, SetLenOnDrop}; +use super::{IntoIter, SetLenOnDrop, Vec}; // Specialization trait used for Vec::extend pub(super) trait SpecExtend { @@ -11,8 +11,8 @@ pub(super) trait SpecExtend { } impl SpecExtend for Vec - where - I: Iterator, +where + I: Iterator, { default fn spec_extend(&mut self, iter: I) { self.extend_desugared(iter) @@ -20,8 +20,8 @@ impl SpecExtend for Vec } impl SpecExtend for Vec - where - I: TrustedLen, +where + I: TrustedLen, { default fn spec_extend(&mut self, iterator: I) { // This is the case for a TrustedLen iterator. @@ -62,9 +62,9 @@ impl SpecExtend> for Vec { } impl<'a, T: 'a, I, A: Allocator + 'a> SpecExtend<&'a T, I> for Vec - where - I: Iterator, - T: Clone, +where + I: Iterator, + T: Clone, { default fn spec_extend(&mut self, iterator: I) { self.spec_extend(iterator.cloned()) @@ -72,8 +72,8 @@ impl<'a, T: 'a, I, A: Allocator + 'a> SpecExtend<&'a T, I> for Vec } impl<'a, T: 'a, A: Allocator + 'a> SpecExtend<&'a T, slice::Iter<'a, T>> for Vec - where - T: Copy, +where + T: Copy, { fn spec_extend(&mut self, iterator: slice::Iter<'a, T>) { let slice = iterator.as_slice(); diff --git a/library/alloc/src/vec/spec_from_elem.rs b/library/alloc/src/vec/spec_from_elem.rs index ef89054ea13..de610174783 100644 --- a/library/alloc/src/vec/spec_from_elem.rs +++ b/library/alloc/src/vec/spec_from_elem.rs @@ -1,8 +1,8 @@ -use crate::alloc::{Allocator}; +use crate::alloc::Allocator; use crate::raw_vec::RawVec; use core::ptr::{self}; -use super::{Vec, IsZero, ExtendElement}; +use super::{ExtendElement, IsZero, Vec}; // Specialization trait used for Vec::from_elem pub(super) trait SpecFromElem: Sized { @@ -57,4 +57,4 @@ impl SpecFromElem for T { v.extend_with(n, ExtendElement(elem)); v } -} \ No newline at end of file +} diff --git a/library/alloc/src/vec/spec_from_iter.rs b/library/alloc/src/vec/spec_from_iter.rs index bf07fc97f89..4349d158210 100644 --- a/library/alloc/src/vec/spec_from_iter.rs +++ b/library/alloc/src/vec/spec_from_iter.rs @@ -1,9 +1,9 @@ use crate::alloc::Global; -use core::mem::{ManuallyDrop}; +use core::mem::ManuallyDrop; use core::ptr::{self}; use core::slice::{self}; -use super::{Vec, IntoIter, SpecFromIterNested, SpecExtend}; +use super::{IntoIter, SpecExtend, SpecFromIterNested, Vec}; /// Specialization trait used for Vec::from_iter /// @@ -30,8 +30,8 @@ pub(super) trait SpecFromIter { } impl SpecFromIter for Vec - where - I: Iterator, +where + I: Iterator, { default fn from_iter(iterator: I) -> Self { SpecFromIterNested::from_iter(iterator) @@ -68,9 +68,9 @@ impl SpecFromIter> for Vec { } impl<'a, T: 'a, I> SpecFromIter<&'a T, I> for Vec - where - I: Iterator, - T: Clone, +where + I: Iterator, + T: Clone, { default fn from_iter(iterator: I) -> Self { SpecFromIter::from_iter(iterator.cloned()) diff --git a/library/alloc/src/vec/spec_from_iter_nested.rs b/library/alloc/src/vec/spec_from_iter_nested.rs index 0da42844c96..6abd4ff2a3f 100644 --- a/library/alloc/src/vec/spec_from_iter_nested.rs +++ b/library/alloc/src/vec/spec_from_iter_nested.rs @@ -1,7 +1,7 @@ +use core::iter::TrustedLen; use core::ptr::{self}; -use core::iter::{TrustedLen}; -use super::{Vec, SpecExtend}; +use super::{SpecExtend, Vec}; /// Another specialization trait for Vec::from_iter /// necessary to manually prioritize overlapping specializations @@ -11,8 +11,8 @@ pub(super) trait SpecFromIterNested { } impl SpecFromIterNested for Vec - where - I: Iterator, +where + I: Iterator, { default fn from_iter(mut iterator: I) -> Self { // Unroll the first iteration, as the vector is going to be @@ -40,8 +40,8 @@ impl SpecFromIterNested for Vec } impl SpecFromIterNested for Vec - where - I: TrustedLen, +where + I: TrustedLen, { fn from_iter(iterator: I) -> Self { let mut vector = match iterator.size_hint() { diff --git a/library/alloc/src/vec/splice.rs b/library/alloc/src/vec/splice.rs index 86b2fa0968e..0a27b5b62ec 100644 --- a/library/alloc/src/vec/splice.rs +++ b/library/alloc/src/vec/splice.rs @@ -2,7 +2,7 @@ use crate::alloc::{Allocator, Global}; use core::ptr::{self}; use core::slice::{self}; -use super::{Vec, Drain}; +use super::{Drain, Vec}; /// A splicing iterator for `Vec`. /// @@ -130,4 +130,4 @@ impl Drain<'_, T, A> { } self.tail_start = new_tail_start; } -} \ No newline at end of file +} -- cgit 1.4.1-3-g733a5 From 80f10d7aa7b3e3bf9a47de6ef2a9f4439d993c48 Mon Sep 17 00:00:00 2001 From: C Date: Sat, 5 Dec 2020 13:27:03 +0000 Subject: fix: moved import into #[cfg(test)] --- library/alloc/src/vec/spec_from_iter.rs | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) (limited to 'library/alloc/src') diff --git a/library/alloc/src/vec/spec_from_iter.rs b/library/alloc/src/vec/spec_from_iter.rs index 4349d158210..bbfcc68daef 100644 --- a/library/alloc/src/vec/spec_from_iter.rs +++ b/library/alloc/src/vec/spec_from_iter.rs @@ -1,4 +1,3 @@ -use crate::alloc::Global; use core::mem::ManuallyDrop; use core::ptr::{self}; use core::slice::{self}; @@ -93,6 +92,6 @@ impl<'a, T: 'a + Clone> SpecFromIter<&'a T, slice::Iter<'a, T>> for Vec { // NB see the slice::hack module in slice.rs for more information #[cfg(test)] fn from_iter(iterator: slice::Iter<'a, T>) -> Self { - crate::slice::to_vec(iterator.as_slice(), Global) + crate::slice::to_vec(iterator.as_slice(), crate::alloc::Global) } } -- cgit 1.4.1-3-g733a5 From f7a6f0cae3f6850ad84b8fa6ba6b9f06ae94c27d Mon Sep 17 00:00:00 2001 From: C Date: Sat, 5 Dec 2020 13:47:27 +0000 Subject: docs: fixing references --- library/alloc/src/vec/into_iter.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'library/alloc/src') diff --git a/library/alloc/src/vec/into_iter.rs b/library/alloc/src/vec/into_iter.rs index 1788690d96b..99ecec648ad 100644 --- a/library/alloc/src/vec/into_iter.rs +++ b/library/alloc/src/vec/into_iter.rs @@ -10,7 +10,7 @@ use core::slice::{self}; /// An iterator that moves out of a vector. /// -/// This `struct` is created by the `into_iter` method on [`Vec`] (provided +/// This `struct` is created by the `into_iter` method on [`super::Vec`] (provided /// by the [`IntoIterator`] trait). /// /// # Example -- cgit 1.4.1-3-g733a5 From 81685e9ad8f80634f0dfd7c1afcab74ba1c78a59 Mon Sep 17 00:00:00 2001 From: CAD97 Date: Tue, 29 Dec 2020 15:42:41 -0500 Subject: Do not create dangling &T in Weak::drop --- library/alloc/src/rc.rs | 2 +- library/alloc/src/sync.rs | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) (limited to 'library/alloc/src') diff --git a/library/alloc/src/rc.rs b/library/alloc/src/rc.rs index 73d12f0a5f4..57df28a15c8 100644 --- a/library/alloc/src/rc.rs +++ b/library/alloc/src/rc.rs @@ -2042,7 +2042,7 @@ impl Drop for Weak { // the strong pointers have disappeared. if inner.weak() == 0 { unsafe { - Global.deallocate(self.ptr.cast(), Layout::for_value(self.ptr.as_ref())); + Global.deallocate(self.ptr.cast(), Layout::for_value_raw(self.ptr.as_ptr())); } } } diff --git a/library/alloc/src/sync.rs b/library/alloc/src/sync.rs index 7c03345aba5..85c0a9f0857 100644 --- a/library/alloc/src/sync.rs +++ b/library/alloc/src/sync.rs @@ -1927,7 +1927,7 @@ impl Drop for Weak { if inner.weak.fetch_sub(1, Release) == 1 { acquire!(inner.weak); - unsafe { Global.deallocate(self.ptr.cast(), Layout::for_value(self.ptr.as_ref())) } + unsafe { Global.deallocate(self.ptr.cast(), Layout::for_value_raw(self.ptr.as_ptr())) } } } } -- cgit 1.4.1-3-g733a5 From fe031180d0be11ce15ee82872829af4092356188 Mon Sep 17 00:00:00 2001 From: Mark Rousskov Date: Wed, 30 Dec 2020 08:04:59 -0500 Subject: Bump bootstrap compiler to 1.50 beta --- compiler/rustc_data_structures/src/lib.rs | 3 +- library/alloc/src/lib.rs | 3 +- library/core/src/intrinsics.rs | 1 - library/core/src/lib.rs | 5 +-- library/core/src/macros/mod.rs | 6 +-- library/core/src/sync/atomic.rs | 66 ++----------------------------- library/core/tests/mem.rs | 1 - library/proc_macro/src/lib.rs | 3 +- library/rtstartup/rsbegin.rs | 3 +- library/rtstartup/rsend.rs | 3 +- library/std/src/lib.rs | 3 +- library/std/src/macros.rs | 2 +- src/bootstrap/builder.rs | 5 +-- src/bootstrap/doc.rs | 5 +-- src/stage0.txt | 2 +- 15 files changed, 19 insertions(+), 92 deletions(-) (limited to 'library/alloc/src') diff --git a/compiler/rustc_data_structures/src/lib.rs b/compiler/rustc_data_structures/src/lib.rs index 01d3a759316..5880bbd3de4 100644 --- a/compiler/rustc_data_structures/src/lib.rs +++ b/compiler/rustc_data_structures/src/lib.rs @@ -15,8 +15,7 @@ #![feature(fn_traits)] #![feature(int_bits_const)] #![feature(min_specialization)] -#![cfg_attr(bootstrap, feature(optin_builtin_traits))] -#![cfg_attr(not(bootstrap), feature(auto_traits))] +#![feature(auto_traits)] #![feature(nll)] #![feature(allow_internal_unstable)] #![feature(hash_raw_entry)] diff --git a/library/alloc/src/lib.rs b/library/alloc/src/lib.rs index 3ac34c9ae28..54b402faaeb 100644 --- a/library/alloc/src/lib.rs +++ b/library/alloc/src/lib.rs @@ -112,8 +112,7 @@ #![feature(never_type)] #![feature(nll)] #![feature(nonnull_slice_from_raw_parts)] -#![cfg_attr(bootstrap, feature(optin_builtin_traits))] -#![cfg_attr(not(bootstrap), feature(auto_traits))] +#![feature(auto_traits)] #![feature(or_patterns)] #![feature(pattern)] #![feature(ptr_internals)] diff --git a/library/core/src/intrinsics.rs b/library/core/src/intrinsics.rs index 52921822693..74adb170a1d 100644 --- a/library/core/src/intrinsics.rs +++ b/library/core/src/intrinsics.rs @@ -1736,7 +1736,6 @@ extern "rust-intrinsic" { /// Allocate at compile time. Should not be called at runtime. #[rustc_const_unstable(feature = "const_heap", issue = "79597")] - #[cfg(not(bootstrap))] pub fn const_allocate(size: usize, align: usize) -> *mut u8; } diff --git a/library/core/src/lib.rs b/library/core/src/lib.rs index 5b19bf6b80f..a3283b5b204 100644 --- a/library/core/src/lib.rs +++ b/library/core/src/lib.rs @@ -68,7 +68,7 @@ #![feature(arbitrary_self_types)] #![feature(asm)] #![feature(cfg_target_has_atomic)] -#![cfg_attr(not(bootstrap), feature(const_heap))] +#![feature(const_heap)] #![feature(const_alloc_layout)] #![feature(const_assert_type)] #![feature(const_discriminant)] @@ -122,8 +122,7 @@ #![feature(nll)] #![feature(exhaustive_patterns)] #![feature(no_core)] -#![cfg_attr(bootstrap, feature(optin_builtin_traits))] -#![cfg_attr(not(bootstrap), feature(auto_traits))] +#![feature(auto_traits)] #![feature(or_patterns)] #![feature(prelude_import)] #![feature(repr_simd, platform_intrinsics)] diff --git a/library/core/src/macros/mod.rs b/library/core/src/macros/mod.rs index 0699c9eab18..1634aff7b4d 100644 --- a/library/core/src/macros/mod.rs +++ b/library/core/src/macros/mod.rs @@ -2,7 +2,7 @@ #[macro_export] #[allow_internal_unstable(core_panic, const_caller_location)] #[stable(feature = "core", since = "1.6.0")] -#[cfg_attr(not(bootstrap), rustc_diagnostic_item = "core_panic_macro")] +#[rustc_diagnostic_item = "core_panic_macro"] macro_rules! panic { () => ( $crate::panic!("explicit panic") @@ -163,7 +163,7 @@ macro_rules! assert_ne { /// ``` #[macro_export] #[stable(feature = "rust1", since = "1.0.0")] -#[cfg_attr(not(bootstrap), rustc_diagnostic_item = "debug_assert_macro")] +#[rustc_diagnostic_item = "debug_assert_macro"] macro_rules! debug_assert { ($($arg:tt)*) => (if $crate::cfg!(debug_assertions) { $crate::assert!($($arg)*); }) } @@ -1217,7 +1217,7 @@ pub(crate) mod builtin { #[stable(feature = "rust1", since = "1.0.0")] #[rustc_builtin_macro] #[macro_export] - #[cfg_attr(not(bootstrap), rustc_diagnostic_item = "assert_macro")] + #[rustc_diagnostic_item = "assert_macro"] #[allow_internal_unstable(core_panic)] macro_rules! assert { ($cond:expr $(,)?) => {{ /* compiler built-in */ }}; diff --git a/library/core/src/sync/atomic.rs b/library/core/src/sync/atomic.rs index 36857979af8..e4b99e10354 100644 --- a/library/core/src/sync/atomic.rs +++ b/library/core/src/sync/atomic.rs @@ -991,16 +991,8 @@ impl AtomicPtr { #[inline] #[stable(feature = "rust1", since = "1.0.0")] pub fn load(&self, order: Ordering) -> *mut T { - #[cfg(not(bootstrap))] // SAFETY: data races are prevented by atomic intrinsics. - unsafe { - atomic_load(self.p.get(), order) - } - #[cfg(bootstrap)] - // SAFETY: data races are prevented by atomic intrinsics. - unsafe { - atomic_load(self.p.get() as *mut usize, order) as *mut T - } + unsafe { atomic_load(self.p.get(), order) } } /// Stores a value into the pointer. @@ -1027,16 +1019,10 @@ impl AtomicPtr { #[inline] #[stable(feature = "rust1", since = "1.0.0")] pub fn store(&self, ptr: *mut T, order: Ordering) { - #[cfg(not(bootstrap))] // SAFETY: data races are prevented by atomic intrinsics. unsafe { atomic_store(self.p.get(), ptr, order); } - #[cfg(bootstrap)] - // SAFETY: data races are prevented by atomic intrinsics. - unsafe { - atomic_store(self.p.get() as *mut usize, ptr as usize, order); - } } /// Stores a value into the pointer, returning the previous value. @@ -1065,16 +1051,8 @@ impl AtomicPtr { #[stable(feature = "rust1", since = "1.0.0")] #[cfg(target_has_atomic = "ptr")] pub fn swap(&self, ptr: *mut T, order: Ordering) -> *mut T { - #[cfg(bootstrap)] - // SAFETY: data races are prevented by atomic intrinsics. - unsafe { - atomic_swap(self.p.get() as *mut usize, ptr as usize, order) as *mut T - } - #[cfg(not(bootstrap))] // SAFETY: data races are prevented by atomic intrinsics. - unsafe { - atomic_swap(self.p.get(), ptr, order) - } + unsafe { atomic_swap(self.p.get(), ptr, order) } } /// Stores a value into the pointer if the current value is the same as the `current` value. @@ -1174,26 +1152,8 @@ impl AtomicPtr { success: Ordering, failure: Ordering, ) -> Result<*mut T, *mut T> { - #[cfg(bootstrap)] // SAFETY: data races are prevented by atomic intrinsics. - unsafe { - let res = atomic_compare_exchange( - self.p.get() as *mut usize, - current as usize, - new as usize, - success, - failure, - ); - match res { - Ok(x) => Ok(x as *mut T), - Err(x) => Err(x as *mut T), - } - } - #[cfg(not(bootstrap))] - // SAFETY: data races are prevented by atomic intrinsics. - unsafe { - atomic_compare_exchange(self.p.get(), current, new, success, failure) - } + unsafe { atomic_compare_exchange(self.p.get(), current, new, success, failure) } } /// Stores a value into the pointer if the current value is the same as the `current` value. @@ -1241,29 +1201,11 @@ impl AtomicPtr { success: Ordering, failure: Ordering, ) -> Result<*mut T, *mut T> { - #[cfg(bootstrap)] - // SAFETY: data races are prevented by atomic intrinsics. - unsafe { - let res = atomic_compare_exchange_weak( - self.p.get() as *mut usize, - current as usize, - new as usize, - success, - failure, - ); - match res { - Ok(x) => Ok(x as *mut T), - Err(x) => Err(x as *mut T), - } - } - #[cfg(not(bootstrap))] // SAFETY: This intrinsic is unsafe because it operates on a raw pointer // but we know for sure that the pointer is valid (we just got it from // an `UnsafeCell` that we have by reference) and the atomic operation // itself allows us to safely mutate the `UnsafeCell` contents. - unsafe { - atomic_compare_exchange_weak(self.p.get(), current, new, success, failure) - } + unsafe { atomic_compare_exchange_weak(self.p.get(), current, new, success, failure) } } /// Fetches the value, and applies a function to it that returns an optional diff --git a/library/core/tests/mem.rs b/library/core/tests/mem.rs index 5d0fedd4d9c..c9bafa9c77e 100644 --- a/library/core/tests/mem.rs +++ b/library/core/tests/mem.rs @@ -134,7 +134,6 @@ fn test_discriminant_send_sync() { } #[test] -#[cfg(not(bootstrap))] fn assume_init_good() { const TRUE: bool = unsafe { MaybeUninit::::new(true).assume_init() }; diff --git a/library/proc_macro/src/lib.rs b/library/proc_macro/src/lib.rs index ca40293ed58..a89e7b53e43 100644 --- a/library/proc_macro/src/lib.rs +++ b/library/proc_macro/src/lib.rs @@ -28,8 +28,7 @@ #![feature(extern_types)] #![feature(in_band_lifetimes)] #![feature(negative_impls)] -#![cfg_attr(bootstrap, feature(optin_builtin_traits))] -#![cfg_attr(not(bootstrap), feature(auto_traits))] +#![feature(auto_traits)] #![feature(restricted_std)] #![feature(rustc_attrs)] #![feature(min_specialization)] diff --git a/library/rtstartup/rsbegin.rs b/library/rtstartup/rsbegin.rs index b64f13dba4c..c6a4548ec0c 100644 --- a/library/rtstartup/rsbegin.rs +++ b/library/rtstartup/rsbegin.rs @@ -14,8 +14,7 @@ #![feature(no_core)] #![feature(lang_items)] -#![cfg_attr(bootstrap, feature(optin_builtin_traits))] -#![cfg_attr(not(bootstrap), feature(auto_traits))] +#![feature(auto_traits)] #![crate_type = "rlib"] #![no_core] #![allow(non_camel_case_types)] diff --git a/library/rtstartup/rsend.rs b/library/rtstartup/rsend.rs index 18ee7c19ba0..d5aca80edf9 100644 --- a/library/rtstartup/rsend.rs +++ b/library/rtstartup/rsend.rs @@ -2,8 +2,7 @@ #![feature(no_core)] #![feature(lang_items)] -#![cfg_attr(bootstrap, feature(optin_builtin_traits))] -#![cfg_attr(not(bootstrap), feature(auto_traits))] +#![feature(auto_traits)] #![crate_type = "rlib"] #![no_core] diff --git a/library/std/src/lib.rs b/library/std/src/lib.rs index 4126c8b714f..2c6f03fe224 100644 --- a/library/std/src/lib.rs +++ b/library/std/src/lib.rs @@ -289,8 +289,7 @@ #![feature(nll)] #![feature(nonnull_slice_from_raw_parts)] #![feature(once_cell)] -#![cfg_attr(bootstrap, feature(optin_builtin_traits))] -#![cfg_attr(not(bootstrap), feature(auto_traits))] +#![feature(auto_traits)] #![feature(or_patterns)] #![feature(panic_info_message)] #![feature(panic_internals)] diff --git a/library/std/src/macros.rs b/library/std/src/macros.rs index de072e83dfc..5a70aa070e8 100644 --- a/library/std/src/macros.rs +++ b/library/std/src/macros.rs @@ -8,7 +8,7 @@ #[macro_export] #[stable(feature = "rust1", since = "1.0.0")] #[allow_internal_unstable(libstd_sys_internals)] -#[cfg_attr(not(any(bootstrap, test)), rustc_diagnostic_item = "std_panic_macro")] +#[cfg_attr(not(test), rustc_diagnostic_item = "std_panic_macro")] macro_rules! panic { () => ({ $crate::panic!("explicit panic") }); ($msg:expr $(,)?) => ({ $crate::rt::begin_panic($msg) }); diff --git a/src/bootstrap/builder.rs b/src/bootstrap/builder.rs index c271608a6b6..c2abb01fa8c 100644 --- a/src/bootstrap/builder.rs +++ b/src/bootstrap/builder.rs @@ -736,10 +736,7 @@ impl<'a> Builder<'a> { if self.config.deny_warnings { cmd.arg("-Dwarnings"); } - // cfg(not(bootstrap)), can be removed on the next beta bump - if compiler.stage != 0 { - cmd.arg("-Znormalize-docs"); - } + cmd.arg("-Znormalize-docs"); // Remove make-related flags that can cause jobserver problems. cmd.env_remove("MAKEFLAGS"); diff --git a/src/bootstrap/doc.rs b/src/bootstrap/doc.rs index 2d60bb0a4bd..8c849846676 100644 --- a/src/bootstrap/doc.rs +++ b/src/bootstrap/doc.rs @@ -530,10 +530,7 @@ impl Step for Rustc { cargo.rustdocflag("--document-private-items"); cargo.rustdocflag("--enable-index-page"); cargo.rustdocflag("-Zunstable-options"); - // cfg(not(bootstrap)), can be removed on the next beta bump - if stage != 0 { - cargo.rustdocflag("-Znormalize-docs"); - } + cargo.rustdocflag("-Znormalize-docs"); compile::rustc_cargo(builder, &mut cargo, target); // Only include compiler crates, no dependencies of those, such as `libc`. diff --git a/src/stage0.txt b/src/stage0.txt index 6e05b66c3fe..e853b9b4e41 100644 --- a/src/stage0.txt +++ b/src/stage0.txt @@ -12,7 +12,7 @@ # stable release's version number. `date` is the date where the release we're # bootstrapping off was released. -date: 2020-11-18 +date: 2020-12-30 rustc: beta # We use a nightly rustfmt to format the source because it solves some -- cgit 1.4.1-3-g733a5 From 16834a8f52853be76cf4a96de120042f2a4a96a2 Mon Sep 17 00:00:00 2001 From: Mara Bos Date: Wed, 30 Dec 2020 15:35:02 +0000 Subject: Fix rustdoc link in vec/into_iter.rs. --- library/alloc/src/vec/into_iter.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'library/alloc/src') diff --git a/library/alloc/src/vec/into_iter.rs b/library/alloc/src/vec/into_iter.rs index 99ecec648ad..f131d06bb18 100644 --- a/library/alloc/src/vec/into_iter.rs +++ b/library/alloc/src/vec/into_iter.rs @@ -10,8 +10,8 @@ use core::slice::{self}; /// An iterator that moves out of a vector. /// -/// This `struct` is created by the `into_iter` method on [`super::Vec`] (provided -/// by the [`IntoIterator`] trait). +/// This `struct` is created by the `into_iter` method on [`Vec`](super::Vec) +/// (provided by the [`IntoIterator`] trait). /// /// # Example /// -- cgit 1.4.1-3-g733a5 From 8b53be660444d736bb6a6e1c6ba42c8180c968e7 Mon Sep 17 00:00:00 2001 From: Clément Renault Date: Thu, 31 Dec 2020 12:13:03 +0100 Subject: Replace the tracking issue for the slice_group_by feature --- library/alloc/src/slice.rs | 2 +- library/core/src/slice/iter.rs | 24 ++++++++++++------------ library/core/src/slice/mod.rs | 6 +++--- 3 files changed, 16 insertions(+), 16 deletions(-) (limited to 'library/alloc/src') diff --git a/library/alloc/src/slice.rs b/library/alloc/src/slice.rs index 72da781da3c..cb015b94930 100644 --- a/library/alloc/src/slice.rs +++ b/library/alloc/src/slice.rs @@ -110,7 +110,7 @@ pub use core::slice::{Chunks, Windows}; pub use core::slice::{ChunksExact, ChunksExactMut}; #[stable(feature = "rust1", since = "1.0.0")] pub use core::slice::{ChunksMut, Split, SplitMut}; -#[unstable(feature = "slice_group_by", issue = "none")] +#[unstable(feature = "slice_group_by", issue = "80552")] pub use core::slice::{GroupBy, GroupByMut}; #[stable(feature = "rust1", since = "1.0.0")] pub use core::slice::{Iter, IterMut}; diff --git a/library/core/src/slice/iter.rs b/library/core/src/slice/iter.rs index 6bb9cf99402..a367b4737db 100644 --- a/library/core/src/slice/iter.rs +++ b/library/core/src/slice/iter.rs @@ -2975,20 +2975,20 @@ unsafe impl<'a, T> TrustedRandomAccess for IterMut<'a, T> { /// /// [`group_by`]: ../../std/primitive.slice.html#method.group_by /// [slices]: ../../std/primitive.slice.html -#[unstable(feature = "slice_group_by", issue = "none")] +#[unstable(feature = "slice_group_by", issue = "80552")] pub struct GroupBy<'a, T: 'a, P> { slice: &'a [T], predicate: P, } -#[unstable(feature = "slice_group_by", issue = "none")] +#[unstable(feature = "slice_group_by", issue = "80552")] impl<'a, T: 'a, P> GroupBy<'a, T, P> { pub(super) fn new(slice: &'a [T], predicate: P) -> Self { GroupBy { slice, predicate } } } -#[unstable(feature = "slice_group_by", issue = "none")] +#[unstable(feature = "slice_group_by", issue = "80552")] impl<'a, T: 'a, P> Iterator for GroupBy<'a, T, P> where P: FnMut(&T, &T) -> bool, @@ -3022,7 +3022,7 @@ where } } -#[unstable(feature = "slice_group_by", issue = "none")] +#[unstable(feature = "slice_group_by", issue = "80552")] impl<'a, T: 'a, P> DoubleEndedIterator for GroupBy<'a, T, P> where P: FnMut(&T, &T) -> bool, @@ -3044,10 +3044,10 @@ where } } -#[unstable(feature = "slice_group_by", issue = "none")] +#[unstable(feature = "slice_group_by", issue = "80552")] impl<'a, T: 'a, P> FusedIterator for GroupBy<'a, T, P> where P: FnMut(&T, &T) -> bool {} -#[unstable(feature = "slice_group_by", issue = "none")] +#[unstable(feature = "slice_group_by", issue = "80552")] impl<'a, T: 'a + fmt::Debug, P> fmt::Debug for GroupBy<'a, T, P> { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { f.debug_struct("GroupBy").field("slice", &self.slice).finish() @@ -3061,20 +3061,20 @@ impl<'a, T: 'a + fmt::Debug, P> fmt::Debug for GroupBy<'a, T, P> { /// /// [`group_by_mut`]: ../../std/primitive.slice.html#method.group_by_mut /// [slices]: ../../std/primitive.slice.html -#[unstable(feature = "slice_group_by", issue = "none")] +#[unstable(feature = "slice_group_by", issue = "80552")] pub struct GroupByMut<'a, T: 'a, P> { slice: &'a mut [T], predicate: P, } -#[unstable(feature = "slice_group_by", issue = "none")] +#[unstable(feature = "slice_group_by", issue = "80552")] impl<'a, T: 'a, P> GroupByMut<'a, T, P> { pub(super) fn new(slice: &'a mut [T], predicate: P) -> Self { GroupByMut { slice, predicate } } } -#[unstable(feature = "slice_group_by", issue = "none")] +#[unstable(feature = "slice_group_by", issue = "80552")] impl<'a, T: 'a, P> Iterator for GroupByMut<'a, T, P> where P: FnMut(&T, &T) -> bool, @@ -3109,7 +3109,7 @@ where } } -#[unstable(feature = "slice_group_by", issue = "none")] +#[unstable(feature = "slice_group_by", issue = "80552")] impl<'a, T: 'a, P> DoubleEndedIterator for GroupByMut<'a, T, P> where P: FnMut(&T, &T) -> bool, @@ -3132,10 +3132,10 @@ where } } -#[unstable(feature = "slice_group_by", issue = "none")] +#[unstable(feature = "slice_group_by", issue = "80552")] impl<'a, T: 'a, P> FusedIterator for GroupByMut<'a, T, P> where P: FnMut(&T, &T) -> bool {} -#[unstable(feature = "slice_group_by", issue = "none")] +#[unstable(feature = "slice_group_by", issue = "80552")] impl<'a, T: 'a + fmt::Debug, P> fmt::Debug for GroupByMut<'a, T, P> { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { f.debug_struct("GroupByMut").field("slice", &self.slice).finish() diff --git a/library/core/src/slice/mod.rs b/library/core/src/slice/mod.rs index b4dd057eef0..b1332a3f7bc 100644 --- a/library/core/src/slice/mod.rs +++ b/library/core/src/slice/mod.rs @@ -57,7 +57,7 @@ pub use iter::{ArrayChunks, ArrayChunksMut}; #[unstable(feature = "array_windows", issue = "75027")] pub use iter::ArrayWindows; -#[unstable(feature = "slice_group_by", issue = "none")] +#[unstable(feature = "slice_group_by", issue = "80552")] pub use iter::{GroupBy, GroupByMut}; #[unstable(feature = "split_inclusive", issue = "72360")] @@ -1246,7 +1246,7 @@ impl [T] { /// assert_eq!(iter.next(), Some(&[2, 3, 4][..])); /// assert_eq!(iter.next(), None); /// ``` - #[unstable(feature = "slice_group_by", issue = "none")] + #[unstable(feature = "slice_group_by", issue = "80552")] #[inline] pub fn group_by(&self, pred: F) -> GroupBy<'_, T, F> where @@ -1291,7 +1291,7 @@ impl [T] { /// assert_eq!(iter.next(), Some(&mut [2, 3, 4][..])); /// assert_eq!(iter.next(), None); /// ``` - #[unstable(feature = "slice_group_by", issue = "none")] + #[unstable(feature = "slice_group_by", issue = "80552")] #[inline] pub fn group_by_mut(&mut self, pred: F) -> GroupByMut<'_, T, F> where -- cgit 1.4.1-3-g733a5