mirror of
https://github.com/rust-lang/rust.git
synced 2024-11-02 07:22:42 +00:00
remove drain-on-drop behavior from linked_list::DrainFilter and add #[must_use]
This commit is contained in:
parent
b687e84aeb
commit
b7ce7edd87
@ -1030,6 +1030,10 @@ impl<T, A: Allocator> LinkedList<T, A> {
|
||||
/// If the closure returns false, the element will remain in the list and will not be yielded
|
||||
/// by the iterator.
|
||||
///
|
||||
/// 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 `drain_filter().for_each(drop)` if you do not need the returned iterator.
|
||||
///
|
||||
/// Note that `drain_filter` lets you mutate every element in the filter closure, regardless of
|
||||
/// whether you choose to keep or remove it.
|
||||
///
|
||||
@ -1805,6 +1809,7 @@ impl<'a, T, A: Allocator> CursorMut<'a, T, A> {
|
||||
|
||||
/// An iterator produced by calling `drain_filter` on LinkedList.
|
||||
#[unstable(feature = "drain_filter", reason = "recently added", issue = "43244")]
|
||||
#[must_use = "iterators are lazy and do nothing unless consumed"]
|
||||
pub struct DrainFilter<
|
||||
'a,
|
||||
T: 'a,
|
||||
@ -1849,33 +1854,6 @@ where
|
||||
}
|
||||
}
|
||||
|
||||
#[unstable(feature = "drain_filter", reason = "recently added", issue = "43244")]
|
||||
impl<T, F, A: Allocator> Drop for DrainFilter<'_, T, F, A>
|
||||
where
|
||||
F: FnMut(&mut T) -> bool,
|
||||
{
|
||||
fn drop(&mut self) {
|
||||
struct DropGuard<'r, 'a, T, F, A: Allocator>(&'r mut DrainFilter<'a, T, F, A>)
|
||||
where
|
||||
F: FnMut(&mut T) -> bool;
|
||||
|
||||
impl<'r, 'a, T, F, A: Allocator> Drop for DropGuard<'r, 'a, T, F, A>
|
||||
where
|
||||
F: FnMut(&mut T) -> bool,
|
||||
{
|
||||
fn drop(&mut self) {
|
||||
self.0.for_each(drop);
|
||||
}
|
||||
}
|
||||
|
||||
while let Some(item) = self.next() {
|
||||
let guard = DropGuard(self);
|
||||
drop(item);
|
||||
mem::forget(guard);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[unstable(feature = "drain_filter", reason = "recently added", issue = "43244")]
|
||||
impl<T: fmt::Debug, F> fmt::Debug for DrainFilter<'_, T, F>
|
||||
where
|
||||
|
@ -1005,17 +1005,23 @@ fn drain_filter_drop_panic_leak() {
|
||||
q.push_front(d1.spawn(Panic::InDrop));
|
||||
q.push_front(d0.spawn(Panic::Never));
|
||||
|
||||
catch_unwind(AssertUnwindSafe(|| drop(q.drain_filter(|_| true)))).unwrap_err();
|
||||
catch_unwind(AssertUnwindSafe(|| q.drain_filter(|_| true).for_each(drop))).unwrap_err();
|
||||
|
||||
assert_eq!(d0.dropped(), 1);
|
||||
assert_eq!(d1.dropped(), 1);
|
||||
assert_eq!(d2.dropped(), 0);
|
||||
assert_eq!(d3.dropped(), 0);
|
||||
assert_eq!(d4.dropped(), 0);
|
||||
assert_eq!(d5.dropped(), 0);
|
||||
assert_eq!(d6.dropped(), 0);
|
||||
assert_eq!(d7.dropped(), 0);
|
||||
drop(q);
|
||||
assert_eq!(d2.dropped(), 1);
|
||||
assert_eq!(d3.dropped(), 1);
|
||||
assert_eq!(d4.dropped(), 1);
|
||||
assert_eq!(d5.dropped(), 1);
|
||||
assert_eq!(d6.dropped(), 1);
|
||||
assert_eq!(d7.dropped(), 1);
|
||||
assert!(q.is_empty());
|
||||
}
|
||||
|
||||
#[test]
|
||||
@ -1045,7 +1051,7 @@ fn drain_filter_pred_panic_leak() {
|
||||
q.push_front(D(0));
|
||||
|
||||
catch_unwind(AssertUnwindSafe(|| {
|
||||
drop(q.drain_filter(|item| if item.0 >= 2 { panic!() } else { true }))
|
||||
q.drain_filter(|item| if item.0 >= 2 { panic!() } else { true }).for_each(drop)
|
||||
}))
|
||||
.ok();
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user