diff --git a/library/alloc/src/collections/linked_list.rs b/library/alloc/src/collections/linked_list.rs index 4cd34ac2fa7..2e00e286edc 100644 --- a/library/alloc/src/collections/linked_list.rs +++ b/library/alloc/src/collections/linked_list.rs @@ -1030,6 +1030,10 @@ impl LinkedList { /// 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 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 fmt::Debug for DrainFilter<'_, T, F> where diff --git a/library/alloc/src/collections/linked_list/tests.rs b/library/alloc/src/collections/linked_list/tests.rs index 6a0ea618362..7627b3e8bdc 100644 --- a/library/alloc/src/collections/linked_list/tests.rs +++ b/library/alloc/src/collections/linked_list/tests.rs @@ -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();