about summary refs log tree commit diff
path: root/src/liballoc/collections
diff options
context:
space:
mode:
authorJonas Schievink <jonasschievink@gmail.com>2019-12-12 00:14:09 +0100
committerJonas Schievink <jonasschievink@gmail.com>2019-12-12 00:14:09 +0100
commit5e32da184933e4398a99a3be13d21db857f059b5 (patch)
tree822e5983e1f9e97fda1c02822606ba75a7ed585a /src/liballoc/collections
parent27d6f55f47e8875e71083a28ed84ea5a88e1b596 (diff)
downloadrust-5e32da184933e4398a99a3be13d21db857f059b5.tar.gz
rust-5e32da184933e4398a99a3be13d21db857f059b5.zip
LinkedList: drop remaining items when drop panics
Diffstat (limited to 'src/liballoc/collections')
-rw-r--r--src/liballoc/collections/linked_list.rs16
1 files changed, 15 insertions, 1 deletions
diff --git a/src/liballoc/collections/linked_list.rs b/src/liballoc/collections/linked_list.rs
index a0c9263673d..6ee22834a46 100644
--- a/src/liballoc/collections/linked_list.rs
+++ b/src/liballoc/collections/linked_list.rs
@@ -808,7 +808,21 @@ impl<T> LinkedList<T> {
 #[stable(feature = "rust1", since = "1.0.0")]
 unsafe impl<#[may_dangle] T> Drop for LinkedList<T> {
     fn drop(&mut self) {
-        while let Some(_) = self.pop_front_node() {}
+        struct DropGuard<'a, T>(&'a mut LinkedList<T>);
+
+        impl<'a, T> Drop for DropGuard<'a, T> {
+            fn drop(&mut self) {
+                // Continue the same loop we do below. This only runs when a destructor has
+                // panicked. If another one panics this will abort.
+                while let Some(_) = self.0.pop_front_node() {}
+            }
+        }
+
+        while let Some(node) = self.pop_front_node() {
+            let guard = DropGuard(self);
+            drop(node);
+            mem::forget(guard);
+        }
     }
 }