Skip to content

Commit 479be6a

Browse files
committed
update hashbrown and replace Hash{Set,Map}::DrainFilter with ExtractIf
1 parent 18c9a12 commit 479be6a

File tree

7 files changed

+94
-75
lines changed

7 files changed

+94
-75
lines changed

Cargo.lock

+16-1
Original file line numberDiff line numberDiff line change
@@ -65,6 +65,12 @@ dependencies = [
6565
"rand_xorshift",
6666
]
6767

68+
[[package]]
69+
name = "allocator-api2"
70+
version = "0.2.14"
71+
source = "registry+https://github.com/rust-lang/crates.io-index"
72+
checksum = "c4f263788a35611fba42eb41ff811c5d0360c58b97402570312a350736e2542e"
73+
6874
[[package]]
6975
name = "ammonia"
7076
version = "3.2.0"
@@ -1522,6 +1528,15 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
15221528
checksum = "33ff8ae62cd3a9102e5637afc8452c55acf3844001bd5374e0b0bd7b6616c038"
15231529
dependencies = [
15241530
"ahash 0.8.2",
1531+
]
1532+
1533+
[[package]]
1534+
name = "hashbrown"
1535+
version = "0.14.0"
1536+
source = "registry+https://github.com/rust-lang/crates.io-index"
1537+
checksum = "2c6201b9ff9fd90a5a3bac2e56a830d0caa509576f0e503818ee82c181b3437a"
1538+
dependencies = [
1539+
"allocator-api2",
15251540
"compiler_builtins",
15261541
"rustc-std-workspace-alloc",
15271542
"rustc-std-workspace-core",
@@ -4633,7 +4648,7 @@ dependencies = [
46334648
"core",
46344649
"dlmalloc",
46354650
"fortanix-sgx-abi",
4636-
"hashbrown 0.13.1",
4651+
"hashbrown 0.14.0",
46374652
"hermit-abi 0.3.0",
46384653
"libc",
46394654
"miniz_oxide",

library/std/Cargo.toml

+1-1
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@ libc = { version = "0.2.146", default-features = false, features = ['rustc-dep-o
2121
compiler_builtins = { version = "0.1.92" }
2222
profiler_builtins = { path = "../profiler_builtins", optional = true }
2323
unwind = { path = "../unwind" }
24-
hashbrown = { version = "0.13", default-features = false, features = ['rustc-dep-of-std'] }
24+
hashbrown = { version = "0.14", default-features = false, features = ['rustc-dep-of-std'] }
2525
std_detect = { path = "../stdarch/crates/std_detect", default-features = false, features = ['rustc-dep-of-std'] }
2626

2727
# Dependencies of the `backtrace` crate

library/std/src/collections/hash/map.rs

+26-26
Original file line numberDiff line numberDiff line change
@@ -623,28 +623,27 @@ impl<K, V, S> HashMap<K, V, S> {
623623
/// If the closure returns false, or panics, the element remains in the map and will not be
624624
/// yielded.
625625
///
626-
/// Note that `drain_filter` lets you mutate every value in the filter closure, regardless of
626+
/// Note that `extract_if` lets you mutate every value in the filter closure, regardless of
627627
/// whether you choose to keep or remove it.
628628
///
629-
/// If the iterator is only partially consumed or not consumed at all, each of the remaining
630-
/// elements will still be subjected to the closure and removed and dropped if it returns true.
629+
/// If the returned `ExtractIf` is not exhausted, e.g. because it is dropped without iterating
630+
/// or the iteration short-circuits, then the remaining elements will be retained.
631+
/// Use [`retain`] with a negated predicate if you do not need the returned iterator.
631632
///
632-
/// It is unspecified how many more elements will be subjected to the closure
633-
/// if a panic occurs in the closure, or a panic occurs while dropping an element,
634-
/// or if the `DrainFilter` value is leaked.
633+
/// [`retain`]: HashMap::retain
635634
///
636635
/// # Examples
637636
///
638637
/// Splitting a map into even and odd keys, reusing the original map:
639638
///
640639
/// ```
641-
/// #![feature(hash_drain_filter)]
640+
/// #![feature(hash_extract_if)]
642641
/// use std::collections::HashMap;
643642
///
644643
/// let mut map: HashMap<i32, i32> = (0..8).map(|x| (x, x)).collect();
645-
/// let drained: HashMap<i32, i32> = map.drain_filter(|k, _v| k % 2 == 0).collect();
644+
/// let extracted: HashMap<i32, i32> = map.extract_if(|k, _v| k % 2 == 0).collect();
646645
///
647-
/// let mut evens = drained.keys().copied().collect::<Vec<_>>();
646+
/// let mut evens = extracted.keys().copied().collect::<Vec<_>>();
648647
/// let mut odds = map.keys().copied().collect::<Vec<_>>();
649648
/// evens.sort();
650649
/// odds.sort();
@@ -654,12 +653,12 @@ impl<K, V, S> HashMap<K, V, S> {
654653
/// ```
655654
#[inline]
656655
#[rustc_lint_query_instability]
657-
#[unstable(feature = "hash_drain_filter", issue = "59618")]
658-
pub fn drain_filter<F>(&mut self, pred: F) -> DrainFilter<'_, K, V, F>
656+
#[unstable(feature = "hash_extract_if", issue = "59618")]
657+
pub fn extract_if<F>(&mut self, pred: F) -> ExtractIf<'_, K, V, F>
659658
where
660659
F: FnMut(&K, &mut V) -> bool,
661660
{
662-
DrainFilter { base: self.base.drain_filter(pred) }
661+
ExtractIf { base: self.base.extract_if(pred) }
663662
}
664663

665664
/// Retains only the elements specified by the predicate.
@@ -1578,28 +1577,29 @@ impl<'a, K, V> Drain<'a, K, V> {
15781577

15791578
/// A draining, filtering iterator over the entries of a `HashMap`.
15801579
///
1581-
/// This `struct` is created by the [`drain_filter`] method on [`HashMap`].
1580+
/// This `struct` is created by the [`extract_if`] method on [`HashMap`].
15821581
///
1583-
/// [`drain_filter`]: HashMap::drain_filter
1582+
/// [`extract_if`]: HashMap::extract_if
15841583
///
15851584
/// # Example
15861585
///
15871586
/// ```
1588-
/// #![feature(hash_drain_filter)]
1587+
/// #![feature(hash_extract_if)]
15891588
///
15901589
/// use std::collections::HashMap;
15911590
///
15921591
/// let mut map = HashMap::from([
15931592
/// ("a", 1),
15941593
/// ]);
1595-
/// let iter = map.drain_filter(|_k, v| *v % 2 == 0);
1594+
/// let iter = map.extract_if(|_k, v| *v % 2 == 0);
15961595
/// ```
1597-
#[unstable(feature = "hash_drain_filter", issue = "59618")]
1598-
pub struct DrainFilter<'a, K, V, F>
1596+
#[unstable(feature = "hash_extract_if", issue = "59618")]
1597+
#[must_use = "iterators are lazy and do nothing unless consumed"]
1598+
pub struct ExtractIf<'a, K, V, F>
15991599
where
16001600
F: FnMut(&K, &mut V) -> bool,
16011601
{
1602-
base: base::DrainFilter<'a, K, V, F>,
1602+
base: base::ExtractIf<'a, K, V, F>,
16031603
}
16041604

16051605
/// A mutable iterator over the values of a `HashMap`.
@@ -2479,8 +2479,8 @@ where
24792479
}
24802480
}
24812481

2482-
#[unstable(feature = "hash_drain_filter", issue = "59618")]
2483-
impl<K, V, F> Iterator for DrainFilter<'_, K, V, F>
2482+
#[unstable(feature = "hash_extract_if", issue = "59618")]
2483+
impl<K, V, F> Iterator for ExtractIf<'_, K, V, F>
24842484
where
24852485
F: FnMut(&K, &mut V) -> bool,
24862486
{
@@ -2496,16 +2496,16 @@ where
24962496
}
24972497
}
24982498

2499-
#[unstable(feature = "hash_drain_filter", issue = "59618")]
2500-
impl<K, V, F> FusedIterator for DrainFilter<'_, K, V, F> where F: FnMut(&K, &mut V) -> bool {}
2499+
#[unstable(feature = "hash_extract_if", issue = "59618")]
2500+
impl<K, V, F> FusedIterator for ExtractIf<'_, K, V, F> where F: FnMut(&K, &mut V) -> bool {}
25012501

2502-
#[unstable(feature = "hash_drain_filter", issue = "59618")]
2503-
impl<'a, K, V, F> fmt::Debug for DrainFilter<'a, K, V, F>
2502+
#[unstable(feature = "hash_extract_if", issue = "59618")]
2503+
impl<'a, K, V, F> fmt::Debug for ExtractIf<'a, K, V, F>
25042504
where
25052505
F: FnMut(&K, &mut V) -> bool,
25062506
{
25072507
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
2508-
f.debug_struct("DrainFilter").finish_non_exhaustive()
2508+
f.debug_struct("ExtractIf").finish_non_exhaustive()
25092509
}
25102510
}
25112511

library/std/src/collections/hash/map/tests.rs

+14-12
Original file line numberDiff line numberDiff line change
@@ -944,7 +944,7 @@ fn test_raw_entry() {
944944
}
945945
}
946946

947-
mod test_drain_filter {
947+
mod test_extract_if {
948948
use super::*;
949949

950950
use crate::panic::{catch_unwind, AssertUnwindSafe};
@@ -968,23 +968,23 @@ mod test_drain_filter {
968968
#[test]
969969
fn empty() {
970970
let mut map: HashMap<i32, i32> = HashMap::new();
971-
map.drain_filter(|_, _| unreachable!("there's nothing to decide on"));
971+
map.extract_if(|_, _| unreachable!("there's nothing to decide on")).for_each(drop);
972972
assert!(map.is_empty());
973973
}
974974

975975
#[test]
976976
fn consuming_nothing() {
977977
let pairs = (0..3).map(|i| (i, i));
978978
let mut map: HashMap<_, _> = pairs.collect();
979-
assert!(map.drain_filter(|_, _| false).eq_sorted(crate::iter::empty()));
979+
assert!(map.extract_if(|_, _| false).eq_sorted(crate::iter::empty()));
980980
assert_eq!(map.len(), 3);
981981
}
982982

983983
#[test]
984984
fn consuming_all() {
985985
let pairs = (0..3).map(|i| (i, i));
986986
let mut map: HashMap<_, _> = pairs.clone().collect();
987-
assert!(map.drain_filter(|_, _| true).eq_sorted(pairs));
987+
assert!(map.extract_if(|_, _| true).eq_sorted(pairs));
988988
assert!(map.is_empty());
989989
}
990990

@@ -993,7 +993,7 @@ mod test_drain_filter {
993993
let pairs = (0..3).map(|i| (i, i));
994994
let mut map: HashMap<_, _> = pairs.collect();
995995
assert!(
996-
map.drain_filter(|_, v| {
996+
map.extract_if(|_, v| {
997997
*v += 6;
998998
false
999999
})
@@ -1008,7 +1008,7 @@ mod test_drain_filter {
10081008
let pairs = (0..3).map(|i| (i, i));
10091009
let mut map: HashMap<_, _> = pairs.collect();
10101010
assert!(
1011-
map.drain_filter(|_, v| {
1011+
map.extract_if(|_, v| {
10121012
*v += 6;
10131013
true
10141014
})
@@ -1034,14 +1034,15 @@ mod test_drain_filter {
10341034
let mut map = (0..3).map(|i| (i, D)).collect::<HashMap<_, _>>();
10351035

10361036
catch_unwind(move || {
1037-
drop(map.drain_filter(|_, _| {
1037+
map.extract_if(|_, _| {
10381038
PREDS.fetch_add(1, Ordering::SeqCst);
10391039
true
1040-
}))
1040+
})
1041+
.for_each(drop)
10411042
})
10421043
.unwrap_err();
10431044

1044-
assert_eq!(PREDS.load(Ordering::SeqCst), 3);
1045+
assert_eq!(PREDS.load(Ordering::SeqCst), 2);
10451046
assert_eq!(DROPS.load(Ordering::SeqCst), 3);
10461047
}
10471048

@@ -1060,10 +1061,11 @@ mod test_drain_filter {
10601061
let mut map = (0..3).map(|i| (i, D)).collect::<HashMap<_, _>>();
10611062

10621063
catch_unwind(AssertUnwindSafe(|| {
1063-
drop(map.drain_filter(|_, _| match PREDS.fetch_add(1, Ordering::SeqCst) {
1064+
map.extract_if(|_, _| match PREDS.fetch_add(1, Ordering::SeqCst) {
10641065
0 => true,
10651066
_ => panic!(),
1066-
}))
1067+
})
1068+
.for_each(drop)
10671069
}))
10681070
.unwrap_err();
10691071

@@ -1088,7 +1090,7 @@ mod test_drain_filter {
10881090
let mut map = (0..3).map(|i| (i, D)).collect::<HashMap<_, _>>();
10891091

10901092
{
1091-
let mut it = map.drain_filter(|_, _| match PREDS.fetch_add(1, Ordering::SeqCst) {
1093+
let mut it = map.extract_if(|_, _| match PREDS.fetch_add(1, Ordering::SeqCst) {
10921094
0 => true,
10931095
_ => panic!(),
10941096
});

library/std/src/collections/hash/set.rs

+24-25
Original file line numberDiff line numberDiff line change
@@ -262,25 +262,24 @@ impl<T, S> HashSet<T, S> {
262262
/// If the closure returns false, the value will remain in the list and will not be yielded
263263
/// by the iterator.
264264
///
265-
/// If the iterator is only partially consumed or not consumed at all, each of the remaining
266-
/// values will still be subjected to the closure and removed and dropped if it returns true.
265+
/// If the returned `ExtractIf` is not exhausted, e.g. because it is dropped without iterating
266+
/// or the iteration short-circuits, then the remaining elements will be retained.
267+
/// Use [`retain`] with a negated predicate if you do not need the returned iterator.
267268
///
268-
/// It is unspecified how many more values will be subjected to the closure
269-
/// if a panic occurs in the closure, or if a panic occurs while dropping a value, or if the
270-
/// `DrainFilter` itself is leaked.
269+
/// [`retain`]: HashSet::retain
271270
///
272271
/// # Examples
273272
///
274273
/// Splitting a set into even and odd values, reusing the original set:
275274
///
276275
/// ```
277-
/// #![feature(hash_drain_filter)]
276+
/// #![feature(hash_extract_if)]
278277
/// use std::collections::HashSet;
279278
///
280279
/// let mut set: HashSet<i32> = (0..8).collect();
281-
/// let drained: HashSet<i32> = set.drain_filter(|v| v % 2 == 0).collect();
280+
/// let extracted: HashSet<i32> = set.extract_if(|v| v % 2 == 0).collect();
282281
///
283-
/// let mut evens = drained.into_iter().collect::<Vec<_>>();
282+
/// let mut evens = extracted.into_iter().collect::<Vec<_>>();
284283
/// let mut odds = set.into_iter().collect::<Vec<_>>();
285284
/// evens.sort();
286285
/// odds.sort();
@@ -290,12 +289,12 @@ impl<T, S> HashSet<T, S> {
290289
/// ```
291290
#[inline]
292291
#[rustc_lint_query_instability]
293-
#[unstable(feature = "hash_drain_filter", issue = "59618")]
294-
pub fn drain_filter<F>(&mut self, pred: F) -> DrainFilter<'_, T, F>
292+
#[unstable(feature = "hash_extract_if", issue = "59618")]
293+
pub fn extract_if<F>(&mut self, pred: F) -> ExtractIf<'_, T, F>
295294
where
296295
F: FnMut(&T) -> bool,
297296
{
298-
DrainFilter { base: self.base.drain_filter(pred) }
297+
ExtractIf { base: self.base.extract_if(pred) }
299298
}
300299

301300
/// Retains only the elements specified by the predicate.
@@ -1310,27 +1309,27 @@ pub struct Drain<'a, K: 'a> {
13101309

13111310
/// A draining, filtering iterator over the items of a `HashSet`.
13121311
///
1313-
/// This `struct` is created by the [`drain_filter`] method on [`HashSet`].
1312+
/// This `struct` is created by the [`extract_if`] method on [`HashSet`].
13141313
///
1315-
/// [`drain_filter`]: HashSet::drain_filter
1314+
/// [`extract_if`]: HashSet::extract_if
13161315
///
13171316
/// # Examples
13181317
///
13191318
/// ```
1320-
/// #![feature(hash_drain_filter)]
1319+
/// #![feature(hash_extract_if)]
13211320
///
13221321
/// use std::collections::HashSet;
13231322
///
13241323
/// let mut a = HashSet::from([1, 2, 3]);
13251324
///
1326-
/// let mut drain_filtered = a.drain_filter(|v| v % 2 == 0);
1325+
/// let mut extract_ifed = a.extract_if(|v| v % 2 == 0);
13271326
/// ```
1328-
#[unstable(feature = "hash_drain_filter", issue = "59618")]
1329-
pub struct DrainFilter<'a, K, F>
1327+
#[unstable(feature = "hash_extract_if", issue = "59618")]
1328+
pub struct ExtractIf<'a, K, F>
13301329
where
13311330
F: FnMut(&K) -> bool,
13321331
{
1333-
base: base::DrainFilter<'a, K, F>,
1332+
base: base::ExtractIf<'a, K, F>,
13341333
}
13351334

13361335
/// A lazy iterator producing elements in the intersection of `HashSet`s.
@@ -1576,8 +1575,8 @@ impl<K: fmt::Debug> fmt::Debug for Drain<'_, K> {
15761575
}
15771576
}
15781577

1579-
#[unstable(feature = "hash_drain_filter", issue = "59618")]
1580-
impl<K, F> Iterator for DrainFilter<'_, K, F>
1578+
#[unstable(feature = "hash_extract_if", issue = "59618")]
1579+
impl<K, F> Iterator for ExtractIf<'_, K, F>
15811580
where
15821581
F: FnMut(&K) -> bool,
15831582
{
@@ -1593,16 +1592,16 @@ where
15931592
}
15941593
}
15951594

1596-
#[unstable(feature = "hash_drain_filter", issue = "59618")]
1597-
impl<K, F> FusedIterator for DrainFilter<'_, K, F> where F: FnMut(&K) -> bool {}
1595+
#[unstable(feature = "hash_extract_if", issue = "59618")]
1596+
impl<K, F> FusedIterator for ExtractIf<'_, K, F> where F: FnMut(&K) -> bool {}
15981597

1599-
#[unstable(feature = "hash_drain_filter", issue = "59618")]
1600-
impl<'a, K, F> fmt::Debug for DrainFilter<'a, K, F>
1598+
#[unstable(feature = "hash_extract_if", issue = "59618")]
1599+
impl<'a, K, F> fmt::Debug for ExtractIf<'a, K, F>
16011600
where
16021601
F: FnMut(&K) -> bool,
16031602
{
16041603
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1605-
f.debug_struct("DrainFilter").finish_non_exhaustive()
1604+
f.debug_struct("ExtractIf").finish_non_exhaustive()
16061605
}
16071606
}
16081607

0 commit comments

Comments
 (0)