about summary refs log tree commit diff
path: root/library/alloc/src/sync.rs
diff options
context:
space:
mode:
authorLukas Markeffsky <@>2024-10-27 17:48:15 +0100
committerLukas Markeffsky <@>2024-10-27 18:32:36 +0100
commit4a71a592819b6fe87377dd5f857218ed37dbf195 (patch)
tree5cd074988d5f7bfcf686cc169ff832cfc4c6ae27 /library/alloc/src/sync.rs
parent8a9f40043fb6177a8a6d720103bac4e8889e0732 (diff)
downloadrust-4a71a592819b6fe87377dd5f857218ed37dbf195.tar.gz
rust-4a71a592819b6fe87377dd5f857218ed37dbf195.zip
Rc/Arc: don't leak the allocation if drop panics
Diffstat (limited to 'library/alloc/src/sync.rs')
-rw-r--r--library/alloc/src/sync.rs16
1 files changed, 9 insertions, 7 deletions
diff --git a/library/alloc/src/sync.rs b/library/alloc/src/sync.rs
index 15a1b0f2834..98a2fe24257 100644
--- a/library/alloc/src/sync.rs
+++ b/library/alloc/src/sync.rs
@@ -1872,15 +1872,17 @@ impl<T: ?Sized, A: Allocator> Arc<T, A> {
     // Non-inlined part of `drop`.
     #[inline(never)]
     unsafe fn drop_slow(&mut self) {
+        // Drop the weak ref collectively held by all strong references when this
+        // variable goes out of scope. This ensures that the memory is deallocated
+        // even if the destructor of `T` panics.
+        // Take a reference to `self.alloc` instead of cloning because 1. it'll last long
+        // enough, and 2. you should be able to drop `Arc`s with unclonable allocators
+        let _weak = Weak { ptr: self.ptr, alloc: &self.alloc };
+
         // Destroy the data at this time, even though we must not free the box
         // allocation itself (there might still be weak pointers lying around).
-        unsafe { ptr::drop_in_place(Self::get_mut_unchecked(self)) };
-
-        // Drop the weak ref collectively held by all strong references
-        // Take a reference to `self.alloc` instead of cloning because 1. it'll
-        // last long enough, and 2. you should be able to drop `Arc`s with
-        // unclonable allocators
-        drop(Weak { ptr: self.ptr, alloc: &self.alloc });
+        // We cannot use `get_mut_unchecked` here, because `self.alloc` is borrowed.
+        unsafe { ptr::drop_in_place(&mut (*self.ptr.as_ptr()).data) };
     }
 
     /// Returns `true` if the two `Arc`s point to the same allocation in a vein similar to