Skip to content

Commit

Permalink
std: Mark mem::forget as a safe function
Browse files Browse the repository at this point in the history
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 rust-lang#25186
  • Loading branch information
alexcrichton committed May 7, 2015
1 parent 05d5fca commit e8ea4b4
Show file tree
Hide file tree
Showing 5 changed files with 48 additions and 11 deletions.
4 changes: 2 additions & 2 deletions src/libcollections/vec.rs
Original file line number Diff line number Diff line change
Expand Up @@ -647,7 +647,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
}

Expand Down Expand Up @@ -994,7 +994,7 @@ impl<T> Vec<T> {
num_u: 0,
marker: PhantomData,
};
unsafe { mem::forget(vec); }
mem::forget(vec);

while pv.num_t != 0 {
unsafe {
Expand Down
1 change: 0 additions & 1 deletion src/libcore/intrinsics.rs
Original file line number Diff line number Diff line change
Expand Up @@ -235,7 +235,6 @@ extern "rust-intrinsic" {
///
/// `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.
Expand Down
50 changes: 44 additions & 6 deletions src/libcore/mem.rs
Original file line number Diff line number Diff line change
Expand Up @@ -22,15 +22,53 @@ 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, you cannot write a primitive that relies on a destructor running
/// to preserve memory safety. Unsafe code must be resilient to destructors not
/// running in all circumstances.
///
/// # 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.
///
Expand Down
2 changes: 1 addition & 1 deletion src/libstd/sys/unix/fd.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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
}

Expand Down
2 changes: 1 addition & 1 deletion src/libstd/sys/windows/handle.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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;
}

Expand Down

0 comments on commit e8ea4b4

Please sign in to comment.