summaryrefslogtreecommitdiffstats
path: root/vendor/triomphe/src/offset_arc.rs
diff options
context:
space:
mode:
Diffstat (limited to 'vendor/triomphe/src/offset_arc.rs')
-rw-r--r--vendor/triomphe/src/offset_arc.rs20
1 files changed, 12 insertions, 8 deletions
diff --git a/vendor/triomphe/src/offset_arc.rs b/vendor/triomphe/src/offset_arc.rs
index 9345416d4..4d7707e77 100644
--- a/vendor/triomphe/src/offset_arc.rs
+++ b/vendor/triomphe/src/offset_arc.rs
@@ -105,16 +105,20 @@ impl<T> OffsetArc<T> {
T: Clone,
{
unsafe {
- // extract the OffsetArc as an owned variable
+ // extract the OffsetArc as an owned variable. This does not modify
+ // the refcount and we should be careful to not drop `this`
let this = ptr::read(self);
- // treat it as a real Arc
- let mut arc = Arc::from_raw_offset(this);
- // obtain the mutable reference. Cast away the lifetime
- // This may mutate `arc`
- let ret = Arc::make_mut(&mut arc) as *mut _;
+ // treat it as a real Arc, but wrapped in a ManuallyDrop
+ // in case `Arc::make_mut()` panics in the clone impl
+ let mut arc = ManuallyDrop::new(Arc::from_raw_offset(this));
+ // obtain the mutable reference. Cast away the lifetime since
+ // we have the right lifetime bounds in the parameters.
+ // This may mutate `arc`.
+ let ret = Arc::make_mut(&mut *arc) as *mut _;
// Store the possibly-mutated arc back inside, after converting
- // it to a OffsetArc again
- ptr::write(self, Arc::into_raw_offset(arc));
+ // it to a OffsetArc again. Release the ManuallyDrop.
+ // This also does not modify the refcount or call drop on self
+ ptr::write(self, Arc::into_raw_offset(ManuallyDrop::into_inner(arc)));
&mut *ret
}
}