diff options
| author | The 8472 <git@infinite-source.de> | 2022-11-15 19:51:49 +0100 |
|---|---|---|
| committer | The 8472 <git@infinite-source.de> | 2023-06-14 09:24:51 +0200 |
| commit | b7ce7edd87c984997137eb067df2a32d4d66470c (patch) | |
| tree | 9536891d648676ce153ade1777bf7a24aa2b1499 | |
| parent | b687e84aebe871f8dc76424ceee30379d3b3381f (diff) | |
| download | rust-b7ce7edd87c984997137eb067df2a32d4d66470c.tar.gz rust-b7ce7edd87c984997137eb067df2a32d4d66470c.zip | |
remove drain-on-drop behavior from linked_list::DrainFilter and add #[must_use]
| -rw-r--r-- | library/alloc/src/collections/linked_list.rs | 32 | ||||
| -rw-r--r-- | library/alloc/src/collections/linked_list/tests.rs | 12 |
2 files changed, 14 insertions, 30 deletions
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<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, @@ -1850,33 +1855,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 F: FnMut(&mut T) -> bool, 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(); |
