Rollup merge of #133265 - the8472:extract-if-ranges, r=cuviper
Add a range argument to vec.extract_if tracking issue: #43244 This adds the range argument requested in https://github.com/rust-lang/rust/issues/43244#issuecomment-2486160659
This commit is contained in:
commit
938742e687
11 changed files with 105 additions and 72 deletions
|
@ -1569,18 +1569,18 @@ impl DiagCtxtInner {
|
||||||
debug!(?diagnostic);
|
debug!(?diagnostic);
|
||||||
debug!(?self.emitted_diagnostics);
|
debug!(?self.emitted_diagnostics);
|
||||||
|
|
||||||
let already_emitted_sub = |sub: &mut Subdiag| {
|
let not_yet_emitted = |sub: &mut Subdiag| {
|
||||||
debug!(?sub);
|
debug!(?sub);
|
||||||
if sub.level != OnceNote && sub.level != OnceHelp {
|
if sub.level != OnceNote && sub.level != OnceHelp {
|
||||||
return false;
|
return true;
|
||||||
}
|
}
|
||||||
let mut hasher = StableHasher::new();
|
let mut hasher = StableHasher::new();
|
||||||
sub.hash(&mut hasher);
|
sub.hash(&mut hasher);
|
||||||
let diagnostic_hash = hasher.finish();
|
let diagnostic_hash = hasher.finish();
|
||||||
debug!(?diagnostic_hash);
|
debug!(?diagnostic_hash);
|
||||||
!self.emitted_diagnostics.insert(diagnostic_hash)
|
self.emitted_diagnostics.insert(diagnostic_hash)
|
||||||
};
|
};
|
||||||
diagnostic.children.extract_if(already_emitted_sub).for_each(|_| {});
|
diagnostic.children.retain_mut(not_yet_emitted);
|
||||||
if already_emitted {
|
if already_emitted {
|
||||||
let msg = "duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`";
|
let msg = "duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`";
|
||||||
diagnostic.sub(Note, msg, MultiSpan::new());
|
diagnostic.sub(Note, msg, MultiSpan::new());
|
||||||
|
|
|
@ -205,7 +205,7 @@ impl EarlyLintPass for NonAsciiIdents {
|
||||||
(IdentifierType::Not_NFKC, "Not_NFKC"),
|
(IdentifierType::Not_NFKC, "Not_NFKC"),
|
||||||
] {
|
] {
|
||||||
let codepoints: Vec<_> =
|
let codepoints: Vec<_> =
|
||||||
chars.extract_if(|(_, ty)| *ty == Some(id_ty)).collect();
|
chars.extract_if(.., |(_, ty)| *ty == Some(id_ty)).collect();
|
||||||
if codepoints.is_empty() {
|
if codepoints.is_empty() {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
@ -217,7 +217,7 @@ impl EarlyLintPass for NonAsciiIdents {
|
||||||
}
|
}
|
||||||
|
|
||||||
let remaining = chars
|
let remaining = chars
|
||||||
.extract_if(|(c, _)| !GeneralSecurityProfile::identifier_allowed(*c))
|
.extract_if(.., |(c, _)| !GeneralSecurityProfile::identifier_allowed(*c))
|
||||||
.collect::<Vec<_>>();
|
.collect::<Vec<_>>();
|
||||||
if !remaining.is_empty() {
|
if !remaining.is_empty() {
|
||||||
cx.emit_span_lint(UNCOMMON_CODEPOINTS, sp, IdentifierUncommonCodepoints {
|
cx.emit_span_lint(UNCOMMON_CODEPOINTS, sp, IdentifierUncommonCodepoints {
|
||||||
|
|
|
@ -544,7 +544,7 @@ impl<'tcx> Collector<'tcx> {
|
||||||
// can move them to the end of the list below.
|
// can move them to the end of the list below.
|
||||||
let mut existing = self
|
let mut existing = self
|
||||||
.libs
|
.libs
|
||||||
.extract_if(|lib| {
|
.extract_if(.., |lib| {
|
||||||
if lib.name.as_str() == passed_lib.name {
|
if lib.name.as_str() == passed_lib.name {
|
||||||
// FIXME: This whole logic is questionable, whether modifiers are
|
// FIXME: This whole logic is questionable, whether modifiers are
|
||||||
// involved or not, library reordering and kind overriding without
|
// involved or not, library reordering and kind overriding without
|
||||||
|
|
|
@ -309,7 +309,7 @@ pub fn suggest_constraining_type_params<'a>(
|
||||||
let Some(param) = param else { return false };
|
let Some(param) = param else { return false };
|
||||||
|
|
||||||
{
|
{
|
||||||
let mut sized_constraints = constraints.extract_if(|(_, def_id, _)| {
|
let mut sized_constraints = constraints.extract_if(.., |(_, def_id, _)| {
|
||||||
def_id.is_some_and(|def_id| tcx.is_lang_item(def_id, LangItem::Sized))
|
def_id.is_some_and(|def_id| tcx.is_lang_item(def_id, LangItem::Sized))
|
||||||
});
|
});
|
||||||
if let Some((_, def_id, _)) = sized_constraints.next() {
|
if let Some((_, def_id, _)) = sized_constraints.next() {
|
||||||
|
|
|
@ -2817,11 +2817,11 @@ fn show_candidates(
|
||||||
path_strings.sort_by(|a, b| a.0.cmp(&b.0));
|
path_strings.sort_by(|a, b| a.0.cmp(&b.0));
|
||||||
path_strings.dedup_by(|a, b| a.0 == b.0);
|
path_strings.dedup_by(|a, b| a.0 == b.0);
|
||||||
let core_path_strings =
|
let core_path_strings =
|
||||||
path_strings.extract_if(|p| p.0.starts_with("core::")).collect::<Vec<_>>();
|
path_strings.extract_if(.., |p| p.0.starts_with("core::")).collect::<Vec<_>>();
|
||||||
let std_path_strings =
|
let std_path_strings =
|
||||||
path_strings.extract_if(|p| p.0.starts_with("std::")).collect::<Vec<_>>();
|
path_strings.extract_if(.., |p| p.0.starts_with("std::")).collect::<Vec<_>>();
|
||||||
let foreign_crate_path_strings =
|
let foreign_crate_path_strings =
|
||||||
path_strings.extract_if(|p| !p.0.starts_with("crate::")).collect::<Vec<_>>();
|
path_strings.extract_if(.., |p| !p.0.starts_with("crate::")).collect::<Vec<_>>();
|
||||||
|
|
||||||
// We list the `crate` local paths first.
|
// We list the `crate` local paths first.
|
||||||
// Then we list the `std`/`core` paths.
|
// Then we list the `std`/`core` paths.
|
||||||
|
|
|
@ -629,7 +629,7 @@ impl<'ast, 'ra: 'ast, 'tcx> LateResolutionVisitor<'_, 'ast, 'ra, 'tcx> {
|
||||||
// Try to filter out intrinsics candidates, as long as we have
|
// Try to filter out intrinsics candidates, as long as we have
|
||||||
// some other candidates to suggest.
|
// some other candidates to suggest.
|
||||||
let intrinsic_candidates: Vec<_> = candidates
|
let intrinsic_candidates: Vec<_> = candidates
|
||||||
.extract_if(|sugg| {
|
.extract_if(.., |sugg| {
|
||||||
let path = path_names_to_string(&sugg.path);
|
let path = path_names_to_string(&sugg.path);
|
||||||
path.starts_with("core::intrinsics::") || path.starts_with("std::intrinsics::")
|
path.starts_with("core::intrinsics::") || path.starts_with("std::intrinsics::")
|
||||||
})
|
})
|
||||||
|
|
|
@ -447,7 +447,7 @@ pub fn normalize_param_env_or_error<'tcx>(
|
||||||
// This works fairly well because trait matching does not actually care about param-env
|
// This works fairly well because trait matching does not actually care about param-env
|
||||||
// TypeOutlives predicates - these are normally used by regionck.
|
// TypeOutlives predicates - these are normally used by regionck.
|
||||||
let outlives_predicates: Vec<_> = predicates
|
let outlives_predicates: Vec<_> = predicates
|
||||||
.extract_if(|predicate| {
|
.extract_if(.., |predicate| {
|
||||||
matches!(predicate.kind().skip_binder(), ty::ClauseKind::TypeOutlives(..))
|
matches!(predicate.kind().skip_binder(), ty::ClauseKind::TypeOutlives(..))
|
||||||
})
|
})
|
||||||
.collect();
|
.collect();
|
||||||
|
|
|
@ -1939,9 +1939,7 @@ pub struct ExtractIf<
|
||||||
T: 'a,
|
T: 'a,
|
||||||
F: 'a,
|
F: 'a,
|
||||||
#[unstable(feature = "allocator_api", issue = "32838")] A: Allocator = Global,
|
#[unstable(feature = "allocator_api", issue = "32838")] A: Allocator = Global,
|
||||||
> where
|
> {
|
||||||
F: FnMut(&mut T) -> bool,
|
|
||||||
{
|
|
||||||
list: &'a mut LinkedList<T, A>,
|
list: &'a mut LinkedList<T, A>,
|
||||||
it: Option<NonNull<Node<T>>>,
|
it: Option<NonNull<Node<T>>>,
|
||||||
pred: F,
|
pred: F,
|
||||||
|
@ -1979,10 +1977,7 @@ where
|
||||||
}
|
}
|
||||||
|
|
||||||
#[unstable(feature = "extract_if", reason = "recently added", issue = "43244")]
|
#[unstable(feature = "extract_if", reason = "recently added", issue = "43244")]
|
||||||
impl<T: fmt::Debug, F> fmt::Debug for ExtractIf<'_, T, F>
|
impl<T: fmt::Debug, F> fmt::Debug for ExtractIf<'_, T, F> {
|
||||||
where
|
|
||||||
F: FnMut(&mut T) -> bool,
|
|
||||||
{
|
|
||||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||||
f.debug_tuple("ExtractIf").field(&self.list).finish()
|
f.debug_tuple("ExtractIf").field(&self.list).finish()
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,3 +1,4 @@
|
||||||
|
use core::ops::{Range, RangeBounds};
|
||||||
use core::{ptr, slice};
|
use core::{ptr, slice};
|
||||||
|
|
||||||
use super::Vec;
|
use super::Vec;
|
||||||
|
@ -14,7 +15,7 @@ use crate::alloc::{Allocator, Global};
|
||||||
/// #![feature(extract_if)]
|
/// #![feature(extract_if)]
|
||||||
///
|
///
|
||||||
/// let mut v = vec![0, 1, 2];
|
/// let mut v = vec![0, 1, 2];
|
||||||
/// let iter: std::vec::ExtractIf<'_, _, _> = v.extract_if(|x| *x % 2 == 0);
|
/// let iter: std::vec::ExtractIf<'_, _, _> = v.extract_if(.., |x| *x % 2 == 0);
|
||||||
/// ```
|
/// ```
|
||||||
#[unstable(feature = "extract_if", reason = "recently added", issue = "43244")]
|
#[unstable(feature = "extract_if", reason = "recently added", issue = "43244")]
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
|
@ -24,24 +25,32 @@ pub struct ExtractIf<
|
||||||
T,
|
T,
|
||||||
F,
|
F,
|
||||||
#[unstable(feature = "allocator_api", issue = "32838")] A: Allocator = Global,
|
#[unstable(feature = "allocator_api", issue = "32838")] A: Allocator = Global,
|
||||||
> where
|
> {
|
||||||
F: FnMut(&mut T) -> bool,
|
vec: &'a mut Vec<T, A>,
|
||||||
{
|
|
||||||
pub(super) vec: &'a mut Vec<T, A>,
|
|
||||||
/// The index of the item that will be inspected by the next call to `next`.
|
/// The index of the item that will be inspected by the next call to `next`.
|
||||||
pub(super) idx: usize,
|
idx: usize,
|
||||||
|
/// Elements at and beyond this point will be retained. Must be equal or smaller than `old_len`.
|
||||||
|
end: usize,
|
||||||
/// The number of items that have been drained (removed) thus far.
|
/// The number of items that have been drained (removed) thus far.
|
||||||
pub(super) del: usize,
|
del: usize,
|
||||||
/// The original length of `vec` prior to draining.
|
/// The original length of `vec` prior to draining.
|
||||||
pub(super) old_len: usize,
|
old_len: usize,
|
||||||
/// The filter test predicate.
|
/// The filter test predicate.
|
||||||
pub(super) pred: F,
|
pred: F,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<T, F, A: Allocator> ExtractIf<'_, T, F, A>
|
impl<'a, T, F, A: Allocator> ExtractIf<'a, T, F, A> {
|
||||||
where
|
pub(super) fn new<R: RangeBounds<usize>>(vec: &'a mut Vec<T, A>, pred: F, range: R) -> Self {
|
||||||
F: FnMut(&mut T) -> bool,
|
let old_len = vec.len();
|
||||||
{
|
let Range { start, end } = slice::range(range, ..old_len);
|
||||||
|
|
||||||
|
// Guard against the vec getting leaked (leak amplification)
|
||||||
|
unsafe {
|
||||||
|
vec.set_len(0);
|
||||||
|
}
|
||||||
|
ExtractIf { vec, idx: start, del: 0, end, old_len, pred }
|
||||||
|
}
|
||||||
|
|
||||||
/// Returns a reference to the underlying allocator.
|
/// Returns a reference to the underlying allocator.
|
||||||
#[unstable(feature = "allocator_api", issue = "32838")]
|
#[unstable(feature = "allocator_api", issue = "32838")]
|
||||||
#[inline]
|
#[inline]
|
||||||
|
@ -59,7 +68,7 @@ where
|
||||||
|
|
||||||
fn next(&mut self) -> Option<T> {
|
fn next(&mut self) -> Option<T> {
|
||||||
unsafe {
|
unsafe {
|
||||||
while self.idx < self.old_len {
|
while self.idx < self.end {
|
||||||
let i = self.idx;
|
let i = self.idx;
|
||||||
let v = slice::from_raw_parts_mut(self.vec.as_mut_ptr(), self.old_len);
|
let v = slice::from_raw_parts_mut(self.vec.as_mut_ptr(), self.old_len);
|
||||||
let drained = (self.pred)(&mut v[i]);
|
let drained = (self.pred)(&mut v[i]);
|
||||||
|
@ -82,24 +91,15 @@ where
|
||||||
}
|
}
|
||||||
|
|
||||||
fn size_hint(&self) -> (usize, Option<usize>) {
|
fn size_hint(&self) -> (usize, Option<usize>) {
|
||||||
(0, Some(self.old_len - self.idx))
|
(0, Some(self.end - self.idx))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[unstable(feature = "extract_if", reason = "recently added", issue = "43244")]
|
#[unstable(feature = "extract_if", reason = "recently added", issue = "43244")]
|
||||||
impl<T, F, A: Allocator> Drop for ExtractIf<'_, T, F, A>
|
impl<T, F, A: Allocator> Drop for ExtractIf<'_, T, F, A> {
|
||||||
where
|
|
||||||
F: FnMut(&mut T) -> bool,
|
|
||||||
{
|
|
||||||
fn drop(&mut self) {
|
fn drop(&mut self) {
|
||||||
unsafe {
|
unsafe {
|
||||||
if self.idx < self.old_len && self.del > 0 {
|
if self.idx < self.old_len && self.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.vec.as_mut_ptr();
|
let ptr = self.vec.as_mut_ptr();
|
||||||
let src = ptr.add(self.idx);
|
let src = ptr.add(self.idx);
|
||||||
let dst = src.sub(self.del);
|
let dst = src.sub(self.del);
|
||||||
|
|
|
@ -3615,12 +3615,15 @@ impl<T, A: Allocator> Vec<T, A> {
|
||||||
Splice { drain: self.drain(range), replace_with: replace_with.into_iter() }
|
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.
|
/// Creates an iterator which uses a closure to determine if element in the range should be removed.
|
||||||
///
|
///
|
||||||
/// If the closure returns true, then the element is removed and yielded.
|
/// 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
|
/// If the closure returns false, the element will remain in the vector and will not be yielded
|
||||||
/// by the iterator.
|
/// by the iterator.
|
||||||
///
|
///
|
||||||
|
/// Only elements that fall in the provided range are considered for extraction, but any elements
|
||||||
|
/// after the range will still have to be moved if any element has been extracted.
|
||||||
|
///
|
||||||
/// If the returned `ExtractIf` is not exhausted, e.g. because it is dropped without iterating
|
/// If the returned `ExtractIf` is not exhausted, e.g. because it is dropped without iterating
|
||||||
/// or the iteration short-circuits, then the remaining elements will be retained.
|
/// or the iteration short-circuits, then the remaining elements will be retained.
|
||||||
/// Use [`retain`] with a negated predicate if you do not need the returned iterator.
|
/// Use [`retain`] with a negated predicate if you do not need the returned iterator.
|
||||||
|
@ -3630,10 +3633,12 @@ impl<T, A: Allocator> Vec<T, A> {
|
||||||
/// Using this method is equivalent to the following code:
|
/// Using this method is equivalent to the following code:
|
||||||
///
|
///
|
||||||
/// ```
|
/// ```
|
||||||
|
/// # use std::cmp::min;
|
||||||
/// # let some_predicate = |x: &mut i32| { *x == 2 || *x == 3 || *x == 6 };
|
/// # let some_predicate = |x: &mut i32| { *x == 2 || *x == 3 || *x == 6 };
|
||||||
/// # let mut vec = vec![1, 2, 3, 4, 5, 6];
|
/// # let mut vec = vec![1, 2, 3, 4, 5, 6];
|
||||||
/// let mut i = 0;
|
/// # let range = 1..4;
|
||||||
/// while i < vec.len() {
|
/// let mut i = range.start;
|
||||||
|
/// while i < min(vec.len(), range.end) {
|
||||||
/// if some_predicate(&mut vec[i]) {
|
/// if some_predicate(&mut vec[i]) {
|
||||||
/// let val = vec.remove(i);
|
/// let val = vec.remove(i);
|
||||||
/// // your code here
|
/// // your code here
|
||||||
|
@ -3648,8 +3653,12 @@ impl<T, A: Allocator> Vec<T, A> {
|
||||||
/// But `extract_if` is easier to use. `extract_if` is also more efficient,
|
/// But `extract_if` is easier to use. `extract_if` is also more efficient,
|
||||||
/// because it can backshift the elements of the array in bulk.
|
/// because it can backshift the elements of the array in bulk.
|
||||||
///
|
///
|
||||||
/// Note that `extract_if` also lets you mutate every element in the filter closure,
|
/// Note that `extract_if` also lets you mutate the elements passed to the filter closure,
|
||||||
/// regardless of whether you choose to keep or remove it.
|
/// regardless of whether you choose to keep or remove them.
|
||||||
|
///
|
||||||
|
/// # Panics
|
||||||
|
///
|
||||||
|
/// If `range` is out of bounds.
|
||||||
///
|
///
|
||||||
/// # Examples
|
/// # Examples
|
||||||
///
|
///
|
||||||
|
@ -3659,25 +3668,29 @@ impl<T, A: Allocator> Vec<T, A> {
|
||||||
/// #![feature(extract_if)]
|
/// #![feature(extract_if)]
|
||||||
/// let mut numbers = vec![1, 2, 3, 4, 5, 6, 8, 9, 11, 13, 14, 15];
|
/// let mut numbers = vec![1, 2, 3, 4, 5, 6, 8, 9, 11, 13, 14, 15];
|
||||||
///
|
///
|
||||||
/// let evens = numbers.extract_if(|x| *x % 2 == 0).collect::<Vec<_>>();
|
/// let evens = numbers.extract_if(.., |x| *x % 2 == 0).collect::<Vec<_>>();
|
||||||
/// let odds = numbers;
|
/// let odds = numbers;
|
||||||
///
|
///
|
||||||
/// assert_eq!(evens, vec![2, 4, 6, 8, 14]);
|
/// assert_eq!(evens, vec![2, 4, 6, 8, 14]);
|
||||||
/// assert_eq!(odds, vec![1, 3, 5, 9, 11, 13, 15]);
|
/// assert_eq!(odds, vec![1, 3, 5, 9, 11, 13, 15]);
|
||||||
/// ```
|
/// ```
|
||||||
|
///
|
||||||
|
/// Using the range argument to only process a part of the vector:
|
||||||
|
///
|
||||||
|
/// ```
|
||||||
|
/// #![feature(extract_if)]
|
||||||
|
/// let mut items = vec![0, 0, 0, 0, 0, 0, 0, 1, 2, 1, 2, 1, 2];
|
||||||
|
/// let ones = items.extract_if(7.., |x| *x == 1).collect::<Vec<_>>();
|
||||||
|
/// assert_eq!(items, vec![0, 0, 0, 0, 0, 0, 0, 2, 2, 2]);
|
||||||
|
/// assert_eq!(ones.len(), 3);
|
||||||
|
/// ```
|
||||||
#[unstable(feature = "extract_if", reason = "recently added", issue = "43244")]
|
#[unstable(feature = "extract_if", reason = "recently added", issue = "43244")]
|
||||||
pub fn extract_if<F>(&mut self, filter: F) -> ExtractIf<'_, T, F, A>
|
pub fn extract_if<F, R>(&mut self, range: R, filter: F) -> ExtractIf<'_, T, F, A>
|
||||||
where
|
where
|
||||||
F: FnMut(&mut T) -> bool,
|
F: FnMut(&mut T) -> bool,
|
||||||
|
R: RangeBounds<usize>,
|
||||||
{
|
{
|
||||||
let old_len = self.len();
|
ExtractIf::new(self, filter, range)
|
||||||
|
|
||||||
// Guard against us getting leaked (leak amplification)
|
|
||||||
unsafe {
|
|
||||||
self.set_len(0);
|
|
||||||
}
|
|
||||||
|
|
||||||
ExtractIf { vec: self, idx: 0, del: 0, old_len, pred: filter }
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1414,7 +1414,7 @@ fn extract_if_empty() {
|
||||||
let mut vec: Vec<i32> = vec![];
|
let mut vec: Vec<i32> = vec![];
|
||||||
|
|
||||||
{
|
{
|
||||||
let mut iter = vec.extract_if(|_| true);
|
let mut iter = vec.extract_if(.., |_| true);
|
||||||
assert_eq!(iter.size_hint(), (0, Some(0)));
|
assert_eq!(iter.size_hint(), (0, Some(0)));
|
||||||
assert_eq!(iter.next(), None);
|
assert_eq!(iter.next(), None);
|
||||||
assert_eq!(iter.size_hint(), (0, Some(0)));
|
assert_eq!(iter.size_hint(), (0, Some(0)));
|
||||||
|
@ -1431,7 +1431,7 @@ fn extract_if_zst() {
|
||||||
let initial_len = vec.len();
|
let initial_len = vec.len();
|
||||||
let mut count = 0;
|
let mut count = 0;
|
||||||
{
|
{
|
||||||
let mut iter = vec.extract_if(|_| true);
|
let mut iter = vec.extract_if(.., |_| true);
|
||||||
assert_eq!(iter.size_hint(), (0, Some(initial_len)));
|
assert_eq!(iter.size_hint(), (0, Some(initial_len)));
|
||||||
while let Some(_) = iter.next() {
|
while let Some(_) = iter.next() {
|
||||||
count += 1;
|
count += 1;
|
||||||
|
@ -1454,7 +1454,7 @@ fn extract_if_false() {
|
||||||
let initial_len = vec.len();
|
let initial_len = vec.len();
|
||||||
let mut count = 0;
|
let mut count = 0;
|
||||||
{
|
{
|
||||||
let mut iter = vec.extract_if(|_| false);
|
let mut iter = vec.extract_if(.., |_| false);
|
||||||
assert_eq!(iter.size_hint(), (0, Some(initial_len)));
|
assert_eq!(iter.size_hint(), (0, Some(initial_len)));
|
||||||
for _ in iter.by_ref() {
|
for _ in iter.by_ref() {
|
||||||
count += 1;
|
count += 1;
|
||||||
|
@ -1476,7 +1476,7 @@ fn extract_if_true() {
|
||||||
let initial_len = vec.len();
|
let initial_len = vec.len();
|
||||||
let mut count = 0;
|
let mut count = 0;
|
||||||
{
|
{
|
||||||
let mut iter = vec.extract_if(|_| true);
|
let mut iter = vec.extract_if(.., |_| true);
|
||||||
assert_eq!(iter.size_hint(), (0, Some(initial_len)));
|
assert_eq!(iter.size_hint(), (0, Some(initial_len)));
|
||||||
while let Some(_) = iter.next() {
|
while let Some(_) = iter.next() {
|
||||||
count += 1;
|
count += 1;
|
||||||
|
@ -1492,6 +1492,31 @@ fn extract_if_true() {
|
||||||
assert_eq!(vec, vec![]);
|
assert_eq!(vec, vec![]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn extract_if_ranges() {
|
||||||
|
let mut vec = vec![0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10];
|
||||||
|
|
||||||
|
let mut count = 0;
|
||||||
|
let it = vec.extract_if(1..=3, |_| {
|
||||||
|
count += 1;
|
||||||
|
true
|
||||||
|
});
|
||||||
|
assert_eq!(it.collect::<Vec<_>>(), vec![1, 2, 3]);
|
||||||
|
assert_eq!(vec, vec![0, 4, 5, 6, 7, 8, 9, 10]);
|
||||||
|
assert_eq!(count, 3);
|
||||||
|
|
||||||
|
let it = vec.extract_if(1..=3, |_| false);
|
||||||
|
assert_eq!(it.collect::<Vec<_>>(), vec![]);
|
||||||
|
assert_eq!(vec, vec![0, 4, 5, 6, 7, 8, 9, 10]);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
#[should_panic]
|
||||||
|
fn extract_if_out_of_bounds() {
|
||||||
|
let mut vec = vec![0, 1];
|
||||||
|
let _ = vec.extract_if(5.., |_| true).for_each(drop);
|
||||||
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn extract_if_complex() {
|
fn extract_if_complex() {
|
||||||
{
|
{
|
||||||
|
@ -1501,7 +1526,7 @@ fn extract_if_complex() {
|
||||||
39,
|
39,
|
||||||
];
|
];
|
||||||
|
|
||||||
let removed = vec.extract_if(|x| *x % 2 == 0).collect::<Vec<_>>();
|
let removed = vec.extract_if(.., |x| *x % 2 == 0).collect::<Vec<_>>();
|
||||||
assert_eq!(removed.len(), 10);
|
assert_eq!(removed.len(), 10);
|
||||||
assert_eq!(removed, vec![2, 4, 6, 18, 20, 22, 24, 26, 34, 36]);
|
assert_eq!(removed, vec![2, 4, 6, 18, 20, 22, 24, 26, 34, 36]);
|
||||||
|
|
||||||
|
@ -1515,7 +1540,7 @@ fn extract_if_complex() {
|
||||||
2, 4, 6, 7, 9, 11, 13, 15, 17, 18, 20, 22, 24, 26, 27, 29, 31, 33, 34, 35, 36, 37, 39,
|
2, 4, 6, 7, 9, 11, 13, 15, 17, 18, 20, 22, 24, 26, 27, 29, 31, 33, 34, 35, 36, 37, 39,
|
||||||
];
|
];
|
||||||
|
|
||||||
let removed = vec.extract_if(|x| *x % 2 == 0).collect::<Vec<_>>();
|
let removed = vec.extract_if(.., |x| *x % 2 == 0).collect::<Vec<_>>();
|
||||||
assert_eq!(removed.len(), 10);
|
assert_eq!(removed.len(), 10);
|
||||||
assert_eq!(removed, vec![2, 4, 6, 18, 20, 22, 24, 26, 34, 36]);
|
assert_eq!(removed, vec![2, 4, 6, 18, 20, 22, 24, 26, 34, 36]);
|
||||||
|
|
||||||
|
@ -1528,7 +1553,7 @@ fn extract_if_complex() {
|
||||||
let mut vec =
|
let mut vec =
|
||||||
vec![2, 4, 6, 7, 9, 11, 13, 15, 17, 18, 20, 22, 24, 26, 27, 29, 31, 33, 34, 35, 36];
|
vec![2, 4, 6, 7, 9, 11, 13, 15, 17, 18, 20, 22, 24, 26, 27, 29, 31, 33, 34, 35, 36];
|
||||||
|
|
||||||
let removed = vec.extract_if(|x| *x % 2 == 0).collect::<Vec<_>>();
|
let removed = vec.extract_if(.., |x| *x % 2 == 0).collect::<Vec<_>>();
|
||||||
assert_eq!(removed.len(), 10);
|
assert_eq!(removed.len(), 10);
|
||||||
assert_eq!(removed, vec![2, 4, 6, 18, 20, 22, 24, 26, 34, 36]);
|
assert_eq!(removed, vec![2, 4, 6, 18, 20, 22, 24, 26, 34, 36]);
|
||||||
|
|
||||||
|
@ -1540,7 +1565,7 @@ fn extract_if_complex() {
|
||||||
// [xxxxxxxxxx+++++++++++]
|
// [xxxxxxxxxx+++++++++++]
|
||||||
let mut vec = vec![2, 4, 6, 8, 10, 12, 14, 16, 18, 20, 1, 3, 5, 7, 9, 11, 13, 15, 17, 19];
|
let mut vec = vec![2, 4, 6, 8, 10, 12, 14, 16, 18, 20, 1, 3, 5, 7, 9, 11, 13, 15, 17, 19];
|
||||||
|
|
||||||
let removed = vec.extract_if(|x| *x % 2 == 0).collect::<Vec<_>>();
|
let removed = vec.extract_if(.., |x| *x % 2 == 0).collect::<Vec<_>>();
|
||||||
assert_eq!(removed.len(), 10);
|
assert_eq!(removed.len(), 10);
|
||||||
assert_eq!(removed, vec![2, 4, 6, 8, 10, 12, 14, 16, 18, 20]);
|
assert_eq!(removed, vec![2, 4, 6, 8, 10, 12, 14, 16, 18, 20]);
|
||||||
|
|
||||||
|
@ -1552,7 +1577,7 @@ fn extract_if_complex() {
|
||||||
// [+++++++++++xxxxxxxxxx]
|
// [+++++++++++xxxxxxxxxx]
|
||||||
let mut vec = vec![1, 3, 5, 7, 9, 11, 13, 15, 17, 19, 2, 4, 6, 8, 10, 12, 14, 16, 18, 20];
|
let mut vec = vec![1, 3, 5, 7, 9, 11, 13, 15, 17, 19, 2, 4, 6, 8, 10, 12, 14, 16, 18, 20];
|
||||||
|
|
||||||
let removed = vec.extract_if(|x| *x % 2 == 0).collect::<Vec<_>>();
|
let removed = vec.extract_if(.., |x| *x % 2 == 0).collect::<Vec<_>>();
|
||||||
assert_eq!(removed.len(), 10);
|
assert_eq!(removed.len(), 10);
|
||||||
assert_eq!(removed, vec![2, 4, 6, 8, 10, 12, 14, 16, 18, 20]);
|
assert_eq!(removed, vec![2, 4, 6, 8, 10, 12, 14, 16, 18, 20]);
|
||||||
|
|
||||||
|
@ -1600,7 +1625,7 @@ fn extract_if_consumed_panic() {
|
||||||
}
|
}
|
||||||
c.index < 6
|
c.index < 6
|
||||||
};
|
};
|
||||||
let drain = data.extract_if(filter);
|
let drain = data.extract_if(.., filter);
|
||||||
|
|
||||||
// NOTE: The ExtractIf is explicitly consumed
|
// NOTE: The ExtractIf is explicitly consumed
|
||||||
drain.for_each(drop);
|
drain.for_each(drop);
|
||||||
|
@ -1653,7 +1678,7 @@ fn extract_if_unconsumed_panic() {
|
||||||
}
|
}
|
||||||
c.index < 6
|
c.index < 6
|
||||||
};
|
};
|
||||||
let _drain = data.extract_if(filter);
|
let _drain = data.extract_if(.., filter);
|
||||||
|
|
||||||
// NOTE: The ExtractIf is dropped without being consumed
|
// NOTE: The ExtractIf is dropped without being consumed
|
||||||
});
|
});
|
||||||
|
@ -1669,7 +1694,7 @@ fn extract_if_unconsumed_panic() {
|
||||||
#[test]
|
#[test]
|
||||||
fn extract_if_unconsumed() {
|
fn extract_if_unconsumed() {
|
||||||
let mut vec = vec![1, 2, 3, 4];
|
let mut vec = vec![1, 2, 3, 4];
|
||||||
let drain = vec.extract_if(|&mut x| x % 2 != 0);
|
let drain = vec.extract_if(.., |&mut x| x % 2 != 0);
|
||||||
drop(drain);
|
drop(drain);
|
||||||
assert_eq!(vec, [1, 2, 3, 4]);
|
assert_eq!(vec, [1, 2, 3, 4]);
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue