summary refs log tree commit diff
path: root/src
diff options
context:
space:
mode:
authorAlex Crichton <alex@alexcrichton.com>2015-05-07 10:49:39 -0700
committerAlex Crichton <alex@alexcrichton.com>2015-05-10 23:16:54 -0700
commit7b78086ba4c6bfc656bc0d8b3171aa9929f593dc (patch)
treec4cadace8c4dbab06b369050d522975e960af518 /src
parent8421c7cfc8507f37d906447afaaa80cb09ca2cbe (diff)
downloadrust-7b78086ba4c6bfc656bc0d8b3171aa9929f593dc.tar.gz
rust-7b78086ba4c6bfc656bc0d8b3171aa9929f593dc.zip
std: Mark `mem::forget` as a safe function
This commit is an implementation of [RFC 1066][rfc] where the conclusion was
that leaking a value is a safe operation in Rust code, so updating the signature
of this function follows suit.

[rfc]: https://github.com/rust-lang/rfcs/blob/master/text/1066-safe-mem-forget.md

Closes #25186
Diffstat (limited to 'src')
-rw-r--r--src/libcollections/vec.rs4
-rw-r--r--src/libcore/intrinsics.rs4
-rw-r--r--src/libcore/mem.rs51
-rw-r--r--src/libstd/sys/unix/fd.rs2
-rw-r--r--src/libstd/sys/windows/handle.rs2
5 files changed, 49 insertions, 14 deletions
diff --git a/src/libcollections/vec.rs b/src/libcollections/vec.rs
index 6195056579d..d5112c9fdff 100644
--- a/src/libcollections/vec.rs
+++ b/src/libcollections/vec.rs
@@ -637,7 +637,7 @@ impl<T> Vec<T> {
             // 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
         }
 
@@ -959,7 +959,7 @@ impl<T> Vec<T> {
                 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 8ed89adec5b..077d6367ff3 100644
--- a/src/libcore/intrinsics.rs
+++ b/src/libcore/intrinsics.rs
@@ -217,10 +217,6 @@ extern "rust-intrinsic" {
     pub fn uninit<T>() -> 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>(_: 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 c4128e79765..a149af3a440 100644
--- a/src/libcore/mem.rs
+++ b/src/libcore/mem.rs
@@ -22,15 +22,54 @@ use ptr;
 #[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: 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 e5bdb554359..026380027d2 100644
--- a/src/libstd/sys/unix/fd.rs
+++ b/src/libstd/sys/unix/fd.rs
@@ -31,7 +31,7 @@ impl FileDesc {
     /// 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 9481e180ce5..c835d503388 100644
--- a/src/libstd/sys/windows/handle.rs
+++ b/src/libstd/sys/windows/handle.rs
@@ -32,7 +32,7 @@ impl Handle {
 
     pub fn into_raw(self) -> HANDLE {
         let ret = self.0;
-        unsafe { mem::forget(self) }
+        mem::forget(self);
         return ret;
     }