forked from rust-lang/rust
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Rollup merge of rust-lang#78934 - DeveloperC286:issue_60302_vec, r=m-…
…ou-se refactor: removing library/alloc/src/vec/mod.rs ignore-tidy-filelength This PR removes the need for ignore-tidy-filelength for library/alloc/src/vec/mod.rs which is part of the issue rust-lang#60302 It is probably easiest to review this PR by looking at it commit by commit rather than looking at the overall diff.
- Loading branch information
Showing
19 changed files
with
1,378 additions
and
1,272 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -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<Vec<T>> for Cow<'a, [T]> { | ||
fn from(v: Vec<T>) -> Cow<'a, [T]> { | ||
Cow::Owned(v) | ||
} | ||
} | ||
|
||
#[stable(feature = "cow_from_vec_ref", since = "1.28.0")] | ||
impl<'a, T: Clone> From<&'a Vec<T>> for Cow<'a, [T]> { | ||
fn from(v: &'a Vec<T>) -> Cow<'a, [T]> { | ||
Cow::Borrowed(v.as_slice()) | ||
} | ||
} | ||
|
||
#[stable(feature = "rust1", since = "1.0.0")] | ||
impl<'a, T> FromIterator<T> for Cow<'a, [T]> | ||
where | ||
T: Clone, | ||
{ | ||
fn from_iter<I: IntoIterator<Item = T>>(it: I) -> Cow<'a, [T]> { | ||
Cow::Owned(FromIterator::from_iter(it)) | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,155 @@ | ||
use crate::alloc::{Allocator, Global}; | ||
use core::fmt; | ||
use core::iter::{FusedIterator, TrustedLen}; | ||
use core::mem::{self}; | ||
use core::ptr::{self, NonNull}; | ||
use core::slice::{self}; | ||
|
||
use super::Vec; | ||
|
||
/// A draining iterator for `Vec<T>`. | ||
/// | ||
/// 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<Vec<T, A>>, | ||
} | ||
|
||
#[stable(feature = "collection_debug", since = "1.17.0")] | ||
impl<T: fmt::Debug, A: Allocator> 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<T: Sync, A: Sync + Allocator> Sync for Drain<'_, T, A> {} | ||
#[stable(feature = "drain", since = "1.6.0")] | ||
unsafe impl<T: Send, A: Send + Allocator> Send for Drain<'_, T, A> {} | ||
|
||
#[stable(feature = "drain", since = "1.6.0")] | ||
impl<T, A: Allocator> Iterator for Drain<'_, T, A> { | ||
type Item = T; | ||
|
||
#[inline] | ||
fn next(&mut self) -> Option<T> { | ||
self.iter.next().map(|elt| unsafe { ptr::read(elt as *const _) }) | ||
} | ||
|
||
fn size_hint(&self) -> (usize, Option<usize>) { | ||
self.iter.size_hint() | ||
} | ||
} | ||
|
||
#[stable(feature = "drain", since = "1.6.0")] | ||
impl<T, A: Allocator> DoubleEndedIterator for Drain<'_, T, A> { | ||
#[inline] | ||
fn next_back(&mut self) -> Option<T> { | ||
self.iter.next_back().map(|elt| unsafe { ptr::read(elt as *const _) }) | ||
} | ||
} | ||
|
||
#[stable(feature = "drain", since = "1.6.0")] | ||
impl<T, A: Allocator> 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<T, A: Allocator> ExactSizeIterator for Drain<'_, T, A> { | ||
fn is_empty(&self) -> bool { | ||
self.iter.is_empty() | ||
} | ||
} | ||
|
||
#[unstable(feature = "trusted_len", issue = "37572")] | ||
unsafe impl<T, A: Allocator> TrustedLen for Drain<'_, T, A> {} | ||
|
||
#[stable(feature = "fused", since = "1.26.0")] | ||
impl<T, A: Allocator> FusedIterator for Drain<'_, T, A> {} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,143 @@ | ||
use crate::alloc::{Allocator, Global}; | ||
use core::ptr::{self}; | ||
use core::slice::{self}; | ||
|
||
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<T, A>, | ||
/// 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<T, F, A: Allocator> 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<T, F, A: Allocator> Iterator for DrainFilter<'_, T, F, A> | ||
where | ||
F: FnMut(&mut T) -> bool, | ||
{ | ||
type Item = T; | ||
|
||
fn next(&mut self) -> Option<T> { | ||
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<usize>) { | ||
(0, Some(self.old_len - self.idx)) | ||
} | ||
} | ||
|
||
#[unstable(feature = "drain_filter", reason = "recently added", issue = "43244")] | ||
impl<T, F, A: Allocator> 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); | ||
} | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -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<T> { | ||
pub(super) inner: *mut T, | ||
pub(super) dst: *mut T, | ||
} | ||
|
||
impl<T> InPlaceDrop<T> { | ||
fn len(&self) -> usize { | ||
unsafe { self.dst.offset_from(self.inner) as usize } | ||
} | ||
} | ||
|
||
impl<T> Drop for InPlaceDrop<T> { | ||
#[inline] | ||
fn drop(&mut self) { | ||
unsafe { | ||
ptr::drop_in_place(slice::from_raw_parts_mut(self.inner, self.len())); | ||
} | ||
} | ||
} |
Oops, something went wrong.