Skip to content

Commit b7ce7ed

Browse files
committed
remove drain-on-drop behavior from linked_list::DrainFilter and add #[must_use]
1 parent b687e84 commit b7ce7ed

File tree

2 files changed

+14
-30
lines changed

2 files changed

+14
-30
lines changed

library/alloc/src/collections/linked_list.rs

Lines changed: 5 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -1030,6 +1030,10 @@ impl<T, A: Allocator> LinkedList<T, A> {
10301030
/// If the closure returns false, the element will remain in the list and will not be yielded
10311031
/// by the iterator.
10321032
///
1033+
/// If the returned `DrainFilter` is not exhausted, e.g. because it is dropped without iterating
1034+
/// or the iteration short-circuits, then the remaining elements will be retained.
1035+
/// Use `drain_filter().for_each(drop)` if you do not need the returned iterator.
1036+
///
10331037
/// Note that `drain_filter` lets you mutate every element in the filter closure, regardless of
10341038
/// whether you choose to keep or remove it.
10351039
///
@@ -1805,6 +1809,7 @@ impl<'a, T, A: Allocator> CursorMut<'a, T, A> {
18051809

18061810
/// An iterator produced by calling `drain_filter` on LinkedList.
18071811
#[unstable(feature = "drain_filter", reason = "recently added", issue = "43244")]
1812+
#[must_use = "iterators are lazy and do nothing unless consumed"]
18081813
pub struct DrainFilter<
18091814
'a,
18101815
T: 'a,
@@ -1849,33 +1854,6 @@ where
18491854
}
18501855
}
18511856

1852-
#[unstable(feature = "drain_filter", reason = "recently added", issue = "43244")]
1853-
impl<T, F, A: Allocator> Drop for DrainFilter<'_, T, F, A>
1854-
where
1855-
F: FnMut(&mut T) -> bool,
1856-
{
1857-
fn drop(&mut self) {
1858-
struct DropGuard<'r, 'a, T, F, A: Allocator>(&'r mut DrainFilter<'a, T, F, A>)
1859-
where
1860-
F: FnMut(&mut T) -> bool;
1861-
1862-
impl<'r, 'a, T, F, A: Allocator> Drop for DropGuard<'r, 'a, T, F, A>
1863-
where
1864-
F: FnMut(&mut T) -> bool,
1865-
{
1866-
fn drop(&mut self) {
1867-
self.0.for_each(drop);
1868-
}
1869-
}
1870-
1871-
while let Some(item) = self.next() {
1872-
let guard = DropGuard(self);
1873-
drop(item);
1874-
mem::forget(guard);
1875-
}
1876-
}
1877-
}
1878-
18791857
#[unstable(feature = "drain_filter", reason = "recently added", issue = "43244")]
18801858
impl<T: fmt::Debug, F> fmt::Debug for DrainFilter<'_, T, F>
18811859
where

library/alloc/src/collections/linked_list/tests.rs

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1005,17 +1005,23 @@ fn drain_filter_drop_panic_leak() {
10051005
q.push_front(d1.spawn(Panic::InDrop));
10061006
q.push_front(d0.spawn(Panic::Never));
10071007

1008-
catch_unwind(AssertUnwindSafe(|| drop(q.drain_filter(|_| true)))).unwrap_err();
1008+
catch_unwind(AssertUnwindSafe(|| q.drain_filter(|_| true).for_each(drop))).unwrap_err();
10091009

10101010
assert_eq!(d0.dropped(), 1);
10111011
assert_eq!(d1.dropped(), 1);
1012+
assert_eq!(d2.dropped(), 0);
1013+
assert_eq!(d3.dropped(), 0);
1014+
assert_eq!(d4.dropped(), 0);
1015+
assert_eq!(d5.dropped(), 0);
1016+
assert_eq!(d6.dropped(), 0);
1017+
assert_eq!(d7.dropped(), 0);
1018+
drop(q);
10121019
assert_eq!(d2.dropped(), 1);
10131020
assert_eq!(d3.dropped(), 1);
10141021
assert_eq!(d4.dropped(), 1);
10151022
assert_eq!(d5.dropped(), 1);
10161023
assert_eq!(d6.dropped(), 1);
10171024
assert_eq!(d7.dropped(), 1);
1018-
assert!(q.is_empty());
10191025
}
10201026

10211027
#[test]
@@ -1045,7 +1051,7 @@ fn drain_filter_pred_panic_leak() {
10451051
q.push_front(D(0));
10461052

10471053
catch_unwind(AssertUnwindSafe(|| {
1048-
drop(q.drain_filter(|item| if item.0 >= 2 { panic!() } else { true }))
1054+
q.drain_filter(|item| if item.0 >= 2 { panic!() } else { true }).for_each(drop)
10491055
}))
10501056
.ok();
10511057

0 commit comments

Comments
 (0)