diff --git a/src/clear.rs b/src/clear.rs index 5c3f70c..7056e19 100644 --- a/src/clear.rs +++ b/src/clear.rs @@ -65,7 +65,11 @@ where let ptr = self as *mut Self; ptr::drop_in_place(ptr); ptr::write_bytes(ptr as *mut u8, 0, size); - hide_mem_impl::(ptr); + + if !cfg!(miri) { + hide_mem_impl::(ptr); + } + Self::initialize(ptr); } } @@ -135,7 +139,7 @@ macro_rules! array_impl_zerosafe { } // Implement for fixed-size arrays of ZeroSafe up to 64 -array_impl_zerosafe!{ +array_impl_zerosafe! { 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 diff --git a/src/clear_on_drop.rs b/src/clear_on_drop.rs index 83ef2f7..54f69fc 100644 --- a/src/clear_on_drop.rs +++ b/src/clear_on_drop.rs @@ -1,10 +1,10 @@ use core::borrow::{Borrow, BorrowMut}; use core::cmp::Ordering; -use core::fmt; use core::hash::{Hash, Hasher}; -use core::mem; +use core::mem::ManuallyDrop; use core::ops::{Deref, DerefMut}; use core::ptr; +use core::{fmt, mem}; use crate::clear::Clear; @@ -37,7 +37,7 @@ where P: DerefMut, P::Target: Clear, { - _place: P, + _place: ManuallyDrop

, } impl

ClearOnDrop

@@ -56,7 +56,9 @@ where /// back, use `ClearOnDrop::into_place(...)` instead of a borrow. #[inline] pub fn new(place: P) -> Self { - ClearOnDrop { _place: place } + ClearOnDrop { + _place: ManuallyDrop::new(place), + } } /// Consumes the `ClearOnDrop`, returning the `place` after clearing. @@ -78,11 +80,15 @@ where /// `c.into_uncleared_place()`. This is so that there is no conflict /// with a method on the inner type. #[inline] - pub fn into_uncleared_place(c: Self) -> P { + pub fn into_uncleared_place(mut c: Self) -> P { unsafe { let place = ptr::read(&c._place); - mem::forget(c); - place + ptr::write_bytes( + &mut c._place as *mut _ as *mut u8, + 0, + mem::size_of::>(), + ); + ManuallyDrop::into_inner(place) } } } @@ -126,7 +132,7 @@ where #[inline] fn deref(&self) -> &Self::Target { - Deref::deref(&self._place) + Deref::deref(&self._place as &P) } } @@ -137,7 +143,7 @@ where { #[inline] fn deref_mut(&mut self) -> &mut Self::Target { - DerefMut::deref_mut(&mut self._place) + DerefMut::deref_mut(&mut self._place as &mut P) } } @@ -148,7 +154,16 @@ where { #[inline] fn drop(&mut self) { - self.clear(); + let ptr = &mut self._place as *mut _ as *mut u8; + unsafe { + if (0..mem::size_of::>() as isize) + .fold(0, |acc, i| acc + *ptr.offset(i) as i32) + != 0 + { + self.clear(); + ManuallyDrop::drop(&mut self._place); + } + } } } @@ -161,7 +176,7 @@ where { #[inline] fn as_ref(&self) -> &T { - AsRef::as_ref(&self._place) + AsRef::as_ref(&self._place as &P) } } @@ -172,7 +187,7 @@ where { #[inline] fn as_mut(&mut self) -> &mut T { - AsMut::as_mut(&mut self._place) + AsMut::as_mut(&mut self._place as &mut P) } } @@ -190,7 +205,7 @@ where { #[inline] fn borrow(&self) -> &T { - Borrow::borrow(&self._place) + Borrow::borrow(&self._place as &P) } } @@ -202,7 +217,7 @@ where { #[inline] fn borrow_mut(&mut self) -> &mut T { - BorrowMut::borrow_mut(&mut self._place) + BorrowMut::borrow_mut(&mut self._place as &mut P) } } @@ -215,7 +230,7 @@ where { #[inline] fn hash(&self, state: &mut H) { - Hash::hash(&self._place, state) + Hash::hash(&self._place as &P, state) } } @@ -230,12 +245,12 @@ where { #[inline] fn eq(&self, other: &ClearOnDrop) -> bool { - PartialEq::eq(&self._place, &other._place) + PartialEq::eq(&self._place as &P, &other._place as &Q) } #[inline] fn ne(&self, other: &ClearOnDrop) -> bool { - PartialEq::ne(&self._place, &other._place) + PartialEq::ne(&self._place as &P, &other._place as &Q) } } @@ -255,27 +270,27 @@ where { #[inline] fn partial_cmp(&self, other: &ClearOnDrop) -> Option { - PartialOrd::partial_cmp(&self._place, &other._place) + PartialOrd::partial_cmp(&self._place as &P, &other._place as &Q) } #[inline] fn lt(&self, other: &ClearOnDrop) -> bool { - PartialOrd::lt(&self._place, &other._place) + PartialOrd::lt(&self._place as &P, &other._place as &Q) } #[inline] fn le(&self, other: &ClearOnDrop) -> bool { - PartialOrd::le(&self._place, &other._place) + PartialOrd::le(&self._place as &P, &other._place as &Q) } #[inline] fn gt(&self, other: &ClearOnDrop) -> bool { - PartialOrd::gt(&self._place, &other._place) + PartialOrd::gt(&self._place as &P, &other._place as &Q) } #[inline] fn ge(&self, other: &ClearOnDrop) -> bool { - PartialOrd::ge(&self._place, &other._place) + PartialOrd::ge(&self._place as &P, &other._place as &Q) } } @@ -286,7 +301,7 @@ where { #[inline] fn cmp(&self, other: &Self) -> Ordering { - Ord::cmp(&self._place, &other._place) + Ord::cmp(&self._place as &P, &other._place as &P) } } @@ -320,6 +335,7 @@ mod tests { assert_eq!(clear.data, DATA); } + #[cfg(not(miri))] #[test] fn into_box() { let place: Box = Box::new(Default::default()); @@ -389,6 +405,7 @@ mod tests { assert_eq!(&clear[..], "test"); } + #[cfg(not(miri))] #[test] fn into_string() { let place: String = "test".into(); diff --git a/src/hide.rs b/src/hide.rs index 91dca40..0e3bf25 100644 --- a/src/hide.rs +++ b/src/hide.rs @@ -88,6 +88,7 @@ mod impls { } #[cfg(test)] +#[cfg(not(miri))] mod tests { struct Place { data: [u32; 4],