mirror of
https://github.com/rust-lang/rust.git
synced 2024-11-26 08:44:35 +00:00
remove drain-on-drop behavior from BTree{Set,Map}::DrainFilter and add #[must_use]
This commit is contained in:
parent
c0df1c8c43
commit
b687e84aeb
@ -1132,7 +1132,7 @@ impl<K, V, A: Allocator + Clone> BTreeMap<K, V, A> {
|
||||
K: Ord,
|
||||
F: FnMut(&K, &mut V) -> bool,
|
||||
{
|
||||
self.drain_filter(|k, v| !f(k, v));
|
||||
self.drain_filter(|k, v| !f(k, v)).for_each(drop);
|
||||
}
|
||||
|
||||
/// Moves all elements from `other` into `self`, leaving `other` empty.
|
||||
@ -1395,14 +1395,11 @@ impl<K, V, A: Allocator + Clone> BTreeMap<K, V, A> {
|
||||
/// The iterator also lets you mutate the value of each element in the
|
||||
/// closure, regardless of whether you choose to keep or remove it.
|
||||
///
|
||||
/// If the iterator is only partially consumed or not consumed at all, each
|
||||
/// of the remaining elements is still subjected to the closure, which may
|
||||
/// change its value and, by returning `true`, have the element removed and
|
||||
/// dropped.
|
||||
/// If the returned `DrainFilter` is not exhausted, e.g. because it is dropped without iterating
|
||||
/// 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.
|
||||
///
|
||||
/// It is unspecified how many more elements will be subjected to the
|
||||
/// closure if a panic occurs in the closure, or a panic occurs while
|
||||
/// dropping an element, or if the `DrainFilter` value is leaked.
|
||||
/// [`retain`]: BTreeMap::retain
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
@ -1901,6 +1898,7 @@ impl<K, V> Default for Values<'_, K, V> {
|
||||
|
||||
/// An iterator produced by calling `drain_filter` on BTreeMap.
|
||||
#[unstable(feature = "btree_drain_filter", issue = "70530")]
|
||||
#[must_use = "iterators are lazy and do nothing unless consumed"]
|
||||
pub struct DrainFilter<
|
||||
'a,
|
||||
K,
|
||||
@ -1929,16 +1927,6 @@ pub(super) struct DrainFilterInner<'a, K, V> {
|
||||
cur_leaf_edge: Option<Handle<NodeRef<marker::Mut<'a>, K, V, marker::Leaf>, marker::Edge>>,
|
||||
}
|
||||
|
||||
#[unstable(feature = "btree_drain_filter", issue = "70530")]
|
||||
impl<K, V, F, A: Allocator + Clone> Drop for DrainFilter<'_, K, V, F, A>
|
||||
where
|
||||
F: FnMut(&K, &mut V) -> bool,
|
||||
{
|
||||
fn drop(&mut self) {
|
||||
self.for_each(drop);
|
||||
}
|
||||
}
|
||||
|
||||
#[unstable(feature = "btree_drain_filter", issue = "70530")]
|
||||
impl<K, V, F> fmt::Debug for DrainFilter<'_, K, V, F>
|
||||
where
|
||||
|
@ -947,7 +947,7 @@ mod test_drain_filter {
|
||||
#[test]
|
||||
fn empty() {
|
||||
let mut map: BTreeMap<i32, i32> = BTreeMap::new();
|
||||
map.drain_filter(|_, _| unreachable!("there's nothing to decide on"));
|
||||
map.drain_filter(|_, _| unreachable!("there's nothing to decide on")).for_each(drop);
|
||||
assert_eq!(map.height(), None);
|
||||
map.check();
|
||||
}
|
||||
@ -1008,7 +1008,7 @@ mod test_drain_filter {
|
||||
fn underfull_keeping_all() {
|
||||
let pairs = (0..3).map(|i| (i, i));
|
||||
let mut map = BTreeMap::from_iter(pairs);
|
||||
map.drain_filter(|_, _| false);
|
||||
map.drain_filter(|_, _| false).for_each(drop);
|
||||
assert!(map.keys().copied().eq(0..3));
|
||||
map.check();
|
||||
}
|
||||
@ -1018,7 +1018,7 @@ mod test_drain_filter {
|
||||
let pairs = (0..3).map(|i| (i, i));
|
||||
for doomed in 0..3 {
|
||||
let mut map = BTreeMap::from_iter(pairs.clone());
|
||||
map.drain_filter(|i, _| *i == doomed);
|
||||
map.drain_filter(|i, _| *i == doomed).for_each(drop);
|
||||
assert_eq!(map.len(), 2);
|
||||
map.check();
|
||||
}
|
||||
@ -1029,7 +1029,7 @@ mod test_drain_filter {
|
||||
let pairs = (0..3).map(|i| (i, i));
|
||||
for sacred in 0..3 {
|
||||
let mut map = BTreeMap::from_iter(pairs.clone());
|
||||
map.drain_filter(|i, _| *i != sacred);
|
||||
map.drain_filter(|i, _| *i != sacred).for_each(drop);
|
||||
assert!(map.keys().copied().eq(sacred..=sacred));
|
||||
map.check();
|
||||
}
|
||||
@ -1039,7 +1039,7 @@ mod test_drain_filter {
|
||||
fn underfull_removing_all() {
|
||||
let pairs = (0..3).map(|i| (i, i));
|
||||
let mut map = BTreeMap::from_iter(pairs);
|
||||
map.drain_filter(|_, _| true);
|
||||
map.drain_filter(|_, _| true).for_each(drop);
|
||||
assert!(map.is_empty());
|
||||
map.check();
|
||||
}
|
||||
@ -1048,7 +1048,7 @@ mod test_drain_filter {
|
||||
fn height_0_keeping_all() {
|
||||
let pairs = (0..node::CAPACITY).map(|i| (i, i));
|
||||
let mut map = BTreeMap::from_iter(pairs);
|
||||
map.drain_filter(|_, _| false);
|
||||
map.drain_filter(|_, _| false).for_each(drop);
|
||||
assert!(map.keys().copied().eq(0..node::CAPACITY));
|
||||
map.check();
|
||||
}
|
||||
@ -1058,7 +1058,7 @@ mod test_drain_filter {
|
||||
let pairs = (0..node::CAPACITY).map(|i| (i, i));
|
||||
for doomed in 0..node::CAPACITY {
|
||||
let mut map = BTreeMap::from_iter(pairs.clone());
|
||||
map.drain_filter(|i, _| *i == doomed);
|
||||
map.drain_filter(|i, _| *i == doomed).for_each(drop);
|
||||
assert_eq!(map.len(), node::CAPACITY - 1);
|
||||
map.check();
|
||||
}
|
||||
@ -1069,7 +1069,7 @@ mod test_drain_filter {
|
||||
let pairs = (0..node::CAPACITY).map(|i| (i, i));
|
||||
for sacred in 0..node::CAPACITY {
|
||||
let mut map = BTreeMap::from_iter(pairs.clone());
|
||||
map.drain_filter(|i, _| *i != sacred);
|
||||
map.drain_filter(|i, _| *i != sacred).for_each(drop);
|
||||
assert!(map.keys().copied().eq(sacred..=sacred));
|
||||
map.check();
|
||||
}
|
||||
@ -1079,7 +1079,7 @@ mod test_drain_filter {
|
||||
fn height_0_removing_all() {
|
||||
let pairs = (0..node::CAPACITY).map(|i| (i, i));
|
||||
let mut map = BTreeMap::from_iter(pairs);
|
||||
map.drain_filter(|_, _| true);
|
||||
map.drain_filter(|_, _| true).for_each(drop);
|
||||
assert!(map.is_empty());
|
||||
map.check();
|
||||
}
|
||||
@ -1096,7 +1096,7 @@ mod test_drain_filter {
|
||||
fn height_1_removing_all() {
|
||||
let pairs = (0..MIN_INSERTS_HEIGHT_1).map(|i| (i, i));
|
||||
let mut map = BTreeMap::from_iter(pairs);
|
||||
map.drain_filter(|_, _| true);
|
||||
map.drain_filter(|_, _| true).for_each(drop);
|
||||
assert!(map.is_empty());
|
||||
map.check();
|
||||
}
|
||||
@ -1106,7 +1106,7 @@ mod test_drain_filter {
|
||||
let pairs = (0..MIN_INSERTS_HEIGHT_1).map(|i| (i, i));
|
||||
for doomed in 0..MIN_INSERTS_HEIGHT_1 {
|
||||
let mut map = BTreeMap::from_iter(pairs.clone());
|
||||
map.drain_filter(|i, _| *i == doomed);
|
||||
map.drain_filter(|i, _| *i == doomed).for_each(drop);
|
||||
assert_eq!(map.len(), MIN_INSERTS_HEIGHT_1 - 1);
|
||||
map.check();
|
||||
}
|
||||
@ -1117,7 +1117,7 @@ mod test_drain_filter {
|
||||
let pairs = (0..MIN_INSERTS_HEIGHT_1).map(|i| (i, i));
|
||||
for sacred in 0..MIN_INSERTS_HEIGHT_1 {
|
||||
let mut map = BTreeMap::from_iter(pairs.clone());
|
||||
map.drain_filter(|i, _| *i != sacred);
|
||||
map.drain_filter(|i, _| *i != sacred).for_each(drop);
|
||||
assert!(map.keys().copied().eq(sacred..=sacred));
|
||||
map.check();
|
||||
}
|
||||
@ -1128,7 +1128,7 @@ mod test_drain_filter {
|
||||
let pairs = (0..MIN_INSERTS_HEIGHT_2).map(|i| (i, i));
|
||||
for doomed in (0..MIN_INSERTS_HEIGHT_2).step_by(12) {
|
||||
let mut map = BTreeMap::from_iter(pairs.clone());
|
||||
map.drain_filter(|i, _| *i == doomed);
|
||||
map.drain_filter(|i, _| *i == doomed).for_each(drop);
|
||||
assert_eq!(map.len(), MIN_INSERTS_HEIGHT_2 - 1);
|
||||
map.check();
|
||||
}
|
||||
@ -1139,7 +1139,7 @@ mod test_drain_filter {
|
||||
let pairs = (0..MIN_INSERTS_HEIGHT_2).map(|i| (i, i));
|
||||
for sacred in (0..MIN_INSERTS_HEIGHT_2).step_by(12) {
|
||||
let mut map = BTreeMap::from_iter(pairs.clone());
|
||||
map.drain_filter(|i, _| *i != sacred);
|
||||
map.drain_filter(|i, _| *i != sacred).for_each(drop);
|
||||
assert!(map.keys().copied().eq(sacred..=sacred));
|
||||
map.check();
|
||||
}
|
||||
@ -1149,7 +1149,7 @@ mod test_drain_filter {
|
||||
fn height_2_removing_all() {
|
||||
let pairs = (0..MIN_INSERTS_HEIGHT_2).map(|i| (i, i));
|
||||
let mut map = BTreeMap::from_iter(pairs);
|
||||
map.drain_filter(|_, _| true);
|
||||
map.drain_filter(|_, _| true).for_each(drop);
|
||||
assert!(map.is_empty());
|
||||
map.check();
|
||||
}
|
||||
@ -1165,7 +1165,8 @@ mod test_drain_filter {
|
||||
map.insert(b.spawn(Panic::InDrop), ());
|
||||
map.insert(c.spawn(Panic::Never), ());
|
||||
|
||||
catch_unwind(move || drop(map.drain_filter(|dummy, _| dummy.query(true)))).unwrap_err();
|
||||
catch_unwind(move || map.drain_filter(|dummy, _| dummy.query(true)).for_each(drop))
|
||||
.unwrap_err();
|
||||
|
||||
assert_eq!(a.queried(), 1);
|
||||
assert_eq!(b.queried(), 1);
|
||||
@ -1186,8 +1187,10 @@ mod test_drain_filter {
|
||||
map.insert(b.spawn(Panic::InQuery), ());
|
||||
map.insert(c.spawn(Panic::InQuery), ());
|
||||
|
||||
catch_unwind(AssertUnwindSafe(|| drop(map.drain_filter(|dummy, _| dummy.query(true)))))
|
||||
.unwrap_err();
|
||||
catch_unwind(AssertUnwindSafe(|| {
|
||||
map.drain_filter(|dummy, _| dummy.query(true)).for_each(drop)
|
||||
}))
|
||||
.unwrap_err();
|
||||
|
||||
assert_eq!(a.queried(), 1);
|
||||
assert_eq!(b.queried(), 1);
|
||||
|
@ -999,7 +999,7 @@ impl<T, A: Allocator + Clone> BTreeSet<T, A> {
|
||||
T: Ord,
|
||||
F: FnMut(&T) -> bool,
|
||||
{
|
||||
self.drain_filter(|v| !f(v));
|
||||
self.drain_filter(|v| !f(v)).for_each(drop);
|
||||
}
|
||||
|
||||
/// Moves all elements from `other` into `self`, leaving `other` empty.
|
||||
@ -1084,14 +1084,11 @@ impl<T, A: Allocator + Clone> BTreeSet<T, A> {
|
||||
/// yielded. If the closure returns `false`, or panics, the element remains
|
||||
/// in the set and will not be yielded.
|
||||
///
|
||||
/// If the iterator is only partially consumed or not consumed at all, each
|
||||
/// of the remaining elements is still subjected to the closure and removed
|
||||
/// and dropped if it returns `true`.
|
||||
///
|
||||
/// It is unspecified how many more elements will be subjected to the
|
||||
/// closure if a panic occurs in the closure, or if a panic occurs while
|
||||
/// dropping an element, or if the `DrainFilter` itself is leaked.
|
||||
/// If the returned `DrainFilter` is not exhausted, e.g. because it is dropped without iterating
|
||||
/// 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.
|
||||
///
|
||||
/// [`retain`]: BTreeSet::retain
|
||||
/// # Examples
|
||||
///
|
||||
/// Splitting a set into even and odd values, reusing the original set:
|
||||
@ -1277,6 +1274,7 @@ impl<'a, T, A: Allocator + Clone> IntoIterator for &'a BTreeSet<T, A> {
|
||||
|
||||
/// An iterator produced by calling `drain_filter` on BTreeSet.
|
||||
#[unstable(feature = "btree_drain_filter", issue = "70530")]
|
||||
#[must_use = "iterators are lazy and do nothing unless consumed"]
|
||||
pub struct DrainFilter<
|
||||
'a,
|
||||
T,
|
||||
@ -1292,16 +1290,6 @@ pub struct DrainFilter<
|
||||
alloc: A,
|
||||
}
|
||||
|
||||
#[unstable(feature = "btree_drain_filter", issue = "70530")]
|
||||
impl<T, F, A: Allocator + Clone> Drop for DrainFilter<'_, T, F, A>
|
||||
where
|
||||
F: FnMut(&T) -> bool,
|
||||
{
|
||||
fn drop(&mut self) {
|
||||
self.for_each(drop);
|
||||
}
|
||||
}
|
||||
|
||||
#[unstable(feature = "btree_drain_filter", issue = "70530")]
|
||||
impl<T, F, A: Allocator + Clone> fmt::Debug for DrainFilter<'_, T, F, A>
|
||||
where
|
||||
|
@ -370,8 +370,8 @@ fn test_drain_filter() {
|
||||
let mut x = BTreeSet::from([1]);
|
||||
let mut y = BTreeSet::from([1]);
|
||||
|
||||
x.drain_filter(|_| true);
|
||||
y.drain_filter(|_| false);
|
||||
x.drain_filter(|_| true).for_each(drop);
|
||||
y.drain_filter(|_| false).for_each(drop);
|
||||
assert_eq!(x.len(), 0);
|
||||
assert_eq!(y.len(), 1);
|
||||
}
|
||||
@ -387,7 +387,7 @@ fn test_drain_filter_drop_panic_leak() {
|
||||
set.insert(b.spawn(Panic::InDrop));
|
||||
set.insert(c.spawn(Panic::Never));
|
||||
|
||||
catch_unwind(move || drop(set.drain_filter(|dummy| dummy.query(true)))).ok();
|
||||
catch_unwind(move || set.drain_filter(|dummy| dummy.query(true)).for_each(drop)).ok();
|
||||
|
||||
assert_eq!(a.queried(), 1);
|
||||
assert_eq!(b.queried(), 1);
|
||||
@ -408,7 +408,10 @@ fn test_drain_filter_pred_panic_leak() {
|
||||
set.insert(b.spawn(Panic::InQuery));
|
||||
set.insert(c.spawn(Panic::InQuery));
|
||||
|
||||
catch_unwind(AssertUnwindSafe(|| drop(set.drain_filter(|dummy| dummy.query(true))))).ok();
|
||||
catch_unwind(AssertUnwindSafe(|| {
|
||||
set.drain_filter(|dummy| dummy.query(true)).for_each(drop)
|
||||
}))
|
||||
.ok();
|
||||
|
||||
assert_eq!(a.queried(), 1);
|
||||
assert_eq!(b.queried(), 1);
|
||||
|
Loading…
Reference in New Issue
Block a user