From 8746b1ac6f3c95383a19ad2ab365a62140516206 Mon Sep 17 00:00:00 2001 From: Tim Ringenbach Date: Thu, 28 May 2015 13:04:17 -0500 Subject: [PATCH] Improve mem::forget documentation This adds an example from mem::swap, and provides some suggested uses of this function. Change wording on comment on forget line to be more specific as to why we need to call forget. This breaks the examples up into three pieces. The last piece isn't compiling for some reason. --- src/libcore/mem.rs | 56 ++++++++++++++++++++++++++++++++++++++++------ 1 file changed, 49 insertions(+), 7 deletions(-) diff --git a/src/libcore/mem.rs b/src/libcore/mem.rs index 7749d053285..26c6e899df1 100644 --- a/src/libcore/mem.rs +++ b/src/libcore/mem.rs @@ -52,20 +52,61 @@ pub use intrinsics::transmute; /// * `mpsc::{Sender, Receiver}` cycles (they use `Arc` internally) /// * Panicking destructors are likely to leak local resources /// +/// # When To Use +/// +/// There's only a few reasons to use this function. They mainly come +/// up in unsafe code or FFI code. +/// +/// * You have an uninitialized value, perhaps for performance reasons, and +/// need to prevent the destructor from running on it. +/// * You have two copies of a value (like `std::mem::swap`), but need the +/// destructor to only run once to prevent a double free. +/// * Transferring resources across FFI boundries. +/// /// # Example /// +/// Leak some heap memory by never deallocating it. +/// +/// ```rust +/// use std::mem; +/// +/// let heap_memory = Box::new(3); +/// mem::forget(heap_memory); +/// ``` +/// +/// Leak an I/O object, never closing the file. +/// /// ```rust,no_run /// use std::mem; /// use std::fs::File; /// -/// // Leak some heap memory by never deallocating it -/// let heap_memory = Box::new(3); -/// mem::forget(heap_memory); -/// -/// // Leak an I/O object, never closing the file /// let file = File::open("foo.txt").unwrap(); /// mem::forget(file); /// ``` +/// +/// The swap function uses forget to good effect. +/// +/// ```rust +/// use std::mem; +/// use std::ptr; +/// +/// fn swap(x: &mut T, y: &mut T) { +/// unsafe { +/// // Give ourselves some scratch space to work with +/// let mut t: T = mem::uninitialized(); +/// +/// // Perform the swap, `&mut` pointers never alias +/// ptr::copy_nonoverlapping(&*x, &mut t, 1); +/// ptr::copy_nonoverlapping(&*y, x, 1); +/// ptr::copy_nonoverlapping(&t, y, 1); +/// +/// // y and t now point to the same thing, but we need to completely +/// // forget `t` because we do not want to run the destructor for `T` +/// // on its value, which is still owned somewhere outside this function. +/// mem::forget(t); +/// } +/// } +/// ``` #[stable(feature = "rust1", since = "1.0.0")] pub fn forget(t: T) { unsafe { intrinsics::forget(t) } @@ -267,8 +308,9 @@ pub fn swap(x: &mut T, y: &mut T) { ptr::copy_nonoverlapping(&*y, x, 1); ptr::copy_nonoverlapping(&t, y, 1); - // y and t now point to the same thing, but we need to completely forget `t` - // because it's no longer relevant. + // y and t now point to the same thing, but we need to completely + // forget `t` because we do not want to run the destructor for `T` + // on its value, which is still owned somewhere outside this function. forget(t); } }