From 9f8f366eeabee6273abf3628bb75ecd3b4b57f22 Mon Sep 17 00:00:00 2001 From: Nikita Popov Date: Sun, 6 May 2018 16:55:04 +0200 Subject: [PATCH] Use ManuallyDrop instead of Option in Hole implementation The Option is always Some until drop, where it becomes None. Make this more explicit and avoid unwraps by using ManuallyDrop. This change should be performance-neutral as LLVM already optimizes the unwraps away in the inlined code. --- src/liballoc/binary_heap.rs | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/src/liballoc/binary_heap.rs b/src/liballoc/binary_heap.rs index 668b61c51d8bc..fcadcb544c431 100644 --- a/src/liballoc/binary_heap.rs +++ b/src/liballoc/binary_heap.rs @@ -157,7 +157,7 @@ use core::ops::{Deref, DerefMut}; use core::iter::{FromIterator, FusedIterator}; -use core::mem::{swap, size_of}; +use core::mem::{swap, size_of, ManuallyDrop}; use core::ptr; use core::fmt; @@ -864,8 +864,7 @@ impl BinaryHeap { /// position with the value that was originally removed. struct Hole<'a, T: 'a> { data: &'a mut [T], - /// `elt` is always `Some` from new until drop. - elt: Option, + elt: ManuallyDrop, pos: usize, } @@ -879,7 +878,7 @@ impl<'a, T> Hole<'a, T> { let elt = ptr::read(&data[pos]); Hole { data, - elt: Some(elt), + elt: ManuallyDrop::new(elt), pos, } } @@ -892,7 +891,7 @@ impl<'a, T> Hole<'a, T> { /// Returns a reference to the element removed. #[inline] fn element(&self) -> &T { - self.elt.as_ref().unwrap() + &self.elt } /// Returns a reference to the element at `index`. @@ -925,7 +924,7 @@ impl<'a, T> Drop for Hole<'a, T> { // fill the hole again unsafe { let pos = self.pos; - ptr::write(self.data.get_unchecked_mut(pos), self.elt.take().unwrap()); + ptr::copy_nonoverlapping(&*self.elt, self.data.get_unchecked_mut(pos), 1); } } }