Skip to content

Commit 3b8efd5

Browse files
committed
Auto merge of #163 - CAD97:easier-retain, r=Amanieu
Remove generic bounds from retain Closes #161 (the underlying feature request, not the titular proposed access; a raw all might still be useful in niche cases) Removes the `<K: Eq + Hash, S: BuildHasher>` generic requirement from `HashMap::retain`, `HashMap::drain_filter`, and `HashSet::retain`. Places these methods directly after `drain`, where they seem to fit logically. Functionally, this is promising that `retain`/`drain_filter` do not do further rehashing/comparison of elements in the hash map, and gives access to these methods to `raw_entry` use cases that have a dummy `BuildHasher` parameter.
2 parents caf003c + c78f937 commit 3b8efd5

File tree

2 files changed

+81
-80
lines changed

2 files changed

+81
-80
lines changed

src/map.rs

Lines changed: 60 additions & 59 deletions
Original file line numberDiff line numberDiff line change
@@ -556,6 +556,66 @@ impl<K, V, S> HashMap<K, V, S> {
556556
}
557557
}
558558

559+
/// Retains only the elements specified by the predicate.
560+
///
561+
/// In other words, remove all pairs `(k, v)` such that `f(&k,&mut v)` returns `false`.
562+
///
563+
/// # Examples
564+
///
565+
/// ```
566+
/// use hashbrown::HashMap;
567+
///
568+
/// let mut map: HashMap<i32, i32> = (0..8).map(|x|(x, x*10)).collect();
569+
/// map.retain(|&k, _| k % 2 == 0);
570+
/// assert_eq!(map.len(), 4);
571+
/// ```
572+
pub fn retain<F>(&mut self, mut f: F)
573+
where
574+
F: FnMut(&K, &mut V) -> bool,
575+
{
576+
// Here we only use `iter` as a temporary, preventing use-after-free
577+
unsafe {
578+
for item in self.table.iter() {
579+
let &mut (ref key, ref mut value) = item.as_mut();
580+
if !f(key, value) {
581+
// Erase the element from the table first since drop might panic.
582+
self.table.erase_no_drop(&item);
583+
item.drop();
584+
}
585+
}
586+
}
587+
}
588+
589+
/// Drains elements which are false under the given predicate,
590+
/// and returns an iterator over the removed items.
591+
///
592+
/// In other words, move all pairs `(k, v)` such that `f(&k,&mut v)` returns `false` out
593+
/// into another iterator.
594+
///
595+
/// When the returned DrainedFilter is dropped, the elements that don't satisfy
596+
/// the predicate are dropped from the table.
597+
///
598+
/// # Examples
599+
///
600+
/// ```
601+
/// use hashbrown::HashMap;
602+
///
603+
/// let mut map: HashMap<i32, i32> = (0..8).map(|x|(x, x*10)).collect();
604+
/// let drained = map.drain_filter(|&k, _| k % 2 == 0);
605+
/// assert_eq!(drained.count(), 4);
606+
/// assert_eq!(map.len(), 4);
607+
/// ```
608+
pub fn drain_filter<F>(&mut self, f: F) -> DrainFilter<'_, K, V, F>
609+
where
610+
F: FnMut(&K, &mut V) -> bool,
611+
{
612+
DrainFilter {
613+
f,
614+
iter: unsafe { self.table.iter() },
615+
table: &mut self.table,
616+
}
617+
}
618+
559619
/// Clears the map, removing all key-value pairs. Keeps the allocated memory
560620
/// for reuse.
561621
///
@@ -982,65 +1042,6 @@ where
9821042
}
9831043
}
9841044
}
985-
986-
/// Retains only the elements specified by the predicate.
987-
///
988-
/// In other words, remove all pairs `(k, v)` such that `f(&k,&mut v)` returns `false`.
989-
///
990-
/// # Examples
991-
///
992-
/// ```
993-
/// use hashbrown::HashMap;
994-
///
995-
/// let mut map: HashMap<i32, i32> = (0..8).map(|x|(x, x*10)).collect();
996-
/// map.retain(|&k, _| k % 2 == 0);
997-
/// assert_eq!(map.len(), 4);
998-
/// ```
999-
pub fn retain<F>(&mut self, mut f: F)
1000-
where
1001-
F: FnMut(&K, &mut V) -> bool,
1002-
{
1003-
// Here we only use `iter` as a temporary, preventing use-after-free
1004-
unsafe {
1005-
for item in self.table.iter() {
1006-
let &mut (ref key, ref mut value) = item.as_mut();
1007-
if !f(key, value) {
1008-
// Erase the element from the table first since drop might panic.
1009-
self.table.erase_no_drop(&item);
1010-
item.drop();
1011-
}
1012-
}
1013-
}
1014-
}
1015-
/// Drains elements which are false under the given predicate,
1016-
/// and returns an iterator over the removed items.
1017-
///
1018-
/// In other words, move all pairs `(k, v)` such that `f(&k,&mut v)` returns `false` out
1019-
/// into another iterator.
1020-
///
1021-
/// When the returned DrainedFilter is dropped, the elements that don't satisfy
1022-
/// the predicate are dropped from the table.
1023-
///
1024-
/// # Examples
1025-
///
1026-
/// ```
1027-
/// use hashbrown::HashMap;
1028-
///
1029-
/// let mut map: HashMap<i32, i32> = (0..8).map(|x|(x, x*10)).collect();
1030-
/// let drained = map.drain_filter(|&k, _| k % 2 == 0);
1031-
/// assert_eq!(drained.count(), 4);
1032-
/// assert_eq!(map.len(), 4);
1033-
/// ```
1034-
pub fn drain_filter<F>(&mut self, f: F) -> DrainFilter<'_, K, V, F>
1035-
where
1036-
F: FnMut(&K, &mut V) -> bool,
1037-
{
1038-
DrainFilter {
1039-
f,
1040-
iter: unsafe { self.table.iter() },
1041-
table: &mut self.table,
1042-
}
1043-
}
10441045
}
10451046

10461047
impl<K, V, S> HashMap<K, V, S> {

src/set.rs

Lines changed: 21 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -264,6 +264,27 @@ impl<T, S> HashSet<T, S> {
264264
}
265265
}
266266

267+
/// Retains only the elements specified by the predicate.
268+
///
269+
/// In other words, remove all elements `e` such that `f(&e)` returns `false`.
270+
///
271+
/// # Examples
272+
///
273+
/// ```
274+
/// use hashbrown::HashSet;
275+
///
276+
/// let xs = [1,2,3,4,5,6];
277+
/// let mut set: HashSet<i32> = xs.iter().cloned().collect();
278+
/// set.retain(|&k| k % 2 == 0);
279+
/// assert_eq!(set.len(), 3);
280+
/// ```
281+
pub fn retain<F>(&mut self, mut f: F)
282+
where
283+
F: FnMut(&T) -> bool,
284+
{
285+
self.map.retain(|k, _| f(k));
286+
}
287+
267288
/// Clears the set, removing all values.
268289
///
269290
/// # Examples
@@ -898,27 +919,6 @@ where
898919
{
899920
self.map.remove_entry(value).map(|(k, _)| k)
900921
}
901-
902-
/// Retains only the elements specified by the predicate.
903-
///
904-
/// In other words, remove all elements `e` such that `f(&e)` returns `false`.
905-
///
906-
/// # Examples
907-
///
908-
/// ```
909-
/// use hashbrown::HashSet;
910-
///
911-
/// let xs = [1,2,3,4,5,6];
912-
/// let mut set: HashSet<i32> = xs.iter().cloned().collect();
913-
/// set.retain(|&k| k % 2 == 0);
914-
/// assert_eq!(set.len(), 3);
915-
/// ```
916-
pub fn retain<F>(&mut self, mut f: F)
917-
where
918-
F: FnMut(&T) -> bool,
919-
{
920-
self.map.retain(|k, _| f(k));
921-
}
922922
}
923923

924924
impl<T, S> PartialEq for HashSet<T, S>

0 commit comments

Comments
 (0)