Skip to content

Commit 242a252

Browse files
authored
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.
2 parents 507bff9 + 16834a8 commit 242a252

19 files changed

+1378
-1272
lines changed

library/alloc/src/vec/cow.rs

+35
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
use crate::borrow::Cow;
2+
use core::iter::FromIterator;
3+
4+
use super::Vec;
5+
6+
#[stable(feature = "cow_from_vec", since = "1.8.0")]
7+
impl<'a, T: Clone> From<&'a [T]> for Cow<'a, [T]> {
8+
fn from(s: &'a [T]) -> Cow<'a, [T]> {
9+
Cow::Borrowed(s)
10+
}
11+
}
12+
13+
#[stable(feature = "cow_from_vec", since = "1.8.0")]
14+
impl<'a, T: Clone> From<Vec<T>> for Cow<'a, [T]> {
15+
fn from(v: Vec<T>) -> Cow<'a, [T]> {
16+
Cow::Owned(v)
17+
}
18+
}
19+
20+
#[stable(feature = "cow_from_vec_ref", since = "1.28.0")]
21+
impl<'a, T: Clone> From<&'a Vec<T>> for Cow<'a, [T]> {
22+
fn from(v: &'a Vec<T>) -> Cow<'a, [T]> {
23+
Cow::Borrowed(v.as_slice())
24+
}
25+
}
26+
27+
#[stable(feature = "rust1", since = "1.0.0")]
28+
impl<'a, T> FromIterator<T> for Cow<'a, [T]>
29+
where
30+
T: Clone,
31+
{
32+
fn from_iter<I: IntoIterator<Item = T>>(it: I) -> Cow<'a, [T]> {
33+
Cow::Owned(FromIterator::from_iter(it))
34+
}
35+
}

library/alloc/src/vec/drain.rs

+155
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,155 @@
1+
use crate::alloc::{Allocator, Global};
2+
use core::fmt;
3+
use core::iter::{FusedIterator, TrustedLen};
4+
use core::mem::{self};
5+
use core::ptr::{self, NonNull};
6+
use core::slice::{self};
7+
8+
use super::Vec;
9+
10+
/// A draining iterator for `Vec<T>`.
11+
///
12+
/// This `struct` is created by [`Vec::drain`].
13+
/// See its documentation for more.
14+
///
15+
/// # Example
16+
///
17+
/// ```
18+
/// let mut v = vec![0, 1, 2];
19+
/// let iter: std::vec::Drain<_> = v.drain(..);
20+
/// ```
21+
#[stable(feature = "drain", since = "1.6.0")]
22+
pub struct Drain<
23+
'a,
24+
T: 'a,
25+
#[unstable(feature = "allocator_api", issue = "32838")] A: Allocator + 'a = Global,
26+
> {
27+
/// Index of tail to preserve
28+
pub(super) tail_start: usize,
29+
/// Length of tail
30+
pub(super) tail_len: usize,
31+
/// Current remaining range to remove
32+
pub(super) iter: slice::Iter<'a, T>,
33+
pub(super) vec: NonNull<Vec<T, A>>,
34+
}
35+
36+
#[stable(feature = "collection_debug", since = "1.17.0")]
37+
impl<T: fmt::Debug, A: Allocator> fmt::Debug for Drain<'_, T, A> {
38+
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
39+
f.debug_tuple("Drain").field(&self.iter.as_slice()).finish()
40+
}
41+
}
42+
43+
impl<'a, T, A: Allocator> Drain<'a, T, A> {
44+
/// Returns the remaining items of this iterator as a slice.
45+
///
46+
/// # Examples
47+
///
48+
/// ```
49+
/// let mut vec = vec!['a', 'b', 'c'];
50+
/// let mut drain = vec.drain(..);
51+
/// assert_eq!(drain.as_slice(), &['a', 'b', 'c']);
52+
/// let _ = drain.next().unwrap();
53+
/// assert_eq!(drain.as_slice(), &['b', 'c']);
54+
/// ```
55+
#[stable(feature = "vec_drain_as_slice", since = "1.46.0")]
56+
pub fn as_slice(&self) -> &[T] {
57+
self.iter.as_slice()
58+
}
59+
60+
/// Returns a reference to the underlying allocator.
61+
#[unstable(feature = "allocator_api", issue = "32838")]
62+
#[inline]
63+
pub fn allocator(&self) -> &A {
64+
unsafe { self.vec.as_ref().allocator() }
65+
}
66+
}
67+
68+
#[stable(feature = "vec_drain_as_slice", since = "1.46.0")]
69+
impl<'a, T, A: Allocator> AsRef<[T]> for Drain<'a, T, A> {
70+
fn as_ref(&self) -> &[T] {
71+
self.as_slice()
72+
}
73+
}
74+
75+
#[stable(feature = "drain", since = "1.6.0")]
76+
unsafe impl<T: Sync, A: Sync + Allocator> Sync for Drain<'_, T, A> {}
77+
#[stable(feature = "drain", since = "1.6.0")]
78+
unsafe impl<T: Send, A: Send + Allocator> Send for Drain<'_, T, A> {}
79+
80+
#[stable(feature = "drain", since = "1.6.0")]
81+
impl<T, A: Allocator> Iterator for Drain<'_, T, A> {
82+
type Item = T;
83+
84+
#[inline]
85+
fn next(&mut self) -> Option<T> {
86+
self.iter.next().map(|elt| unsafe { ptr::read(elt as *const _) })
87+
}
88+
89+
fn size_hint(&self) -> (usize, Option<usize>) {
90+
self.iter.size_hint()
91+
}
92+
}
93+
94+
#[stable(feature = "drain", since = "1.6.0")]
95+
impl<T, A: Allocator> DoubleEndedIterator for Drain<'_, T, A> {
96+
#[inline]
97+
fn next_back(&mut self) -> Option<T> {
98+
self.iter.next_back().map(|elt| unsafe { ptr::read(elt as *const _) })
99+
}
100+
}
101+
102+
#[stable(feature = "drain", since = "1.6.0")]
103+
impl<T, A: Allocator> Drop for Drain<'_, T, A> {
104+
fn drop(&mut self) {
105+
/// Continues dropping the remaining elements in the `Drain`, then moves back the
106+
/// un-`Drain`ed elements to restore the original `Vec`.
107+
struct DropGuard<'r, 'a, T, A: Allocator>(&'r mut Drain<'a, T, A>);
108+
109+
impl<'r, 'a, T, A: Allocator> Drop for DropGuard<'r, 'a, T, A> {
110+
fn drop(&mut self) {
111+
// Continue the same loop we have below. If the loop already finished, this does
112+
// nothing.
113+
self.0.for_each(drop);
114+
115+
if self.0.tail_len > 0 {
116+
unsafe {
117+
let source_vec = self.0.vec.as_mut();
118+
// memmove back untouched tail, update to new length
119+
let start = source_vec.len();
120+
let tail = self.0.tail_start;
121+
if tail != start {
122+
let src = source_vec.as_ptr().add(tail);
123+
let dst = source_vec.as_mut_ptr().add(start);
124+
ptr::copy(src, dst, self.0.tail_len);
125+
}
126+
source_vec.set_len(start + self.0.tail_len);
127+
}
128+
}
129+
}
130+
}
131+
132+
// exhaust self first
133+
while let Some(item) = self.next() {
134+
let guard = DropGuard(self);
135+
drop(item);
136+
mem::forget(guard);
137+
}
138+
139+
// Drop a `DropGuard` to move back the non-drained tail of `self`.
140+
DropGuard(self);
141+
}
142+
}
143+
144+
#[stable(feature = "drain", since = "1.6.0")]
145+
impl<T, A: Allocator> ExactSizeIterator for Drain<'_, T, A> {
146+
fn is_empty(&self) -> bool {
147+
self.iter.is_empty()
148+
}
149+
}
150+
151+
#[unstable(feature = "trusted_len", issue = "37572")]
152+
unsafe impl<T, A: Allocator> TrustedLen for Drain<'_, T, A> {}
153+
154+
#[stable(feature = "fused", since = "1.26.0")]
155+
impl<T, A: Allocator> FusedIterator for Drain<'_, T, A> {}

library/alloc/src/vec/drain_filter.rs

+143
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,143 @@
1+
use crate::alloc::{Allocator, Global};
2+
use core::ptr::{self};
3+
use core::slice::{self};
4+
5+
use super::Vec;
6+
7+
/// An iterator which uses a closure to determine if an element should be removed.
8+
///
9+
/// This struct is created by [`Vec::drain_filter`].
10+
/// See its documentation for more.
11+
///
12+
/// # Example
13+
///
14+
/// ```
15+
/// #![feature(drain_filter)]
16+
///
17+
/// let mut v = vec![0, 1, 2];
18+
/// let iter: std::vec::DrainFilter<_, _> = v.drain_filter(|x| *x % 2 == 0);
19+
/// ```
20+
#[unstable(feature = "drain_filter", reason = "recently added", issue = "43244")]
21+
#[derive(Debug)]
22+
pub struct DrainFilter<
23+
'a,
24+
T,
25+
F,
26+
#[unstable(feature = "allocator_api", issue = "32838")] A: Allocator = Global,
27+
> where
28+
F: FnMut(&mut T) -> bool,
29+
{
30+
pub(super) vec: &'a mut Vec<T, A>,
31+
/// The index of the item that will be inspected by the next call to `next`.
32+
pub(super) idx: usize,
33+
/// The number of items that have been drained (removed) thus far.
34+
pub(super) del: usize,
35+
/// The original length of `vec` prior to draining.
36+
pub(super) old_len: usize,
37+
/// The filter test predicate.
38+
pub(super) pred: F,
39+
/// A flag that indicates a panic has occurred in the filter test predicate.
40+
/// This is used as a hint in the drop implementation to prevent consumption
41+
/// of the remainder of the `DrainFilter`. Any unprocessed items will be
42+
/// backshifted in the `vec`, but no further items will be dropped or
43+
/// tested by the filter predicate.
44+
pub(super) panic_flag: bool,
45+
}
46+
47+
impl<T, F, A: Allocator> DrainFilter<'_, T, F, A>
48+
where
49+
F: FnMut(&mut T) -> bool,
50+
{
51+
/// Returns a reference to the underlying allocator.
52+
#[unstable(feature = "allocator_api", issue = "32838")]
53+
#[inline]
54+
pub fn allocator(&self) -> &A {
55+
self.vec.allocator()
56+
}
57+
}
58+
59+
#[unstable(feature = "drain_filter", reason = "recently added", issue = "43244")]
60+
impl<T, F, A: Allocator> Iterator for DrainFilter<'_, T, F, A>
61+
where
62+
F: FnMut(&mut T) -> bool,
63+
{
64+
type Item = T;
65+
66+
fn next(&mut self) -> Option<T> {
67+
unsafe {
68+
while self.idx < self.old_len {
69+
let i = self.idx;
70+
let v = slice::from_raw_parts_mut(self.vec.as_mut_ptr(), self.old_len);
71+
self.panic_flag = true;
72+
let drained = (self.pred)(&mut v[i]);
73+
self.panic_flag = false;
74+
// Update the index *after* the predicate is called. If the index
75+
// is updated prior and the predicate panics, the element at this
76+
// index would be leaked.
77+
self.idx += 1;
78+
if drained {
79+
self.del += 1;
80+
return Some(ptr::read(&v[i]));
81+
} else if self.del > 0 {
82+
let del = self.del;
83+
let src: *const T = &v[i];
84+
let dst: *mut T = &mut v[i - del];
85+
ptr::copy_nonoverlapping(src, dst, 1);
86+
}
87+
}
88+
None
89+
}
90+
}
91+
92+
fn size_hint(&self) -> (usize, Option<usize>) {
93+
(0, Some(self.old_len - self.idx))
94+
}
95+
}
96+
97+
#[unstable(feature = "drain_filter", reason = "recently added", issue = "43244")]
98+
impl<T, F, A: Allocator> Drop for DrainFilter<'_, T, F, A>
99+
where
100+
F: FnMut(&mut T) -> bool,
101+
{
102+
fn drop(&mut self) {
103+
struct BackshiftOnDrop<'a, 'b, T, F, A: Allocator>
104+
where
105+
F: FnMut(&mut T) -> bool,
106+
{
107+
drain: &'b mut DrainFilter<'a, T, F, A>,
108+
}
109+
110+
impl<'a, 'b, T, F, A: Allocator> Drop for BackshiftOnDrop<'a, 'b, T, F, A>
111+
where
112+
F: FnMut(&mut T) -> bool,
113+
{
114+
fn drop(&mut self) {
115+
unsafe {
116+
if self.drain.idx < self.drain.old_len && self.drain.del > 0 {
117+
// This is a pretty messed up state, and there isn't really an
118+
// obviously right thing to do. We don't want to keep trying
119+
// to execute `pred`, so we just backshift all the unprocessed
120+
// elements and tell the vec that they still exist. The backshift
121+
// is required to prevent a double-drop of the last successfully
122+
// drained item prior to a panic in the predicate.
123+
let ptr = self.drain.vec.as_mut_ptr();
124+
let src = ptr.add(self.drain.idx);
125+
let dst = src.sub(self.drain.del);
126+
let tail_len = self.drain.old_len - self.drain.idx;
127+
src.copy_to(dst, tail_len);
128+
}
129+
self.drain.vec.set_len(self.drain.old_len - self.drain.del);
130+
}
131+
}
132+
}
133+
134+
let backshift = BackshiftOnDrop { drain: self };
135+
136+
// Attempt to consume any remaining elements if the filter predicate
137+
// has not yet panicked. We'll backshift any remaining elements
138+
// whether we've already panicked or if the consumption here panics.
139+
if !backshift.drain.panic_flag {
140+
backshift.drain.for_each(drop);
141+
}
142+
}
143+
}
+24
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
use core::ptr::{self};
2+
use core::slice::{self};
3+
4+
// A helper struct for in-place iteration that drops the destination slice of iteration,
5+
// i.e. the head. The source slice (the tail) is dropped by IntoIter.
6+
pub(super) struct InPlaceDrop<T> {
7+
pub(super) inner: *mut T,
8+
pub(super) dst: *mut T,
9+
}
10+
11+
impl<T> InPlaceDrop<T> {
12+
fn len(&self) -> usize {
13+
unsafe { self.dst.offset_from(self.inner) as usize }
14+
}
15+
}
16+
17+
impl<T> Drop for InPlaceDrop<T> {
18+
#[inline]
19+
fn drop(&mut self) {
20+
unsafe {
21+
ptr::drop_in_place(slice::from_raw_parts_mut(self.inner, self.len()));
22+
}
23+
}
24+
}

0 commit comments

Comments
 (0)