diff options
| author | The 8472 <git@infinite-source.de> | 2022-11-15 19:51:24 +0100 |
|---|---|---|
| committer | The 8472 <git@infinite-source.de> | 2023-06-14 09:24:51 +0200 |
| commit | b687e84aebe871f8dc76424ceee30379d3b3381f (patch) | |
| tree | 520c43ffa0402b08b138d50f90565c0cde3e1a15 /library/alloc | |
| parent | c0df1c8c432e856c4317c5c7585c86c54bcb46a2 (diff) | |
| download | rust-b687e84aebe871f8dc76424ceee30379d3b3381f.tar.gz rust-b687e84aebe871f8dc76424ceee30379d3b3381f.zip | |
remove drain-on-drop behavior from BTree{Set,Map}::DrainFilter and add #[must_use]
Diffstat (limited to 'library/alloc')
| -rw-r--r-- | library/alloc/src/collections/btree/map.rs | 24 | ||||
| -rw-r--r-- | library/alloc/src/collections/btree/map/tests.rs | 39 | ||||
| -rw-r--r-- | library/alloc/src/collections/btree/set.rs | 24 | ||||
| -rw-r--r-- | library/alloc/src/collections/btree/set/tests.rs | 11 |
4 files changed, 40 insertions, 58 deletions
diff --git a/library/alloc/src/collections/btree/map.rs b/library/alloc/src/collections/btree/map.rs index 1f8a1ecba6e..4f50cdefc3c 100644 --- a/library/alloc/src/collections/btree/map.rs +++ b/library/alloc/src/collections/btree/map.rs @@ -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, @@ -1930,16 +1928,6 @@ pub(super) struct DrainFilterInner<'a, K, V> { } #[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 K: fmt::Debug, diff --git a/library/alloc/src/collections/btree/map/tests.rs b/library/alloc/src/collections/btree/map/tests.rs index 8efd9a03ad0..1b9957fcd51 100644 --- a/library/alloc/src/collections/btree/map/tests.rs +++ b/library/alloc/src/collections/btree/map/tests.rs @@ -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); diff --git a/library/alloc/src/collections/btree/set.rs b/library/alloc/src/collections/btree/set.rs index 940fa30afb8..d8f34a7fa48 100644 --- a/library/alloc/src/collections/btree/set.rs +++ b/library/alloc/src/collections/btree/set.rs @@ -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, @@ -1293,16 +1291,6 @@ pub struct DrainFilter< } #[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 T: fmt::Debug, diff --git a/library/alloc/src/collections/btree/set/tests.rs b/library/alloc/src/collections/btree/set/tests.rs index 8eb730f4aaf..9e4be2f67ec 100644 --- a/library/alloc/src/collections/btree/set/tests.rs +++ b/library/alloc/src/collections/btree/set/tests.rs @@ -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); |
