Skip to content

Commit f6e5661

Browse files
committed
Implement Manually Drop
1 parent 2c48ae6 commit f6e5661

File tree

1 file changed

+96
-0
lines changed

1 file changed

+96
-0
lines changed

src/libcore/mem.rs

Lines changed: 96 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -736,3 +736,99 @@ pub fn discriminant<T>(v: &T) -> Discriminant<T> {
736736
}
737737
}
738738

739+
740+
/// A wrapper to inhibit compiler from automatically calling `T`’s destructor.
741+
///
742+
/// This wrapper is 0-cost.
743+
///
744+
/// # Examples
745+
///
746+
/// This wrapper helps with explicitly documenting the drop order dependencies between fields of
747+
/// the type:
748+
///
749+
/// ```rust
750+
/// # #![feature(manually_drop)]
751+
/// use std::mem::ManuallyDrop;
752+
/// struct Peach;
753+
/// struct Banana;
754+
/// struct Melon;
755+
/// struct FruitBox {
756+
/// // Immediately clear there’s something non-trivial going on with these fields.
757+
/// peach: ManuallyDrop<Peach>,
758+
/// melon: Melon, // Field that’s independent of the other two.
759+
/// banana: ManuallyDrop<Banana>,
760+
/// }
761+
///
762+
/// impl Drop for FruitBox {
763+
/// fn drop(&mut self) {
764+
/// unsafe {
765+
/// // Explicit ordering in which field destructors are run specified in the intuitive
766+
/// // location – the destructor of the structure containing the fields.
767+
/// // Moreover, one can now reorder fields within the struct however much they want.
768+
/// ManuallyDrop::drop(&mut self.peach);
769+
/// ManuallyDrop::drop(&mut self.banana);
770+
/// }
771+
/// // After destructor for `FruitBox` runs (this function), the destructor for Melon gets
772+
/// // invoked in the usual manner, as it is not wrapped in `ManuallyDrop`.
773+
/// }
774+
/// }
775+
/// ```
776+
#[unstable(feature = "manually_drop", issue = "40673")]
777+
#[allow(unions_with_drop_fields)]
778+
pub union ManuallyDrop<T>{ value: T }
779+
780+
impl<T> ManuallyDrop<T> {
781+
/// Wrap a value to be manually dropped.
782+
#[unstable(feature = "manually_drop", issue = "40673")]
783+
pub fn new(value: T) -> ManuallyDrop<T> {
784+
ManuallyDrop { value: value }
785+
}
786+
787+
/// Extract the value from the ManuallyDrop container.
788+
#[unstable(feature = "manually_drop", issue = "40673")]
789+
pub fn into_inner(self) -> T {
790+
unsafe {
791+
self.value
792+
}
793+
}
794+
795+
/// Manually drops the contained value.
796+
///
797+
/// # Unsafety
798+
///
799+
/// This function runs the destructor of the contained value and thus the wrapped value
800+
/// now represents uninitialized data. It is up to the user of this method to ensure the
801+
/// uninitialized data is not actually used.
802+
#[unstable(feature = "manually_drop", issue = "40673")]
803+
pub unsafe fn drop(slot: &mut ManuallyDrop<T>) {
804+
ptr::drop_in_place(&mut slot.value)
805+
}
806+
}
807+
808+
#[unstable(feature = "manually_drop", issue = "40673")]
809+
impl<T> ::ops::Deref for ManuallyDrop<T> {
810+
type Target = T;
811+
fn deref(&self) -> &Self::Target {
812+
unsafe {
813+
&self.value
814+
}
815+
}
816+
}
817+
818+
#[unstable(feature = "manually_drop", issue = "40673")]
819+
impl<T> ::ops::DerefMut for ManuallyDrop<T> {
820+
fn deref_mut(&mut self) -> &mut Self::Target {
821+
unsafe {
822+
&mut self.value
823+
}
824+
}
825+
}
826+
827+
#[unstable(feature = "manually_drop", issue = "40673")]
828+
impl<T: ::fmt::Debug> ::fmt::Debug for ManuallyDrop<T> {
829+
fn fmt(&self, fmt: &mut ::fmt::Formatter) -> ::fmt::Result {
830+
unsafe {
831+
fmt.debug_tuple("ManuallyDrop").field(&self.value).finish()
832+
}
833+
}
834+
}

0 commit comments

Comments
 (0)