diff --git a/src/libcollections/vec.rs b/src/libcollections/vec.rs index 69f877cbf1c8b5220c8971cd9321273f99c9c304..66bb84205e21ce72f2c48e3b60437b87e09265c9 100644 --- a/src/libcollections/vec.rs +++ b/src/libcollections/vec.rs @@ -647,7 +647,7 @@ fn resize(vec: &mut Vec) { // zero-size types consume no memory, so we can't rely on the // address space running out self.len = self.len.checked_add(1).expect("length overflow"); - unsafe { mem::forget(value); } + mem::forget(value); return } @@ -994,7 +994,7 @@ pub fn map_in_place(self, mut f: F) -> Vec where F: FnMut(T) -> U { num_u: 0, marker: PhantomData, }; - unsafe { mem::forget(vec); } + mem::forget(vec); while pv.num_t != 0 { unsafe { diff --git a/src/libcore/intrinsics.rs b/src/libcore/intrinsics.rs index 101381e2c71efa7b495342e8b6abb1b8e32daca9..100b7e70591f9c10d749fe53eed7ceefcfb842b1 100644 --- a/src/libcore/intrinsics.rs +++ b/src/libcore/intrinsics.rs @@ -232,10 +232,6 @@ pub fn uninit() -> T; /// Moves a value out of scope without running drop glue. - /// - /// `forget` is unsafe because the caller is responsible for - /// ensuring the argument is deallocated already. - #[stable(feature = "rust1", since = "1.0.0")] pub fn forget(_: T) -> (); /// Unsafely transforms a value of one type into a value of another type. diff --git a/src/libcore/mem.rs b/src/libcore/mem.rs index c4128e79765c8157a8f738b2eb090b7a0d463c1f..a149af3a44063c44afa1376f589af192ced14c47 100644 --- a/src/libcore/mem.rs +++ b/src/libcore/mem.rs @@ -22,15 +22,54 @@ #[stable(feature = "rust1", since = "1.0.0")] pub use intrinsics::transmute; -/// Moves a thing into the void. +/// Leaks a value into the void, consuming ownership and never running its +/// destructor. /// -/// The forget function will take ownership of the provided value but neglect -/// to run any required cleanup or memory management operations on it. +/// This function will take ownership of its argument, but is distinct from the +/// `mem::drop` function in that it **does not run the destructor**, leaking the +/// value and any resources that it owns. /// -/// This function is the unsafe version of the `drop` function because it does -/// not run any destructors. +/// # Safety +/// +/// This function is not marked as `unsafe` as Rust does not guarantee that the +/// `Drop` implementation for a value will always run. Note, however, that +/// leaking resources such as memory or I/O objects is likely not desired, so +/// this function is only recommended for specialized use cases. +/// +/// The safety of this function implies that when writing `unsafe` code +/// yourself care must be taken when leveraging a destructor that is required to +/// run to preserve memory safety. There are known situations where the +/// destructor may not run (such as if ownership of the object with the +/// destructor is returned) which must be taken into account. +/// +/// # Other forms of Leakage +/// +/// It's important to point out that this function is not the only method by +/// which a value can be leaked in safe Rust code. Other known sources of +/// leakage are: +/// +/// * `Rc` and `Arc` cycles +/// * `mpsc::{Sender, Receiver}` cycles (they use `Arc` internally) +/// * Panicking destructors are likely to leak local resources +/// +/// # Example +/// +/// ```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); +/// ``` #[stable(feature = "rust1", since = "1.0.0")] -pub use intrinsics::forget; +pub fn forget(t: T) { + unsafe { intrinsics::forget(t) } +} /// Returns the size of a type in bytes. /// diff --git a/src/libstd/sys/unix/fd.rs b/src/libstd/sys/unix/fd.rs index e5bdb554359df6257ddf43929c7dce9dc922fa11..026380027d29e58f7c01dcc482a48d43f151677e 100644 --- a/src/libstd/sys/unix/fd.rs +++ b/src/libstd/sys/unix/fd.rs @@ -31,7 +31,7 @@ pub fn raw(&self) -> c_int { self.fd } /// Extracts the actual filedescriptor without closing it. pub fn into_raw(self) -> c_int { let fd = self.fd; - unsafe { mem::forget(self) }; + mem::forget(self); fd } diff --git a/src/libstd/sys/windows/handle.rs b/src/libstd/sys/windows/handle.rs index 9481e180ce5781a42219c79cd2b79b93ed574c4c..c835d503388c7c57925a171d4d49337e9fb47d81 100644 --- a/src/libstd/sys/windows/handle.rs +++ b/src/libstd/sys/windows/handle.rs @@ -32,7 +32,7 @@ pub fn raw(&self) -> HANDLE { self.0 } pub fn into_raw(self) -> HANDLE { let ret = self.0; - unsafe { mem::forget(self) } + mem::forget(self); return ret; }