s/drain_filter/extract_if/ for Vec, Btree{Map,Set} and LinkedList

This commit is contained in:
The 8472 2023-04-09 00:37:21 +02:00
parent b7ce7edd87
commit 114d5f221c
31 changed files with 204 additions and 216 deletions

View File

@ -4,7 +4,7 @@
#![doc(html_root_url = "https://doc.rust-lang.org/nightly/nightly-rustc/")] #![doc(html_root_url = "https://doc.rust-lang.org/nightly/nightly-rustc/")]
#![feature(array_windows)] #![feature(array_windows)]
#![feature(drain_filter)] #![feature(extract_if)]
#![feature(if_let_guard)] #![feature(if_let_guard)]
#![feature(let_chains)] #![feature(let_chains)]
#![feature(never_type)] #![feature(never_type)]
@ -1399,7 +1399,7 @@ impl HandlerInner {
!self.emitted_diagnostics.insert(diagnostic_hash) !self.emitted_diagnostics.insert(diagnostic_hash)
}; };
diagnostic.children.drain_filter(already_emitted_sub).for_each(|_| {}); diagnostic.children.extract_if(already_emitted_sub).for_each(|_| {});
self.emitter.emit_diagnostic(diagnostic); self.emitter.emit_diagnostic(diagnostic);
if diagnostic.is_error() { if diagnostic.is_error() {

View File

@ -59,7 +59,6 @@ This API is completely unstable and subject to change.
#![doc(html_root_url = "https://doc.rust-lang.org/nightly/nightly-rustc/")] #![doc(html_root_url = "https://doc.rust-lang.org/nightly/nightly-rustc/")]
#![feature(box_patterns)] #![feature(box_patterns)]
#![feature(control_flow_enum)] #![feature(control_flow_enum)]
#![feature(drain_filter)]
#![feature(hash_drain_filter)] #![feature(hash_drain_filter)]
#![feature(if_let_guard)] #![feature(if_let_guard)]
#![feature(is_sorted)] #![feature(is_sorted)]

View File

@ -5,7 +5,6 @@
#![feature(box_patterns)] #![feature(box_patterns)]
#![feature(min_specialization)] #![feature(min_specialization)]
#![feature(control_flow_enum)] #![feature(control_flow_enum)]
#![feature(drain_filter)]
#![feature(option_as_slice)] #![feature(option_as_slice)]
#![allow(rustc::potential_query_instability)] #![allow(rustc::potential_query_instability)]
#![recursion_limit = "256"] #![recursion_limit = "256"]

View File

@ -1,6 +1,6 @@
#![doc(html_root_url = "https://doc.rust-lang.org/nightly/nightly-rustc/")] #![doc(html_root_url = "https://doc.rust-lang.org/nightly/nightly-rustc/")]
#![feature(decl_macro)] #![feature(decl_macro)]
#![feature(drain_filter)] #![feature(extract_if)]
#![feature(generators)] #![feature(generators)]
#![feature(iter_from_generator)] #![feature(iter_from_generator)]
#![feature(let_chains)] #![feature(let_chains)]

View File

@ -425,7 +425,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
.drain_filter(|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

View File

@ -54,7 +54,7 @@
#![feature(try_reserve_kind)] #![feature(try_reserve_kind)]
#![feature(nonzero_ops)] #![feature(nonzero_ops)]
#![feature(decl_macro)] #![feature(decl_macro)]
#![feature(drain_filter)] #![feature(extract_if)]
#![feature(intra_doc_pointers)] #![feature(intra_doc_pointers)]
#![feature(yeet_expr)] #![feature(yeet_expr)]
#![feature(result_option_inspect)] #![feature(result_option_inspect)]

View File

@ -237,7 +237,7 @@ pub fn suggest_constraining_type_params<'a>(
{ {
let mut sized_constraints = let mut sized_constraints =
constraints.drain_filter(|(_, def_id)| *def_id == tcx.lang_items().sized_trait()); constraints.extract_if(|(_, def_id)| *def_id == tcx.lang_items().sized_trait());
if let Some((constraint, def_id)) = sized_constraints.next() { if let Some((constraint, def_id)) = sized_constraints.next() {
applicability = Applicability::MaybeIncorrect; applicability = Applicability::MaybeIncorrect;

View File

@ -2,7 +2,6 @@
#![deny(rustc::untranslatable_diagnostic)] #![deny(rustc::untranslatable_diagnostic)]
#![deny(rustc::diagnostic_outside_of_impl)] #![deny(rustc::diagnostic_outside_of_impl)]
#![feature(box_patterns)] #![feature(box_patterns)]
#![feature(drain_filter)]
#![feature(is_sorted)] #![feature(is_sorted)]
#![feature(let_chains)] #![feature(let_chains)]
#![feature(map_try_insert)] #![feature(map_try_insert)]

View File

@ -436,13 +436,12 @@ impl<'tcx, 'll> MutVisitor<'tcx> for ReplacementVisitor<'tcx, 'll> {
VarDebugInfoContents::Composite { ty: _, ref mut fragments } => { VarDebugInfoContents::Composite { ty: _, ref mut fragments } => {
let mut new_fragments = Vec::new(); let mut new_fragments = Vec::new();
debug!(?fragments); debug!(?fragments);
fragments fragments.retain_mut(|fragment| {
.drain_filter(|fragment| {
if let Some(repl) = if let Some(repl) =
self.replacements.replace_place(self.tcx, fragment.contents.as_ref()) self.replacements.replace_place(self.tcx, fragment.contents.as_ref())
{ {
fragment.contents = repl; fragment.contents = repl;
false true
} else if let Some(local) = fragment.contents.as_local() } else if let Some(local) = fragment.contents.as_local()
&& let Some(frg) = self.gather_debug_info_fragments(local) && let Some(frg) = self.gather_debug_info_fragments(local)
{ {
@ -450,12 +449,11 @@ impl<'tcx, 'll> MutVisitor<'tcx> for ReplacementVisitor<'tcx, 'll> {
f.projection.splice(0..0, fragment.projection.iter().copied()); f.projection.splice(0..0, fragment.projection.iter().copied());
f f
})); }));
true
} else {
false false
} else {
true
} }
}) });
.for_each(drop);
debug!(?fragments); debug!(?fragments);
debug!(?new_fragments); debug!(?new_fragments);
fragments.extend(new_fragments); fragments.extend(new_fragments);

View File

@ -2494,7 +2494,7 @@ fn show_candidates(
for path_strings in [&mut accessible_path_strings, &mut inaccessible_path_strings] { for path_strings in [&mut accessible_path_strings, &mut inaccessible_path_strings] {
path_strings.sort_by(|a, b| a.0.cmp(&b.0)); path_strings.sort_by(|a, b| a.0.cmp(&b.0));
let core_path_strings = let core_path_strings =
path_strings.drain_filter(|p| p.0.starts_with("core::")).collect::<Vec<_>>(); path_strings.extract_if(|p| p.0.starts_with("core::")).collect::<Vec<_>>();
path_strings.extend(core_path_strings); path_strings.extend(core_path_strings);
path_strings.dedup_by(|a, b| a.0 == b.0); path_strings.dedup_by(|a, b| a.0 == b.0);
} }

View File

@ -496,7 +496,7 @@ impl<'a: 'ast, 'ast, 'tcx> LateResolutionVisitor<'a, '_, 'ast, '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
.drain_filter(|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::")
}) })

View File

@ -9,7 +9,7 @@
#![doc(html_root_url = "https://doc.rust-lang.org/nightly/nightly-rustc/")] #![doc(html_root_url = "https://doc.rust-lang.org/nightly/nightly-rustc/")]
#![feature(assert_matches)] #![feature(assert_matches)]
#![feature(box_patterns)] #![feature(box_patterns)]
#![feature(drain_filter)] #![feature(extract_if)]
#![feature(if_let_guard)] #![feature(if_let_guard)]
#![feature(iter_intersperse)] #![feature(iter_intersperse)]
#![feature(let_chains)] #![feature(let_chains)]

View File

@ -14,7 +14,7 @@
#![feature(associated_type_bounds)] #![feature(associated_type_bounds)]
#![feature(box_patterns)] #![feature(box_patterns)]
#![feature(control_flow_enum)] #![feature(control_flow_enum)]
#![feature(drain_filter)] #![feature(extract_if)]
#![feature(hash_drain_filter)] #![feature(hash_drain_filter)]
#![feature(let_chains)] #![feature(let_chains)]
#![feature(if_let_guard)] #![feature(if_let_guard)]

View File

@ -354,7 +354,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
.drain_filter(|predicate| { .extract_if(|predicate| {
matches!( matches!(
predicate.kind().skip_binder(), predicate.kind().skip_binder(),
ty::PredicateKind::Clause(ty::Clause::TypeOutlives(..)) ty::PredicateKind::Clause(ty::Clause::TypeOutlives(..))

View File

@ -4,7 +4,6 @@
#![deny(rustc::untranslatable_diagnostic)] #![deny(rustc::untranslatable_diagnostic)]
#![deny(rustc::diagnostic_outside_of_impl)] #![deny(rustc::diagnostic_outside_of_impl)]
#![feature(let_chains)] #![feature(let_chains)]
#![feature(drain_filter)]
#![recursion_limit = "256"] #![recursion_limit = "256"]
#[macro_use] #[macro_use]

View File

@ -385,7 +385,7 @@ pub fn clone_slim_100_and_clear(b: &mut Bencher) {
#[bench] #[bench]
pub fn clone_slim_100_and_drain_all(b: &mut Bencher) { pub fn clone_slim_100_and_drain_all(b: &mut Bencher) {
let src = slim_map(100); let src = slim_map(100);
b.iter(|| src.clone().drain_filter(|_, _| true).count()) b.iter(|| src.clone().extract_if(|_, _| true).count())
} }
#[bench] #[bench]
@ -393,7 +393,7 @@ pub fn clone_slim_100_and_drain_half(b: &mut Bencher) {
let src = slim_map(100); let src = slim_map(100);
b.iter(|| { b.iter(|| {
let mut map = src.clone(); let mut map = src.clone();
assert_eq!(map.drain_filter(|i, _| i % 2 == 0).count(), 100 / 2); assert_eq!(map.extract_if(|i, _| i % 2 == 0).count(), 100 / 2);
assert_eq!(map.len(), 100 / 2); assert_eq!(map.len(), 100 / 2);
}) })
} }
@ -456,7 +456,7 @@ pub fn clone_slim_10k_and_clear(b: &mut Bencher) {
#[bench] #[bench]
pub fn clone_slim_10k_and_drain_all(b: &mut Bencher) { pub fn clone_slim_10k_and_drain_all(b: &mut Bencher) {
let src = slim_map(10_000); let src = slim_map(10_000);
b.iter(|| src.clone().drain_filter(|_, _| true).count()) b.iter(|| src.clone().extract_if(|_, _| true).count())
} }
#[bench] #[bench]
@ -464,7 +464,7 @@ pub fn clone_slim_10k_and_drain_half(b: &mut Bencher) {
let src = slim_map(10_000); let src = slim_map(10_000);
b.iter(|| { b.iter(|| {
let mut map = src.clone(); let mut map = src.clone();
assert_eq!(map.drain_filter(|i, _| i % 2 == 0).count(), 10_000 / 2); assert_eq!(map.extract_if(|i, _| i % 2 == 0).count(), 10_000 / 2);
assert_eq!(map.len(), 10_000 / 2); assert_eq!(map.len(), 10_000 / 2);
}) })
} }
@ -527,7 +527,7 @@ pub fn clone_fat_val_100_and_clear(b: &mut Bencher) {
#[bench] #[bench]
pub fn clone_fat_val_100_and_drain_all(b: &mut Bencher) { pub fn clone_fat_val_100_and_drain_all(b: &mut Bencher) {
let src = fat_val_map(100); let src = fat_val_map(100);
b.iter(|| src.clone().drain_filter(|_, _| true).count()) b.iter(|| src.clone().extract_if(|_, _| true).count())
} }
#[bench] #[bench]
@ -535,7 +535,7 @@ pub fn clone_fat_val_100_and_drain_half(b: &mut Bencher) {
let src = fat_val_map(100); let src = fat_val_map(100);
b.iter(|| { b.iter(|| {
let mut map = src.clone(); let mut map = src.clone();
assert_eq!(map.drain_filter(|i, _| i % 2 == 0).count(), 100 / 2); assert_eq!(map.extract_if(|i, _| i % 2 == 0).count(), 100 / 2);
assert_eq!(map.len(), 100 / 2); assert_eq!(map.len(), 100 / 2);
}) })
} }

View File

@ -69,7 +69,7 @@ pub fn clone_100_and_clear(b: &mut Bencher) {
#[bench] #[bench]
pub fn clone_100_and_drain_all(b: &mut Bencher) { pub fn clone_100_and_drain_all(b: &mut Bencher) {
let src = slim_set(100); let src = slim_set(100);
b.iter(|| src.clone().drain_filter(|_| true).count()) b.iter(|| src.clone().extract_if(|_| true).count())
} }
#[bench] #[bench]
@ -77,7 +77,7 @@ pub fn clone_100_and_drain_half(b: &mut Bencher) {
let src = slim_set(100); let src = slim_set(100);
b.iter(|| { b.iter(|| {
let mut set = src.clone(); let mut set = src.clone();
assert_eq!(set.drain_filter(|i| i % 2 == 0).count(), 100 / 2); assert_eq!(set.extract_if(|i| i % 2 == 0).count(), 100 / 2);
assert_eq!(set.len(), 100 / 2); assert_eq!(set.len(), 100 / 2);
}) })
} }
@ -140,7 +140,7 @@ pub fn clone_10k_and_clear(b: &mut Bencher) {
#[bench] #[bench]
pub fn clone_10k_and_drain_all(b: &mut Bencher) { pub fn clone_10k_and_drain_all(b: &mut Bencher) {
let src = slim_set(10_000); let src = slim_set(10_000);
b.iter(|| src.clone().drain_filter(|_| true).count()) b.iter(|| src.clone().extract_if(|_| true).count())
} }
#[bench] #[bench]
@ -148,7 +148,7 @@ pub fn clone_10k_and_drain_half(b: &mut Bencher) {
let src = slim_set(10_000); let src = slim_set(10_000);
b.iter(|| { b.iter(|| {
let mut set = src.clone(); let mut set = src.clone();
assert_eq!(set.drain_filter(|i| i % 2 == 0).count(), 10_000 / 2); assert_eq!(set.extract_if(|i| i % 2 == 0).count(), 10_000 / 2);
assert_eq!(set.len(), 10_000 / 2); assert_eq!(set.len(), 10_000 / 2);
}) })
} }

View File

@ -1,7 +1,7 @@
// Disabling on android for the time being // Disabling on android for the time being
// See https://github.com/rust-lang/rust/issues/73535#event-3477699747 // See https://github.com/rust-lang/rust/issues/73535#event-3477699747
#![cfg(not(target_os = "android"))] #![cfg(not(target_os = "android"))]
#![feature(btree_drain_filter)] #![feature(btree_extract_if)]
#![feature(iter_next_chunk)] #![feature(iter_next_chunk)]
#![feature(repr_simd)] #![feature(repr_simd)]
#![feature(slice_partition_dedup)] #![feature(slice_partition_dedup)]

View File

@ -1132,7 +1132,7 @@ impl<K, V, A: Allocator + Clone> BTreeMap<K, V, A> {
K: Ord, K: Ord,
F: FnMut(&K, &mut V) -> bool, F: FnMut(&K, &mut V) -> bool,
{ {
self.drain_filter(|k, v| !f(k, v)).for_each(drop); self.extract_if(|k, v| !f(k, v)).for_each(drop);
} }
/// Moves all elements from `other` into `self`, leaving `other` empty. /// Moves all elements from `other` into `self`, leaving `other` empty.
@ -1395,7 +1395,7 @@ impl<K, V, A: Allocator + Clone> BTreeMap<K, V, A> {
/// The iterator also lets you mutate the value of each element in the /// The iterator also lets you mutate the value of each element in the
/// closure, regardless of whether you choose to keep or remove it. /// closure, regardless of whether you choose to keep or remove it.
/// ///
/// If the returned `DrainFilter` 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.
/// ///
@ -1406,26 +1406,26 @@ impl<K, V, A: Allocator + Clone> BTreeMap<K, V, A> {
/// Splitting a map into even and odd keys, reusing the original map: /// Splitting a map into even and odd keys, reusing the original map:
/// ///
/// ``` /// ```
/// #![feature(btree_drain_filter)] /// #![feature(btree_extract_if)]
/// use std::collections::BTreeMap; /// use std::collections::BTreeMap;
/// ///
/// let mut map: BTreeMap<i32, i32> = (0..8).map(|x| (x, x)).collect(); /// let mut map: BTreeMap<i32, i32> = (0..8).map(|x| (x, x)).collect();
/// let evens: BTreeMap<_, _> = map.drain_filter(|k, _v| k % 2 == 0).collect(); /// let evens: BTreeMap<_, _> = map.extract_if(|k, _v| k % 2 == 0).collect();
/// let odds = map; /// let odds = map;
/// assert_eq!(evens.keys().copied().collect::<Vec<_>>(), [0, 2, 4, 6]); /// assert_eq!(evens.keys().copied().collect::<Vec<_>>(), [0, 2, 4, 6]);
/// assert_eq!(odds.keys().copied().collect::<Vec<_>>(), [1, 3, 5, 7]); /// assert_eq!(odds.keys().copied().collect::<Vec<_>>(), [1, 3, 5, 7]);
/// ``` /// ```
#[unstable(feature = "btree_drain_filter", issue = "70530")] #[unstable(feature = "btree_extract_if", issue = "70530")]
pub fn drain_filter<F>(&mut self, pred: F) -> DrainFilter<'_, K, V, F, A> pub fn extract_if<F>(&mut self, pred: F) -> ExtractIf<'_, K, V, F, A>
where where
K: Ord, K: Ord,
F: FnMut(&K, &mut V) -> bool, F: FnMut(&K, &mut V) -> bool,
{ {
let (inner, alloc) = self.drain_filter_inner(); let (inner, alloc) = self.extract_if_inner();
DrainFilter { pred, inner, alloc } ExtractIf { pred, inner, alloc }
} }
pub(super) fn drain_filter_inner(&mut self) -> (DrainFilterInner<'_, K, V>, A) pub(super) fn extract_if_inner(&mut self) -> (ExtractIfInner<'_, K, V>, A)
where where
K: Ord, K: Ord,
{ {
@ -1433,7 +1433,7 @@ impl<K, V, A: Allocator + Clone> BTreeMap<K, V, A> {
let (root, dormant_root) = DormantMutRef::new(root); let (root, dormant_root) = DormantMutRef::new(root);
let front = root.borrow_mut().first_leaf_edge(); let front = root.borrow_mut().first_leaf_edge();
( (
DrainFilterInner { ExtractIfInner {
length: &mut self.length, length: &mut self.length,
dormant_root: Some(dormant_root), dormant_root: Some(dormant_root),
cur_leaf_edge: Some(front), cur_leaf_edge: Some(front),
@ -1442,7 +1442,7 @@ impl<K, V, A: Allocator + Clone> BTreeMap<K, V, A> {
) )
} else { } else {
( (
DrainFilterInner { ExtractIfInner {
length: &mut self.length, length: &mut self.length,
dormant_root: None, dormant_root: None,
cur_leaf_edge: None, cur_leaf_edge: None,
@ -1896,10 +1896,10 @@ impl<K, V> Default for Values<'_, K, V> {
} }
} }
/// An iterator produced by calling `drain_filter` on BTreeMap. /// An iterator produced by calling `extract_if` on BTreeMap.
#[unstable(feature = "btree_drain_filter", issue = "70530")] #[unstable(feature = "btree_extract_if", issue = "70530")]
#[must_use = "iterators are lazy and do nothing unless consumed"] #[must_use = "iterators are lazy and do nothing unless consumed"]
pub struct DrainFilter< pub struct ExtractIf<
'a, 'a,
K, K,
V, V,
@ -1909,13 +1909,13 @@ pub struct DrainFilter<
F: 'a + FnMut(&K, &mut V) -> bool, F: 'a + FnMut(&K, &mut V) -> bool,
{ {
pred: F, pred: F,
inner: DrainFilterInner<'a, K, V>, inner: ExtractIfInner<'a, K, V>,
/// The BTreeMap will outlive this IntoIter so we don't care about drop order for `alloc`. /// The BTreeMap will outlive this IntoIter so we don't care about drop order for `alloc`.
alloc: A, alloc: A,
} }
/// Most of the implementation of DrainFilter are generic over the type /// Most of the implementation of ExtractIf are generic over the type
/// of the predicate, thus also serving for BTreeSet::DrainFilter. /// of the predicate, thus also serving for BTreeSet::ExtractIf.
pub(super) struct DrainFilterInner<'a, K, V> { pub(super) struct ExtractIfInner<'a, K, V> {
/// Reference to the length field in the borrowed map, updated live. /// Reference to the length field in the borrowed map, updated live.
length: &'a mut usize, length: &'a mut usize,
/// Buried reference to the root field in the borrowed map. /// Buried reference to the root field in the borrowed map.
@ -1927,20 +1927,20 @@ pub(super) struct DrainFilterInner<'a, K, V> {
cur_leaf_edge: Option<Handle<NodeRef<marker::Mut<'a>, K, V, marker::Leaf>, marker::Edge>>, cur_leaf_edge: Option<Handle<NodeRef<marker::Mut<'a>, K, V, marker::Leaf>, marker::Edge>>,
} }
#[unstable(feature = "btree_drain_filter", issue = "70530")] #[unstable(feature = "btree_extract_if", issue = "70530")]
impl<K, V, F> fmt::Debug for DrainFilter<'_, K, V, F> impl<K, V, F> fmt::Debug for ExtractIf<'_, K, V, F>
where where
K: fmt::Debug, K: fmt::Debug,
V: fmt::Debug, V: fmt::Debug,
F: FnMut(&K, &mut V) -> bool, F: FnMut(&K, &mut V) -> bool,
{ {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.debug_tuple("DrainFilter").field(&self.inner.peek()).finish() f.debug_tuple("ExtractIf").field(&self.inner.peek()).finish()
} }
} }
#[unstable(feature = "btree_drain_filter", issue = "70530")] #[unstable(feature = "btree_extract_if", issue = "70530")]
impl<K, V, F, A: Allocator + Clone> Iterator for DrainFilter<'_, K, V, F, A> impl<K, V, F, A: Allocator + Clone> Iterator for ExtractIf<'_, K, V, F, A>
where where
F: FnMut(&K, &mut V) -> bool, F: FnMut(&K, &mut V) -> bool,
{ {
@ -1955,14 +1955,14 @@ where
} }
} }
impl<'a, K, V> DrainFilterInner<'a, K, V> { impl<'a, K, V> ExtractIfInner<'a, K, V> {
/// Allow Debug implementations to predict the next element. /// Allow Debug implementations to predict the next element.
pub(super) fn peek(&self) -> Option<(&K, &V)> { pub(super) fn peek(&self) -> Option<(&K, &V)> {
let edge = self.cur_leaf_edge.as_ref()?; let edge = self.cur_leaf_edge.as_ref()?;
edge.reborrow().next_kv().ok().map(Handle::into_kv) edge.reborrow().next_kv().ok().map(Handle::into_kv)
} }
/// Implementation of a typical `DrainFilter::next` method, given the predicate. /// Implementation of a typical `ExtractIf::next` method, given the predicate.
pub(super) fn next<F, A: Allocator + Clone>(&mut self, pred: &mut F, alloc: A) -> Option<(K, V)> pub(super) fn next<F, A: Allocator + Clone>(&mut self, pred: &mut F, alloc: A) -> Option<(K, V)>
where where
F: FnMut(&K, &mut V) -> bool, F: FnMut(&K, &mut V) -> bool,
@ -1989,7 +1989,7 @@ impl<'a, K, V> DrainFilterInner<'a, K, V> {
None None
} }
/// Implementation of a typical `DrainFilter::size_hint` method. /// Implementation of a typical `ExtractIf::size_hint` method.
pub(super) fn size_hint(&self) -> (usize, Option<usize>) { pub(super) fn size_hint(&self) -> (usize, Option<usize>) {
// In most of the btree iterators, `self.length` is the number of elements // In most of the btree iterators, `self.length` is the number of elements
// yet to be visited. Here, it includes elements that were visited and that // yet to be visited. Here, it includes elements that were visited and that
@ -1999,8 +1999,8 @@ impl<'a, K, V> DrainFilterInner<'a, K, V> {
} }
} }
#[unstable(feature = "btree_drain_filter", issue = "70530")] #[unstable(feature = "btree_extract_if", issue = "70530")]
impl<K, V, F> FusedIterator for DrainFilter<'_, K, V, F> where F: FnMut(&K, &mut V) -> bool {} impl<K, V, F> FusedIterator for ExtractIf<'_, K, V, F> where F: FnMut(&K, &mut V) -> bool {}
#[stable(feature = "btree_range", since = "1.17.0")] #[stable(feature = "btree_range", since = "1.17.0")]
impl<'a, K, V> Iterator for Range<'a, K, V> { impl<'a, K, V> Iterator for Range<'a, K, V> {

View File

@ -941,13 +941,13 @@ fn test_retain() {
assert_eq!(map[&6], 60); assert_eq!(map[&6], 60);
} }
mod test_drain_filter { mod test_extract_if {
use super::*; use super::*;
#[test] #[test]
fn empty() { fn empty() {
let mut map: BTreeMap<i32, i32> = BTreeMap::new(); let mut map: BTreeMap<i32, i32> = BTreeMap::new();
map.drain_filter(|_, _| unreachable!("there's nothing to decide on")).for_each(drop); map.extract_if(|_, _| unreachable!("there's nothing to decide on")).for_each(drop);
assert_eq!(map.height(), None); assert_eq!(map.height(), None);
map.check(); map.check();
} }
@ -957,7 +957,7 @@ mod test_drain_filter {
fn consumed_keeping_all() { fn consumed_keeping_all() {
let pairs = (0..3).map(|i| (i, i)); let pairs = (0..3).map(|i| (i, i));
let mut map = BTreeMap::from_iter(pairs); let mut map = BTreeMap::from_iter(pairs);
assert!(map.drain_filter(|_, _| false).eq(iter::empty())); assert!(map.extract_if(|_, _| false).eq(iter::empty()));
map.check(); map.check();
} }
@ -966,7 +966,7 @@ mod test_drain_filter {
fn consumed_removing_all() { fn consumed_removing_all() {
let pairs = (0..3).map(|i| (i, i)); let pairs = (0..3).map(|i| (i, i));
let mut map = BTreeMap::from_iter(pairs.clone()); let mut map = BTreeMap::from_iter(pairs.clone());
assert!(map.drain_filter(|_, _| true).eq(pairs)); assert!(map.extract_if(|_, _| true).eq(pairs));
assert!(map.is_empty()); assert!(map.is_empty());
map.check(); map.check();
} }
@ -977,7 +977,7 @@ mod test_drain_filter {
let pairs = (0..3).map(|i| (i, i)); let pairs = (0..3).map(|i| (i, i));
let mut map = BTreeMap::from_iter(pairs); let mut map = BTreeMap::from_iter(pairs);
assert!( assert!(
map.drain_filter(|_, v| { map.extract_if(|_, v| {
*v += 6; *v += 6;
false false
}) })
@ -994,7 +994,7 @@ mod test_drain_filter {
let pairs = (0..3).map(|i| (i, i)); let pairs = (0..3).map(|i| (i, i));
let mut map = BTreeMap::from_iter(pairs); let mut map = BTreeMap::from_iter(pairs);
assert!( assert!(
map.drain_filter(|_, v| { map.extract_if(|_, v| {
*v += 6; *v += 6;
true true
}) })
@ -1008,7 +1008,7 @@ mod test_drain_filter {
fn underfull_keeping_all() { fn underfull_keeping_all() {
let pairs = (0..3).map(|i| (i, i)); let pairs = (0..3).map(|i| (i, i));
let mut map = BTreeMap::from_iter(pairs); let mut map = BTreeMap::from_iter(pairs);
map.drain_filter(|_, _| false).for_each(drop); map.extract_if(|_, _| false).for_each(drop);
assert!(map.keys().copied().eq(0..3)); assert!(map.keys().copied().eq(0..3));
map.check(); map.check();
} }
@ -1018,7 +1018,7 @@ mod test_drain_filter {
let pairs = (0..3).map(|i| (i, i)); let pairs = (0..3).map(|i| (i, i));
for doomed in 0..3 { for doomed in 0..3 {
let mut map = BTreeMap::from_iter(pairs.clone()); let mut map = BTreeMap::from_iter(pairs.clone());
map.drain_filter(|i, _| *i == doomed).for_each(drop); map.extract_if(|i, _| *i == doomed).for_each(drop);
assert_eq!(map.len(), 2); assert_eq!(map.len(), 2);
map.check(); map.check();
} }
@ -1029,7 +1029,7 @@ mod test_drain_filter {
let pairs = (0..3).map(|i| (i, i)); let pairs = (0..3).map(|i| (i, i));
for sacred in 0..3 { for sacred in 0..3 {
let mut map = BTreeMap::from_iter(pairs.clone()); let mut map = BTreeMap::from_iter(pairs.clone());
map.drain_filter(|i, _| *i != sacred).for_each(drop); map.extract_if(|i, _| *i != sacred).for_each(drop);
assert!(map.keys().copied().eq(sacred..=sacred)); assert!(map.keys().copied().eq(sacred..=sacred));
map.check(); map.check();
} }
@ -1039,7 +1039,7 @@ mod test_drain_filter {
fn underfull_removing_all() { fn underfull_removing_all() {
let pairs = (0..3).map(|i| (i, i)); let pairs = (0..3).map(|i| (i, i));
let mut map = BTreeMap::from_iter(pairs); let mut map = BTreeMap::from_iter(pairs);
map.drain_filter(|_, _| true).for_each(drop); map.extract_if(|_, _| true).for_each(drop);
assert!(map.is_empty()); assert!(map.is_empty());
map.check(); map.check();
} }
@ -1048,7 +1048,7 @@ mod test_drain_filter {
fn height_0_keeping_all() { fn height_0_keeping_all() {
let pairs = (0..node::CAPACITY).map(|i| (i, i)); let pairs = (0..node::CAPACITY).map(|i| (i, i));
let mut map = BTreeMap::from_iter(pairs); let mut map = BTreeMap::from_iter(pairs);
map.drain_filter(|_, _| false).for_each(drop); map.extract_if(|_, _| false).for_each(drop);
assert!(map.keys().copied().eq(0..node::CAPACITY)); assert!(map.keys().copied().eq(0..node::CAPACITY));
map.check(); map.check();
} }
@ -1058,7 +1058,7 @@ mod test_drain_filter {
let pairs = (0..node::CAPACITY).map(|i| (i, i)); let pairs = (0..node::CAPACITY).map(|i| (i, i));
for doomed in 0..node::CAPACITY { for doomed in 0..node::CAPACITY {
let mut map = BTreeMap::from_iter(pairs.clone()); let mut map = BTreeMap::from_iter(pairs.clone());
map.drain_filter(|i, _| *i == doomed).for_each(drop); map.extract_if(|i, _| *i == doomed).for_each(drop);
assert_eq!(map.len(), node::CAPACITY - 1); assert_eq!(map.len(), node::CAPACITY - 1);
map.check(); map.check();
} }
@ -1069,7 +1069,7 @@ mod test_drain_filter {
let pairs = (0..node::CAPACITY).map(|i| (i, i)); let pairs = (0..node::CAPACITY).map(|i| (i, i));
for sacred in 0..node::CAPACITY { for sacred in 0..node::CAPACITY {
let mut map = BTreeMap::from_iter(pairs.clone()); let mut map = BTreeMap::from_iter(pairs.clone());
map.drain_filter(|i, _| *i != sacred).for_each(drop); map.extract_if(|i, _| *i != sacred).for_each(drop);
assert!(map.keys().copied().eq(sacred..=sacred)); assert!(map.keys().copied().eq(sacred..=sacred));
map.check(); map.check();
} }
@ -1079,7 +1079,7 @@ mod test_drain_filter {
fn height_0_removing_all() { fn height_0_removing_all() {
let pairs = (0..node::CAPACITY).map(|i| (i, i)); let pairs = (0..node::CAPACITY).map(|i| (i, i));
let mut map = BTreeMap::from_iter(pairs); let mut map = BTreeMap::from_iter(pairs);
map.drain_filter(|_, _| true).for_each(drop); map.extract_if(|_, _| true).for_each(drop);
assert!(map.is_empty()); assert!(map.is_empty());
map.check(); map.check();
} }
@ -1087,7 +1087,7 @@ mod test_drain_filter {
#[test] #[test]
fn height_0_keeping_half() { fn height_0_keeping_half() {
let mut map = BTreeMap::from_iter((0..16).map(|i| (i, i))); let mut map = BTreeMap::from_iter((0..16).map(|i| (i, i)));
assert_eq!(map.drain_filter(|i, _| *i % 2 == 0).count(), 8); assert_eq!(map.extract_if(|i, _| *i % 2 == 0).count(), 8);
assert_eq!(map.len(), 8); assert_eq!(map.len(), 8);
map.check(); map.check();
} }
@ -1096,7 +1096,7 @@ mod test_drain_filter {
fn height_1_removing_all() { fn height_1_removing_all() {
let pairs = (0..MIN_INSERTS_HEIGHT_1).map(|i| (i, i)); let pairs = (0..MIN_INSERTS_HEIGHT_1).map(|i| (i, i));
let mut map = BTreeMap::from_iter(pairs); let mut map = BTreeMap::from_iter(pairs);
map.drain_filter(|_, _| true).for_each(drop); map.extract_if(|_, _| true).for_each(drop);
assert!(map.is_empty()); assert!(map.is_empty());
map.check(); map.check();
} }
@ -1106,7 +1106,7 @@ mod test_drain_filter {
let pairs = (0..MIN_INSERTS_HEIGHT_1).map(|i| (i, i)); let pairs = (0..MIN_INSERTS_HEIGHT_1).map(|i| (i, i));
for doomed in 0..MIN_INSERTS_HEIGHT_1 { for doomed in 0..MIN_INSERTS_HEIGHT_1 {
let mut map = BTreeMap::from_iter(pairs.clone()); let mut map = BTreeMap::from_iter(pairs.clone());
map.drain_filter(|i, _| *i == doomed).for_each(drop); map.extract_if(|i, _| *i == doomed).for_each(drop);
assert_eq!(map.len(), MIN_INSERTS_HEIGHT_1 - 1); assert_eq!(map.len(), MIN_INSERTS_HEIGHT_1 - 1);
map.check(); map.check();
} }
@ -1117,7 +1117,7 @@ mod test_drain_filter {
let pairs = (0..MIN_INSERTS_HEIGHT_1).map(|i| (i, i)); let pairs = (0..MIN_INSERTS_HEIGHT_1).map(|i| (i, i));
for sacred in 0..MIN_INSERTS_HEIGHT_1 { for sacred in 0..MIN_INSERTS_HEIGHT_1 {
let mut map = BTreeMap::from_iter(pairs.clone()); let mut map = BTreeMap::from_iter(pairs.clone());
map.drain_filter(|i, _| *i != sacred).for_each(drop); map.extract_if(|i, _| *i != sacred).for_each(drop);
assert!(map.keys().copied().eq(sacred..=sacred)); assert!(map.keys().copied().eq(sacred..=sacred));
map.check(); map.check();
} }
@ -1128,7 +1128,7 @@ mod test_drain_filter {
let pairs = (0..MIN_INSERTS_HEIGHT_2).map(|i| (i, i)); let pairs = (0..MIN_INSERTS_HEIGHT_2).map(|i| (i, i));
for doomed in (0..MIN_INSERTS_HEIGHT_2).step_by(12) { for doomed in (0..MIN_INSERTS_HEIGHT_2).step_by(12) {
let mut map = BTreeMap::from_iter(pairs.clone()); let mut map = BTreeMap::from_iter(pairs.clone());
map.drain_filter(|i, _| *i == doomed).for_each(drop); map.extract_if(|i, _| *i == doomed).for_each(drop);
assert_eq!(map.len(), MIN_INSERTS_HEIGHT_2 - 1); assert_eq!(map.len(), MIN_INSERTS_HEIGHT_2 - 1);
map.check(); map.check();
} }
@ -1139,7 +1139,7 @@ mod test_drain_filter {
let pairs = (0..MIN_INSERTS_HEIGHT_2).map(|i| (i, i)); let pairs = (0..MIN_INSERTS_HEIGHT_2).map(|i| (i, i));
for sacred in (0..MIN_INSERTS_HEIGHT_2).step_by(12) { for sacred in (0..MIN_INSERTS_HEIGHT_2).step_by(12) {
let mut map = BTreeMap::from_iter(pairs.clone()); let mut map = BTreeMap::from_iter(pairs.clone());
map.drain_filter(|i, _| *i != sacred).for_each(drop); map.extract_if(|i, _| *i != sacred).for_each(drop);
assert!(map.keys().copied().eq(sacred..=sacred)); assert!(map.keys().copied().eq(sacred..=sacred));
map.check(); map.check();
} }
@ -1149,7 +1149,7 @@ mod test_drain_filter {
fn height_2_removing_all() { fn height_2_removing_all() {
let pairs = (0..MIN_INSERTS_HEIGHT_2).map(|i| (i, i)); let pairs = (0..MIN_INSERTS_HEIGHT_2).map(|i| (i, i));
let mut map = BTreeMap::from_iter(pairs); let mut map = BTreeMap::from_iter(pairs);
map.drain_filter(|_, _| true).for_each(drop); map.extract_if(|_, _| true).for_each(drop);
assert!(map.is_empty()); assert!(map.is_empty());
map.check(); map.check();
} }
@ -1165,7 +1165,7 @@ mod test_drain_filter {
map.insert(b.spawn(Panic::InDrop), ()); map.insert(b.spawn(Panic::InDrop), ());
map.insert(c.spawn(Panic::Never), ()); map.insert(c.spawn(Panic::Never), ());
catch_unwind(move || map.drain_filter(|dummy, _| dummy.query(true)).for_each(drop)) catch_unwind(move || map.extract_if(|dummy, _| dummy.query(true)).for_each(drop))
.unwrap_err(); .unwrap_err();
assert_eq!(a.queried(), 1); assert_eq!(a.queried(), 1);
@ -1188,7 +1188,7 @@ mod test_drain_filter {
map.insert(c.spawn(Panic::InQuery), ()); map.insert(c.spawn(Panic::InQuery), ());
catch_unwind(AssertUnwindSafe(|| { catch_unwind(AssertUnwindSafe(|| {
map.drain_filter(|dummy, _| dummy.query(true)).for_each(drop) map.extract_if(|dummy, _| dummy.query(true)).for_each(drop)
})) }))
.unwrap_err(); .unwrap_err();
@ -1217,7 +1217,7 @@ mod test_drain_filter {
map.insert(c.spawn(Panic::InQuery), ()); map.insert(c.spawn(Panic::InQuery), ());
{ {
let mut it = map.drain_filter(|dummy, _| dummy.query(true)); let mut it = map.extract_if(|dummy, _| dummy.query(true));
catch_unwind(AssertUnwindSafe(|| while it.next().is_some() {})).unwrap_err(); catch_unwind(AssertUnwindSafe(|| while it.next().is_some() {})).unwrap_err();
// Iterator behaviour after a panic is explicitly unspecified, // Iterator behaviour after a panic is explicitly unspecified,
// so this is just the current implementation: // so this is just the current implementation:
@ -1660,8 +1660,8 @@ fn assert_sync() {
v.into_values() v.into_values()
} }
fn drain_filter<T: Sync + Ord>(v: &mut BTreeMap<T, T>) -> impl Sync + '_ { fn extract_if<T: Sync + Ord>(v: &mut BTreeMap<T, T>) -> impl Sync + '_ {
v.drain_filter(|_, _| false) v.extract_if(|_, _| false)
} }
fn iter<T: Sync>(v: &BTreeMap<T, T>) -> impl Sync + '_ { fn iter<T: Sync>(v: &BTreeMap<T, T>) -> impl Sync + '_ {
@ -1729,8 +1729,8 @@ fn assert_send() {
v.into_values() v.into_values()
} }
fn drain_filter<T: Send + Ord>(v: &mut BTreeMap<T, T>) -> impl Send + '_ { fn extract_if<T: Send + Ord>(v: &mut BTreeMap<T, T>) -> impl Send + '_ {
v.drain_filter(|_, _| false) v.extract_if(|_, _| false)
} }
fn iter<T: Send + Sync>(v: &BTreeMap<T, T>) -> impl Send + '_ { fn iter<T: Send + Sync>(v: &BTreeMap<T, T>) -> impl Send + '_ {

View File

@ -999,7 +999,7 @@ impl<T, A: Allocator + Clone> BTreeSet<T, A> {
T: Ord, T: Ord,
F: FnMut(&T) -> bool, F: FnMut(&T) -> bool,
{ {
self.drain_filter(|v| !f(v)).for_each(drop); self.extract_if(|v| !f(v)).for_each(drop);
} }
/// Moves all elements from `other` into `self`, leaving `other` empty. /// Moves all elements from `other` into `self`, leaving `other` empty.
@ -1084,7 +1084,7 @@ impl<T, A: Allocator + Clone> BTreeSet<T, A> {
/// yielded. If the closure returns `false`, or panics, the element remains /// yielded. If the closure returns `false`, or panics, the element remains
/// in the set and will not be yielded. /// in the set and will not be yielded.
/// ///
/// If the returned `DrainFilter` 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.
/// ///
@ -1094,23 +1094,23 @@ impl<T, A: Allocator + Clone> BTreeSet<T, A> {
/// Splitting a set into even and odd values, reusing the original set: /// Splitting a set into even and odd values, reusing the original set:
/// ///
/// ``` /// ```
/// #![feature(btree_drain_filter)] /// #![feature(btree_extract_if)]
/// use std::collections::BTreeSet; /// use std::collections::BTreeSet;
/// ///
/// let mut set: BTreeSet<i32> = (0..8).collect(); /// let mut set: BTreeSet<i32> = (0..8).collect();
/// let evens: BTreeSet<_> = set.drain_filter(|v| v % 2 == 0).collect(); /// let evens: BTreeSet<_> = set.extract_if(|v| v % 2 == 0).collect();
/// let odds = set; /// let odds = set;
/// assert_eq!(evens.into_iter().collect::<Vec<_>>(), vec![0, 2, 4, 6]); /// assert_eq!(evens.into_iter().collect::<Vec<_>>(), vec![0, 2, 4, 6]);
/// assert_eq!(odds.into_iter().collect::<Vec<_>>(), vec![1, 3, 5, 7]); /// assert_eq!(odds.into_iter().collect::<Vec<_>>(), vec![1, 3, 5, 7]);
/// ``` /// ```
#[unstable(feature = "btree_drain_filter", issue = "70530")] #[unstable(feature = "btree_extract_if", issue = "70530")]
pub fn drain_filter<'a, F>(&'a mut self, pred: F) -> DrainFilter<'a, T, F, A> pub fn extract_if<'a, F>(&'a mut self, pred: F) -> ExtractIf<'a, T, F, A>
where where
T: Ord, T: Ord,
F: 'a + FnMut(&T) -> bool, F: 'a + FnMut(&T) -> bool,
{ {
let (inner, alloc) = self.map.drain_filter_inner(); let (inner, alloc) = self.map.extract_if_inner();
DrainFilter { pred, inner, alloc } ExtractIf { pred, inner, alloc }
} }
/// Gets an iterator that visits the elements in the `BTreeSet` in ascending /// Gets an iterator that visits the elements in the `BTreeSet` in ascending
@ -1272,10 +1272,10 @@ impl<'a, T, A: Allocator + Clone> IntoIterator for &'a BTreeSet<T, A> {
} }
} }
/// An iterator produced by calling `drain_filter` on BTreeSet. /// An iterator produced by calling `extract_if` on BTreeSet.
#[unstable(feature = "btree_drain_filter", issue = "70530")] #[unstable(feature = "btree_extract_if", issue = "70530")]
#[must_use = "iterators are lazy and do nothing unless consumed"] #[must_use = "iterators are lazy and do nothing unless consumed"]
pub struct DrainFilter< pub struct ExtractIf<
'a, 'a,
T, T,
F, F,
@ -1285,24 +1285,24 @@ pub struct DrainFilter<
F: 'a + FnMut(&T) -> bool, F: 'a + FnMut(&T) -> bool,
{ {
pred: F, pred: F,
inner: super::map::DrainFilterInner<'a, T, SetValZST>, inner: super::map::ExtractIfInner<'a, T, SetValZST>,
/// The BTreeMap will outlive this IntoIter so we don't care about drop order for `alloc`. /// The BTreeMap will outlive this IntoIter so we don't care about drop order for `alloc`.
alloc: A, alloc: A,
} }
#[unstable(feature = "btree_drain_filter", issue = "70530")] #[unstable(feature = "btree_extract_if", issue = "70530")]
impl<T, F, A: Allocator + Clone> fmt::Debug for DrainFilter<'_, T, F, A> impl<T, F, A: Allocator + Clone> fmt::Debug for ExtractIf<'_, T, F, A>
where where
T: fmt::Debug, T: fmt::Debug,
F: FnMut(&T) -> bool, F: FnMut(&T) -> bool,
{ {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.debug_tuple("DrainFilter").field(&self.inner.peek().map(|(k, _)| k)).finish() f.debug_tuple("ExtractIf").field(&self.inner.peek().map(|(k, _)| k)).finish()
} }
} }
#[unstable(feature = "btree_drain_filter", issue = "70530")] #[unstable(feature = "btree_extract_if", issue = "70530")]
impl<'a, T, F, A: Allocator + Clone> Iterator for DrainFilter<'_, T, F, A> impl<'a, T, F, A: Allocator + Clone> Iterator for ExtractIf<'_, T, F, A>
where where
F: 'a + FnMut(&T) -> bool, F: 'a + FnMut(&T) -> bool,
{ {
@ -1319,11 +1319,8 @@ where
} }
} }
#[unstable(feature = "btree_drain_filter", issue = "70530")] #[unstable(feature = "btree_extract_if", issue = "70530")]
impl<T, F, A: Allocator + Clone> FusedIterator for DrainFilter<'_, T, F, A> where impl<T, F, A: Allocator + Clone> FusedIterator for ExtractIf<'_, T, F, A> where F: FnMut(&T) -> bool {}
F: FnMut(&T) -> bool
{
}
#[stable(feature = "rust1", since = "1.0.0")] #[stable(feature = "rust1", since = "1.0.0")]
impl<T: Ord, A: Allocator + Clone> Extend<T> for BTreeSet<T, A> { impl<T: Ord, A: Allocator + Clone> Extend<T> for BTreeSet<T, A> {

View File

@ -366,19 +366,19 @@ fn test_retain() {
} }
#[test] #[test]
fn test_drain_filter() { fn test_extract_if() {
let mut x = BTreeSet::from([1]); let mut x = BTreeSet::from([1]);
let mut y = BTreeSet::from([1]); let mut y = BTreeSet::from([1]);
x.drain_filter(|_| true).for_each(drop); x.extract_if(|_| true).for_each(drop);
y.drain_filter(|_| false).for_each(drop); y.extract_if(|_| false).for_each(drop);
assert_eq!(x.len(), 0); assert_eq!(x.len(), 0);
assert_eq!(y.len(), 1); assert_eq!(y.len(), 1);
} }
#[test] #[test]
#[cfg_attr(not(panic = "unwind"), ignore = "test requires unwinding support")] #[cfg_attr(not(panic = "unwind"), ignore = "test requires unwinding support")]
fn test_drain_filter_drop_panic_leak() { fn test_extract_if_drop_panic_leak() {
let a = CrashTestDummy::new(0); let a = CrashTestDummy::new(0);
let b = CrashTestDummy::new(1); let b = CrashTestDummy::new(1);
let c = CrashTestDummy::new(2); let c = CrashTestDummy::new(2);
@ -387,7 +387,7 @@ fn test_drain_filter_drop_panic_leak() {
set.insert(b.spawn(Panic::InDrop)); set.insert(b.spawn(Panic::InDrop));
set.insert(c.spawn(Panic::Never)); set.insert(c.spawn(Panic::Never));
catch_unwind(move || set.drain_filter(|dummy| dummy.query(true)).for_each(drop)).ok(); catch_unwind(move || set.extract_if(|dummy| dummy.query(true)).for_each(drop)).ok();
assert_eq!(a.queried(), 1); assert_eq!(a.queried(), 1);
assert_eq!(b.queried(), 1); assert_eq!(b.queried(), 1);
@ -399,7 +399,7 @@ fn test_drain_filter_drop_panic_leak() {
#[test] #[test]
#[cfg_attr(not(panic = "unwind"), ignore = "test requires unwinding support")] #[cfg_attr(not(panic = "unwind"), ignore = "test requires unwinding support")]
fn test_drain_filter_pred_panic_leak() { fn test_extract_if_pred_panic_leak() {
let a = CrashTestDummy::new(0); let a = CrashTestDummy::new(0);
let b = CrashTestDummy::new(1); let b = CrashTestDummy::new(1);
let c = CrashTestDummy::new(2); let c = CrashTestDummy::new(2);
@ -408,9 +408,7 @@ fn test_drain_filter_pred_panic_leak() {
set.insert(b.spawn(Panic::InQuery)); set.insert(b.spawn(Panic::InQuery));
set.insert(c.spawn(Panic::InQuery)); set.insert(c.spawn(Panic::InQuery));
catch_unwind(AssertUnwindSafe(|| { catch_unwind(AssertUnwindSafe(|| set.extract_if(|dummy| dummy.query(true)).for_each(drop)))
set.drain_filter(|dummy| dummy.query(true)).for_each(drop)
}))
.ok(); .ok();
assert_eq!(a.queried(), 1); assert_eq!(a.queried(), 1);
@ -608,8 +606,8 @@ fn assert_sync() {
v.range(..) v.range(..)
} }
fn drain_filter<T: Sync + Ord>(v: &mut BTreeSet<T>) -> impl Sync + '_ { fn extract_if<T: Sync + Ord>(v: &mut BTreeSet<T>) -> impl Sync + '_ {
v.drain_filter(|_| false) v.extract_if(|_| false)
} }
fn difference<T: Sync + Ord>(v: &BTreeSet<T>) -> impl Sync + '_ { fn difference<T: Sync + Ord>(v: &BTreeSet<T>) -> impl Sync + '_ {
@ -647,8 +645,8 @@ fn assert_send() {
v.range(..) v.range(..)
} }
fn drain_filter<T: Send + Ord>(v: &mut BTreeSet<T>) -> impl Send + '_ { fn extract_if<T: Send + Ord>(v: &mut BTreeSet<T>) -> impl Send + '_ {
v.drain_filter(|_| false) v.extract_if(|_| false)
} }
fn difference<T: Send + Sync + Ord>(v: &BTreeSet<T>) -> impl Send + '_ { fn difference<T: Send + Sync + Ord>(v: &BTreeSet<T>) -> impl Send + '_ {

View File

@ -1030,11 +1030,11 @@ impl<T, A: Allocator> LinkedList<T, A> {
/// If the closure returns false, the element will remain in the list and will not be yielded /// If the closure returns false, the element will remain in the list and will not be yielded
/// by the iterator. /// by the iterator.
/// ///
/// If the returned `DrainFilter` 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 `drain_filter().for_each(drop)` if you do not need the returned iterator. /// Use `extract_if().for_each(drop)` if you do not need the returned iterator.
/// ///
/// Note that `drain_filter` lets you mutate every element in the filter closure, regardless of /// Note that `extract_if` lets you mutate every element in the filter closure, regardless of
/// whether you choose to keep or remove it. /// whether you choose to keep or remove it.
/// ///
/// # Examples /// # Examples
@ -1042,20 +1042,20 @@ impl<T, A: Allocator> LinkedList<T, A> {
/// Splitting a list into evens and odds, reusing the original list: /// Splitting a list into evens and odds, reusing the original list:
/// ///
/// ``` /// ```
/// #![feature(drain_filter)] /// #![feature(extract_if)]
/// use std::collections::LinkedList; /// use std::collections::LinkedList;
/// ///
/// let mut numbers: LinkedList<u32> = LinkedList::new(); /// let mut numbers: LinkedList<u32> = LinkedList::new();
/// numbers.extend(&[1, 2, 3, 4, 5, 6, 8, 9, 11, 13, 14, 15]); /// numbers.extend(&[1, 2, 3, 4, 5, 6, 8, 9, 11, 13, 14, 15]);
/// ///
/// let evens = numbers.drain_filter(|x| *x % 2 == 0).collect::<LinkedList<_>>(); /// let evens = numbers.extract_if(|x| *x % 2 == 0).collect::<LinkedList<_>>();
/// let odds = numbers; /// let odds = numbers;
/// ///
/// assert_eq!(evens.into_iter().collect::<Vec<_>>(), vec![2, 4, 6, 8, 14]); /// assert_eq!(evens.into_iter().collect::<Vec<_>>(), vec![2, 4, 6, 8, 14]);
/// assert_eq!(odds.into_iter().collect::<Vec<_>>(), vec![1, 3, 5, 9, 11, 13, 15]); /// assert_eq!(odds.into_iter().collect::<Vec<_>>(), vec![1, 3, 5, 9, 11, 13, 15]);
/// ``` /// ```
#[unstable(feature = "drain_filter", reason = "recently added", issue = "43244")] #[unstable(feature = "extract_if", reason = "recently added", issue = "43244")]
pub fn drain_filter<F>(&mut self, filter: F) -> DrainFilter<'_, T, F, A> pub fn extract_if<F>(&mut self, filter: F) -> ExtractIf<'_, T, F, A>
where where
F: FnMut(&mut T) -> bool, F: FnMut(&mut T) -> bool,
{ {
@ -1063,7 +1063,7 @@ impl<T, A: Allocator> LinkedList<T, A> {
let it = self.head; let it = self.head;
let old_len = self.len; let old_len = self.len;
DrainFilter { list: self, it, pred: filter, idx: 0, old_len } ExtractIf { list: self, it, pred: filter, idx: 0, old_len }
} }
} }
@ -1807,10 +1807,10 @@ impl<'a, T, A: Allocator> CursorMut<'a, T, A> {
} }
} }
/// An iterator produced by calling `drain_filter` on LinkedList. /// An iterator produced by calling `extract_if` on LinkedList.
#[unstable(feature = "drain_filter", reason = "recently added", issue = "43244")] #[unstable(feature = "extract_if", reason = "recently added", issue = "43244")]
#[must_use = "iterators are lazy and do nothing unless consumed"] #[must_use = "iterators are lazy and do nothing unless consumed"]
pub struct DrainFilter< pub struct ExtractIf<
'a, 'a,
T: 'a, T: 'a,
F: 'a, F: 'a,
@ -1825,8 +1825,8 @@ pub struct DrainFilter<
old_len: usize, old_len: usize,
} }
#[unstable(feature = "drain_filter", reason = "recently added", issue = "43244")] #[unstable(feature = "extract_if", reason = "recently added", issue = "43244")]
impl<T, F, A: Allocator> Iterator for DrainFilter<'_, T, F, A> impl<T, F, A: Allocator> Iterator for ExtractIf<'_, T, F, A>
where where
F: FnMut(&mut T) -> bool, F: FnMut(&mut T) -> bool,
{ {
@ -1854,13 +1854,13 @@ where
} }
} }
#[unstable(feature = "drain_filter", reason = "recently added", issue = "43244")] #[unstable(feature = "extract_if", reason = "recently added", issue = "43244")]
impl<T: fmt::Debug, F> fmt::Debug for DrainFilter<'_, T, F> impl<T: fmt::Debug, F> fmt::Debug for ExtractIf<'_, T, F>
where where
F: FnMut(&mut T) -> bool, 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("DrainFilter").field(&self.list).finish() f.debug_tuple("ExtractIf").field(&self.list).finish()
} }
} }

View File

@ -540,10 +540,10 @@ fn test_show() {
} }
#[test] #[test]
fn drain_filter_test() { fn extract_if_test() {
let mut m: LinkedList<u32> = LinkedList::new(); let mut m: LinkedList<u32> = LinkedList::new();
m.extend(&[1, 2, 3, 4, 5, 6]); m.extend(&[1, 2, 3, 4, 5, 6]);
let deleted = m.drain_filter(|v| *v < 4).collect::<Vec<_>>(); let deleted = m.extract_if(|v| *v < 4).collect::<Vec<_>>();
check_links(&m); check_links(&m);
@ -555,7 +555,7 @@ fn drain_filter_test() {
fn drain_to_empty_test() { fn drain_to_empty_test() {
let mut m: LinkedList<u32> = LinkedList::new(); let mut m: LinkedList<u32> = LinkedList::new();
m.extend(&[1, 2, 3, 4, 5, 6]); m.extend(&[1, 2, 3, 4, 5, 6]);
let deleted = m.drain_filter(|_| true).collect::<Vec<_>>(); let deleted = m.extract_if(|_| true).collect::<Vec<_>>();
check_links(&m); check_links(&m);
@ -811,11 +811,11 @@ fn test_contains() {
} }
#[test] #[test]
fn drain_filter_empty() { fn extract_if_empty() {
let mut list: LinkedList<i32> = LinkedList::new(); let mut list: LinkedList<i32> = LinkedList::new();
{ {
let mut iter = list.drain_filter(|_| true); let mut iter = list.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)));
@ -828,13 +828,13 @@ fn drain_filter_empty() {
} }
#[test] #[test]
fn drain_filter_zst() { fn extract_if_zst() {
let mut list: LinkedList<_> = [(), (), (), (), ()].into_iter().collect(); let mut list: LinkedList<_> = [(), (), (), (), ()].into_iter().collect();
let initial_len = list.len(); let initial_len = list.len();
let mut count = 0; let mut count = 0;
{ {
let mut iter = list.drain_filter(|_| true); let mut iter = list.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;
@ -851,14 +851,14 @@ fn drain_filter_zst() {
} }
#[test] #[test]
fn drain_filter_false() { fn extract_if_false() {
let mut list: LinkedList<_> = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10].into_iter().collect(); let mut list: LinkedList<_> = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10].into_iter().collect();
let initial_len = list.len(); let initial_len = list.len();
let mut count = 0; let mut count = 0;
{ {
let mut iter = list.drain_filter(|_| false); let mut iter = list.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;
@ -874,14 +874,14 @@ fn drain_filter_false() {
} }
#[test] #[test]
fn drain_filter_true() { fn extract_if_true() {
let mut list: LinkedList<_> = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10].into_iter().collect(); let mut list: LinkedList<_> = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10].into_iter().collect();
let initial_len = list.len(); let initial_len = list.len();
let mut count = 0; let mut count = 0;
{ {
let mut iter = list.drain_filter(|_| true); let mut iter = list.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;
@ -898,7 +898,7 @@ fn drain_filter_true() {
} }
#[test] #[test]
fn drain_filter_complex() { fn extract_if_complex() {
{ {
// [+xxx++++++xxxxx++++x+x++] // [+xxx++++++xxxxx++++x+x++]
let mut list = [ let mut list = [
@ -908,7 +908,7 @@ fn drain_filter_complex() {
.into_iter() .into_iter()
.collect::<LinkedList<_>>(); .collect::<LinkedList<_>>();
let removed = list.drain_filter(|x| *x % 2 == 0).collect::<Vec<_>>(); let removed = list.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]);
@ -926,7 +926,7 @@ fn drain_filter_complex() {
.into_iter() .into_iter()
.collect::<LinkedList<_>>(); .collect::<LinkedList<_>>();
let removed = list.drain_filter(|x| *x % 2 == 0).collect::<Vec<_>>(); let removed = list.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]);
@ -944,7 +944,7 @@ fn drain_filter_complex() {
.into_iter() .into_iter()
.collect::<LinkedList<_>>(); .collect::<LinkedList<_>>();
let removed = list.drain_filter(|x| *x % 2 == 0).collect::<Vec<_>>(); let removed = list.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]);
@ -961,7 +961,7 @@ fn drain_filter_complex() {
.into_iter() .into_iter()
.collect::<LinkedList<_>>(); .collect::<LinkedList<_>>();
let removed = list.drain_filter(|x| *x % 2 == 0).collect::<Vec<_>>(); let removed = list.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]);
@ -975,7 +975,7 @@ fn drain_filter_complex() {
.into_iter() .into_iter()
.collect::<LinkedList<_>>(); .collect::<LinkedList<_>>();
let removed = list.drain_filter(|x| *x % 2 == 0).collect::<Vec<_>>(); let removed = list.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]);
@ -986,7 +986,7 @@ fn drain_filter_complex() {
#[test] #[test]
#[cfg_attr(not(panic = "unwind"), ignore = "test requires unwinding support")] #[cfg_attr(not(panic = "unwind"), ignore = "test requires unwinding support")]
fn drain_filter_drop_panic_leak() { fn extract_if_drop_panic_leak() {
let d0 = CrashTestDummy::new(0); let d0 = CrashTestDummy::new(0);
let d1 = CrashTestDummy::new(1); let d1 = CrashTestDummy::new(1);
let d2 = CrashTestDummy::new(2); let d2 = CrashTestDummy::new(2);
@ -1005,7 +1005,7 @@ fn drain_filter_drop_panic_leak() {
q.push_front(d1.spawn(Panic::InDrop)); q.push_front(d1.spawn(Panic::InDrop));
q.push_front(d0.spawn(Panic::Never)); q.push_front(d0.spawn(Panic::Never));
catch_unwind(AssertUnwindSafe(|| q.drain_filter(|_| true).for_each(drop))).unwrap_err(); catch_unwind(AssertUnwindSafe(|| q.extract_if(|_| true).for_each(drop))).unwrap_err();
assert_eq!(d0.dropped(), 1); assert_eq!(d0.dropped(), 1);
assert_eq!(d1.dropped(), 1); assert_eq!(d1.dropped(), 1);
@ -1026,7 +1026,7 @@ fn drain_filter_drop_panic_leak() {
#[test] #[test]
#[cfg_attr(not(panic = "unwind"), ignore = "test requires unwinding support")] #[cfg_attr(not(panic = "unwind"), ignore = "test requires unwinding support")]
fn drain_filter_pred_panic_leak() { fn extract_if_pred_panic_leak() {
static mut DROPS: i32 = 0; static mut DROPS: i32 = 0;
#[derive(Debug)] #[derive(Debug)]
@ -1051,7 +1051,7 @@ fn drain_filter_pred_panic_leak() {
q.push_front(D(0)); q.push_front(D(0));
catch_unwind(AssertUnwindSafe(|| { catch_unwind(AssertUnwindSafe(|| {
q.drain_filter(|item| if item.0 >= 2 { panic!() } else { true }).for_each(drop) q.extract_if(|item| if item.0 >= 2 { panic!() } else { true }).for_each(drop)
})) }))
.ok(); .ok();

View File

@ -6,21 +6,21 @@ use super::Vec;
/// An iterator which uses a closure to determine if an element should be removed. /// An iterator which uses a closure to determine if an element should be removed.
/// ///
/// This struct is created by [`Vec::drain_filter`]. /// This struct is created by [`Vec::extract_if`].
/// See its documentation for more. /// See its documentation for more.
/// ///
/// # Example /// # Example
/// ///
/// ``` /// ```
/// #![feature(drain_filter)] /// #![feature(extract_if)]
/// ///
/// let mut v = vec![0, 1, 2]; /// let mut v = vec![0, 1, 2];
/// let iter: std::vec::DrainFilter<'_, _, _> = v.drain_filter(|x| *x % 2 == 0); /// let iter: std::vec::ExtractIf<'_, _, _> = v.extract_if(|x| *x % 2 == 0);
/// ``` /// ```
#[unstable(feature = "drain_filter", reason = "recently added", issue = "43244")] #[unstable(feature = "extract_if", reason = "recently added", issue = "43244")]
#[derive(Debug)] #[derive(Debug)]
#[must_use = "iterators are lazy and do nothing unless consumed"] #[must_use = "iterators are lazy and do nothing unless consumed"]
pub struct DrainFilter< pub struct ExtractIf<
'a, 'a,
T, T,
F, F,
@ -39,13 +39,13 @@ pub struct DrainFilter<
pub(super) pred: F, pub(super) pred: F,
/// A flag that indicates a panic has occurred in the filter test predicate. /// 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 /// This is used as a hint in the drop implementation to prevent consumption
/// of the remainder of the `DrainFilter`. Any unprocessed items will be /// of the remainder of the `ExtractIf`. Any unprocessed items will be
/// backshifted in the `vec`, but no further items will be dropped or /// backshifted in the `vec`, but no further items will be dropped or
/// tested by the filter predicate. /// tested by the filter predicate.
pub(super) panic_flag: bool, pub(super) panic_flag: bool,
} }
impl<T, F, A: Allocator> DrainFilter<'_, T, F, A> impl<T, F, A: Allocator> ExtractIf<'_, T, F, A>
where where
F: FnMut(&mut T) -> bool, F: FnMut(&mut T) -> bool,
{ {
@ -57,8 +57,8 @@ where
} }
} }
#[unstable(feature = "drain_filter", reason = "recently added", issue = "43244")] #[unstable(feature = "extract_if", reason = "recently added", issue = "43244")]
impl<T, F, A: Allocator> Iterator for DrainFilter<'_, T, F, A> impl<T, F, A: Allocator> Iterator for ExtractIf<'_, T, F, A>
where where
F: FnMut(&mut T) -> bool, F: FnMut(&mut T) -> bool,
{ {
@ -95,8 +95,8 @@ where
} }
} }
#[unstable(feature = "drain_filter", reason = "recently added", issue = "43244")] #[unstable(feature = "extract_if", reason = "recently added", issue = "43244")]
impl<T, F, A: Allocator> Drop for DrainFilter<'_, T, F, A> impl<T, F, A: Allocator> Drop for ExtractIf<'_, T, F, A>
where where
F: FnMut(&mut T) -> bool, F: FnMut(&mut T) -> bool,
{ {

View File

@ -71,10 +71,10 @@ use crate::boxed::Box;
use crate::collections::TryReserveError; use crate::collections::TryReserveError;
use crate::raw_vec::RawVec; use crate::raw_vec::RawVec;
#[unstable(feature = "drain_filter", reason = "recently added", issue = "43244")] #[unstable(feature = "extract_if", reason = "recently added", issue = "43244")]
pub use self::drain_filter::DrainFilter; pub use self::extract_if::ExtractIf;
mod drain_filter; mod extract_if;
#[cfg(not(no_global_oom_handling))] #[cfg(not(no_global_oom_handling))]
#[stable(feature = "vec_splice", since = "1.21.0")] #[stable(feature = "vec_splice", since = "1.21.0")]
@ -2892,7 +2892,7 @@ impl<T, A: Allocator> Vec<T, A> {
/// 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.
/// ///
/// If the returned `DrainFilter` 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.
/// ///
@ -2916,10 +2916,10 @@ impl<T, A: Allocator> Vec<T, A> {
/// # assert_eq!(vec, vec![1, 4, 5]); /// # assert_eq!(vec, vec![1, 4, 5]);
/// ``` /// ```
/// ///
/// But `drain_filter` is easier to use. `drain_filter` 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 `drain_filter` also lets you mutate every element in the filter closure, /// Note that `extract_if` also lets you mutate every element in the filter closure,
/// regardless of whether you choose to keep or remove it. /// regardless of whether you choose to keep or remove it.
/// ///
/// # Examples /// # Examples
@ -2927,17 +2927,17 @@ impl<T, A: Allocator> Vec<T, A> {
/// Splitting an array into evens and odds, reusing the original allocation: /// Splitting an array into evens and odds, reusing the original allocation:
/// ///
/// ``` /// ```
/// #![feature(drain_filter)] /// #![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.drain_filter(|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]);
/// ``` /// ```
#[unstable(feature = "drain_filter", reason = "recently added", issue = "43244")] #[unstable(feature = "extract_if", reason = "recently added", issue = "43244")]
pub fn drain_filter<F>(&mut self, filter: F) -> DrainFilter<'_, T, F, A> pub fn extract_if<F>(&mut self, filter: F) -> ExtractIf<'_, T, F, A>
where where
F: FnMut(&mut T) -> bool, F: FnMut(&mut T) -> bool,
{ {
@ -2948,7 +2948,7 @@ impl<T, A: Allocator> Vec<T, A> {
self.set_len(0); self.set_len(0);
} }
DrainFilter { vec: self, idx: 0, del: 0, old_len, pred: filter, panic_flag: false } ExtractIf { vec: self, idx: 0, del: 0, old_len, pred: filter, panic_flag: false }
} }
} }

View File

@ -55,7 +55,7 @@ fn test_btree_map() {
require_send_sync(async { require_send_sync(async {
let _v = None::< let _v = None::<
alloc::collections::btree_map::DrainFilter< alloc::collections::btree_map::ExtractIf<
'_, '_,
&u32, &u32,
&u32, &u32,
@ -149,7 +149,7 @@ fn test_btree_set() {
}); });
require_send_sync(async { require_send_sync(async {
let _v = None::<alloc::collections::btree_set::DrainFilter<'_, &u32, fn(&&u32) -> bool>>; let _v = None::<alloc::collections::btree_set::ExtractIf<'_, &u32, fn(&&u32) -> bool>>;
async {}.await; async {}.await;
}); });
@ -238,7 +238,7 @@ fn test_linked_list() {
/* /*
require_send_sync(async { require_send_sync(async {
let _v = let _v =
None::<alloc::collections::linked_list::DrainFilter<'_, &u32, fn(&mut &u32) -> bool>>; None::<alloc::collections::linked_list::ExtractIf<'_, &u32, fn(&mut &u32) -> bool>>;
async {}.await; async {}.await;
}); });
*/ */

View File

@ -1,7 +1,7 @@
#![feature(allocator_api)] #![feature(allocator_api)]
#![feature(alloc_layout_extra)] #![feature(alloc_layout_extra)]
#![feature(assert_matches)] #![feature(assert_matches)]
#![feature(btree_drain_filter)] #![feature(btree_extract_if)]
#![feature(cow_is_borrowed)] #![feature(cow_is_borrowed)]
#![feature(const_cow_is_borrowed)] #![feature(const_cow_is_borrowed)]
#![feature(const_heap)] #![feature(const_heap)]
@ -10,7 +10,7 @@
#![feature(const_ptr_write)] #![feature(const_ptr_write)]
#![feature(const_try)] #![feature(const_try)]
#![feature(core_intrinsics)] #![feature(core_intrinsics)]
#![feature(drain_filter)] #![feature(extract_if)]
#![feature(exact_size_is_empty)] #![feature(exact_size_is_empty)]
#![feature(linked_list_cursors)] #![feature(linked_list_cursors)]
#![feature(map_try_insert)] #![feature(map_try_insert)]

View File

@ -1347,11 +1347,11 @@ fn overaligned_allocations() {
} }
#[test] #[test]
fn drain_filter_empty() { fn extract_if_empty() {
let mut vec: Vec<i32> = vec![]; let mut vec: Vec<i32> = vec![];
{ {
let mut iter = vec.drain_filter(|_| 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)));
@ -1363,12 +1363,12 @@ fn drain_filter_empty() {
} }
#[test] #[test]
fn drain_filter_zst() { fn extract_if_zst() {
let mut vec = vec![(), (), (), (), ()]; let mut vec = vec![(), (), (), (), ()];
let initial_len = vec.len(); let initial_len = vec.len();
let mut count = 0; let mut count = 0;
{ {
let mut iter = vec.drain_filter(|_| 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;
@ -1385,13 +1385,13 @@ fn drain_filter_zst() {
} }
#[test] #[test]
fn drain_filter_false() { fn extract_if_false() {
let mut vec = vec![1, 2, 3, 4, 5, 6, 7, 8, 9, 10]; let mut vec = vec![1, 2, 3, 4, 5, 6, 7, 8, 9, 10];
let initial_len = vec.len(); let initial_len = vec.len();
let mut count = 0; let mut count = 0;
{ {
let mut iter = vec.drain_filter(|_| 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;
@ -1407,13 +1407,13 @@ fn drain_filter_false() {
} }
#[test] #[test]
fn drain_filter_true() { fn extract_if_true() {
let mut vec = vec![1, 2, 3, 4, 5, 6, 7, 8, 9, 10]; let mut vec = vec![1, 2, 3, 4, 5, 6, 7, 8, 9, 10];
let initial_len = vec.len(); let initial_len = vec.len();
let mut count = 0; let mut count = 0;
{ {
let mut iter = vec.drain_filter(|_| 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;
@ -1430,7 +1430,7 @@ fn drain_filter_true() {
} }
#[test] #[test]
fn drain_filter_complex() { fn extract_if_complex() {
{ {
// [+xxx++++++xxxxx++++x+x++] // [+xxx++++++xxxxx++++x+x++]
let mut vec = vec![ let mut vec = vec![
@ -1438,7 +1438,7 @@ fn drain_filter_complex() {
39, 39,
]; ];
let removed = vec.drain_filter(|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]);
@ -1452,7 +1452,7 @@ fn drain_filter_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.drain_filter(|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]);
@ -1465,7 +1465,7 @@ fn drain_filter_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.drain_filter(|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]);
@ -1477,7 +1477,7 @@ fn drain_filter_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.drain_filter(|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]);
@ -1489,7 +1489,7 @@ fn drain_filter_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.drain_filter(|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]);
@ -1502,7 +1502,7 @@ fn drain_filter_complex() {
#[test] #[test]
#[cfg(not(target_os = "emscripten"))] #[cfg(not(target_os = "emscripten"))]
#[cfg_attr(not(panic = "unwind"), ignore = "test requires unwinding support")] #[cfg_attr(not(panic = "unwind"), ignore = "test requires unwinding support")]
fn drain_filter_consumed_panic() { fn extract_if_consumed_panic() {
use std::rc::Rc; use std::rc::Rc;
use std::sync::Mutex; use std::sync::Mutex;
@ -1537,9 +1537,9 @@ fn drain_filter_consumed_panic() {
} }
c.index < 6 c.index < 6
}; };
let drain = data.drain_filter(filter); let drain = data.extract_if(filter);
// NOTE: The DrainFilter is explicitly consumed // NOTE: The ExtractIf is explicitly consumed
drain.for_each(drop); drain.for_each(drop);
}); });
@ -1555,7 +1555,7 @@ fn drain_filter_consumed_panic() {
#[test] #[test]
#[cfg(not(target_os = "emscripten"))] #[cfg(not(target_os = "emscripten"))]
#[cfg_attr(not(panic = "unwind"), ignore = "test requires unwinding support")] #[cfg_attr(not(panic = "unwind"), ignore = "test requires unwinding support")]
fn drain_filter_unconsumed_panic() { fn extract_if_unconsumed_panic() {
use std::rc::Rc; use std::rc::Rc;
use std::sync::Mutex; use std::sync::Mutex;
@ -1590,9 +1590,9 @@ fn drain_filter_unconsumed_panic() {
} }
c.index < 6 c.index < 6
}; };
let _drain = data.drain_filter(filter); let _drain = data.extract_if(filter);
// NOTE: The DrainFilter is dropped without being consumed // NOTE: The ExtractIf is dropped without being consumed
}); });
let drop_counts = drop_counts.lock().unwrap(); let drop_counts = drop_counts.lock().unwrap();
@ -1604,9 +1604,9 @@ fn drain_filter_unconsumed_panic() {
} }
#[test] #[test]
fn drain_filter_unconsumed() { fn extract_if_unconsumed() {
let mut vec = vec![1, 2, 3, 4]; let mut vec = vec![1, 2, 3, 4];
let drain = vec.drain_filter(|&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]);
} }

View File

@ -6,7 +6,6 @@
#![feature(array_methods)] #![feature(array_methods)]
#![feature(assert_matches)] #![feature(assert_matches)]
#![feature(box_patterns)] #![feature(box_patterns)]
#![feature(drain_filter)]
#![feature(impl_trait_in_assoc_type)] #![feature(impl_trait_in_assoc_type)]
#![feature(iter_intersperse)] #![feature(iter_intersperse)]
#![feature(lazy_cell)] #![feature(lazy_cell)]

View File

@ -2,7 +2,7 @@
//check-pass //check-pass
#![warn(unused)] #![warn(unused)]
#![feature(rustc_attrs)] #![feature(rustc_attrs)]
#![feature(btree_drain_filter)] #![feature(btree_extract_if)]
use std::collections::BTreeMap; use std::collections::BTreeMap;
use std::panic::{catch_unwind, AssertUnwindSafe}; use std::panic::{catch_unwind, AssertUnwindSafe};
@ -14,14 +14,14 @@ fn main() {
map.insert("c", ()); map.insert("c", ());
{ {
let mut it = map.drain_filter(|_, _| true); let mut it = map.extract_if(|_, _| true);
catch_unwind(AssertUnwindSafe(|| while it.next().is_some() {})).unwrap_err(); catch_unwind(AssertUnwindSafe(|| while it.next().is_some() {})).unwrap_err();
let result = catch_unwind(AssertUnwindSafe(|| it.next())); let result = catch_unwind(AssertUnwindSafe(|| it.next()));
assert!(matches!(result, Ok(None))); assert!(matches!(result, Ok(None)));
} }
{ {
let mut it = map.drain_filter(|_, _| true); let mut it = map.extract_if(|_, _| true);
catch_unwind(AssertUnwindSafe(|| while let Some(_) = it.next() {})).unwrap_err(); catch_unwind(AssertUnwindSafe(|| while let Some(_) = it.next() {})).unwrap_err();
let result = catch_unwind(AssertUnwindSafe(|| it.next())); let result = catch_unwind(AssertUnwindSafe(|| it.next()));
assert!(matches!(result, Ok(None))); assert!(matches!(result, Ok(None)));