Skip to content

Commit 28a13cf

Browse files
committed
Remove drain-on-drop behavior from DrainFilter
1 parent 5d49276 commit 28a13cf

File tree

2 files changed

+14
-53
lines changed

2 files changed

+14
-53
lines changed

src/map.rs

Lines changed: 8 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
use std::fmt;
12
use crate::raw::{Allocator, Bucket, Global, RawDrain, RawIntoIter, RawIter, RawTable};
23
use crate::{Equivalent, TryReserveError};
34
use core::borrow::Borrow;
@@ -975,12 +976,9 @@ impl<K, V, S, A: Allocator + Clone> HashMap<K, V, S, A> {
975976
/// Note that `drain_filter` lets you mutate every value in the filter closure, regardless of
976977
/// whether you choose to keep or remove it.
977978
///
978-
/// When the returned DrainedFilter is dropped, any remaining elements that satisfy
979-
/// the predicate are dropped from the table.
980-
///
981-
/// It is unspecified how many more elements will be subjected to the closure
982-
/// if a panic occurs in the closure, or a panic occurs while dropping an element,
983-
/// or if the `DrainFilter` value is leaked.
979+
/// If the returned `DrainFilter` is not exhausted, e.g. because it is dropped without iterating
980+
/// or the iteration short-circuits, then the remaining elements will be retained.
981+
/// Use [`retain()`] with a negated predicate if you do not need the returned iterator.
984982
///
985983
/// Keeps the allocated memory for reuse.
986984
///
@@ -1007,9 +1005,8 @@ impl<K, V, S, A: Allocator + Clone> HashMap<K, V, S, A> {
10071005
/// let d = map.drain_filter(|k, _v| k % 2 != 0);
10081006
/// }
10091007
///
1010-
/// // But the map lens have been reduced by half
1011-
/// // even if we do not use DrainFilter iterator.
1012-
/// assert_eq!(map.len(), 4);
1008+
/// // DrainFilter was not exhausted, therefore no elements were drained.
1009+
/// assert_eq!(map.len(), 8);
10131010
/// ```
10141011
#[cfg_attr(feature = "inline-more", inline)]
10151012
pub fn drain_filter<F>(&mut self, f: F) -> DrainFilter<'_, K, V, F, A>
@@ -2739,6 +2736,7 @@ impl<K, V, A: Allocator + Clone> Drain<'_, K, V, A> {
27392736
///
27402737
/// assert_eq!(map.len(), 1);
27412738
/// ```
2739+
#[must_use = "Iterators are lazy unless consumed"]
27422740
pub struct DrainFilter<'a, K, V, F, A: Allocator + Clone = Global>
27432741
where
27442742
F: FnMut(&K, &mut V) -> bool,
@@ -2747,30 +2745,6 @@ where
27472745
inner: DrainFilterInner<'a, K, V, A>,
27482746
}
27492747

2750-
impl<'a, K, V, F, A> Drop for DrainFilter<'a, K, V, F, A>
2751-
where
2752-
F: FnMut(&K, &mut V) -> bool,
2753-
A: Allocator + Clone,
2754-
{
2755-
#[cfg_attr(feature = "inline-more", inline)]
2756-
fn drop(&mut self) {
2757-
while let Some(item) = self.next() {
2758-
let guard = ConsumeAllOnDrop(self);
2759-
drop(item);
2760-
mem::forget(guard);
2761-
}
2762-
}
2763-
}
2764-
2765-
pub(super) struct ConsumeAllOnDrop<'a, T: Iterator>(pub &'a mut T);
2766-
2767-
impl<T: Iterator> Drop for ConsumeAllOnDrop<'_, T> {
2768-
#[cfg_attr(feature = "inline-more", inline)]
2769-
fn drop(&mut self) {
2770-
self.0.for_each(drop);
2771-
}
2772-
}
2773-
27742748
impl<K, V, F, A> Iterator for DrainFilter<'_, K, V, F, A>
27752749
where
27762750
F: FnMut(&K, &mut V) -> bool,
@@ -8159,7 +8133,7 @@ mod test_map {
81598133
}
81608134
{
81618135
let mut map: HashMap<i32, i32> = (0..8).map(|x| (x, x * 10)).collect();
8162-
drop(map.drain_filter(|&k, _| k % 2 == 0));
8136+
map.drain_filter(|&k, _| k % 2 == 0).for_each(drop);
81638137
assert_eq!(map.len(), 4);
81648138
}
81658139
}

src/set.rs

Lines changed: 6 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -5,10 +5,9 @@ use alloc::borrow::ToOwned;
55
use core::fmt;
66
use core::hash::{BuildHasher, Hash};
77
use core::iter::{Chain, FromIterator, FusedIterator};
8-
use core::mem;
98
use core::ops::{BitAnd, BitOr, BitXor, Sub};
109

11-
use super::map::{self, ConsumeAllOnDrop, DefaultHashBuilder, DrainFilterInner, HashMap, Keys};
10+
use super::map::{self, DefaultHashBuilder, DrainFilterInner, HashMap, Keys};
1211
use crate::raw::{Allocator, Global};
1312

1413
// Future Optimization (FIXME!)
@@ -380,8 +379,9 @@ impl<T, S, A: Allocator + Clone> HashSet<T, S, A> {
380379
/// In other words, move all elements `e` such that `f(&e)` returns `true` out
381380
/// into another iterator.
382381
///
383-
/// When the returned DrainedFilter is dropped, any remaining elements that satisfy
384-
/// the predicate are dropped from the set.
382+
/// If the returned `DrainFilter` is not exhausted, e.g. because it is dropped without iterating
383+
/// or the iteration short-circuits, then the remaining elements will be retained.
384+
/// Use [`retain()`] with a negated predicate if you do not need the returned iterator.
385385
///
386386
/// # Examples
387387
///
@@ -1552,6 +1552,7 @@ pub struct Drain<'a, K, A: Allocator + Clone = Global> {
15521552
///
15531553
/// [`drain_filter`]: struct.HashSet.html#method.drain_filter
15541554
/// [`HashSet`]: struct.HashSet.html
1555+
#[must_use = "Iterators are lazy unless consumed"]
15551556
pub struct DrainFilter<'a, K, F, A: Allocator + Clone = Global>
15561557
where
15571558
F: FnMut(&K) -> bool,
@@ -1748,20 +1749,6 @@ impl<K: fmt::Debug, A: Allocator + Clone> fmt::Debug for Drain<'_, K, A> {
17481749
}
17491750
}
17501751

1751-
impl<'a, K, F, A: Allocator + Clone> Drop for DrainFilter<'a, K, F, A>
1752-
where
1753-
F: FnMut(&K) -> bool,
1754-
{
1755-
#[cfg_attr(feature = "inline-more", inline)]
1756-
fn drop(&mut self) {
1757-
while let Some(item) = self.next() {
1758-
let guard = ConsumeAllOnDrop(self);
1759-
drop(item);
1760-
mem::forget(guard);
1761-
}
1762-
}
1763-
}
1764-
17651752
impl<K, F, A: Allocator + Clone> Iterator for DrainFilter<'_, K, F, A>
17661753
where
17671754
F: FnMut(&K) -> bool,
@@ -2840,7 +2827,7 @@ mod test_set {
28402827
}
28412828
{
28422829
let mut set: HashSet<i32> = (0..8).collect();
2843-
drop(set.drain_filter(|&k| k % 2 == 0));
2830+
set.drain_filter(|&k| k % 2 == 0).for_each(drop);
28442831
assert_eq!(set.len(), 4, "Removes non-matching items on drop");
28452832
}
28462833
}

0 commit comments

Comments
 (0)