Skip to content

Commit 7132092

Browse files
committed
Auto merge of #25187 - alexcrichton:mem-forget-safe, r=brson
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
2 parents cf76e63 + dd59b1f commit 7132092

File tree

5 files changed

+49
-14
lines changed

5 files changed

+49
-14
lines changed

src/libcollections/vec.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -647,7 +647,7 @@ impl<T> Vec<T> {
647647
// zero-size types consume no memory, so we can't rely on the
648648
// address space running out
649649
self.len = self.len.checked_add(1).expect("length overflow");
650-
unsafe { mem::forget(value); }
650+
mem::forget(value);
651651
return
652652
}
653653

@@ -994,7 +994,7 @@ impl<T> Vec<T> {
994994
num_u: 0,
995995
marker: PhantomData,
996996
};
997-
unsafe { mem::forget(vec); }
997+
mem::forget(vec);
998998

999999
while pv.num_t != 0 {
10001000
unsafe {

src/libcore/intrinsics.rs

-4
Original file line numberDiff line numberDiff line change
@@ -232,10 +232,6 @@ extern "rust-intrinsic" {
232232
pub fn uninit<T>() -> T;
233233

234234
/// Moves a value out of scope without running drop glue.
235-
///
236-
/// `forget` is unsafe because the caller is responsible for
237-
/// ensuring the argument is deallocated already.
238-
#[stable(feature = "rust1", since = "1.0.0")]
239235
pub fn forget<T>(_: T) -> ();
240236

241237
/// Unsafely transforms a value of one type into a value of another type.

src/libcore/mem.rs

+45-6
Original file line numberDiff line numberDiff line change
@@ -22,15 +22,54 @@ use ptr;
2222
#[stable(feature = "rust1", since = "1.0.0")]
2323
pub use intrinsics::transmute;
2424

25-
/// Moves a thing into the void.
25+
/// Leaks a value into the void, consuming ownership and never running its
26+
/// destructor.
2627
///
27-
/// The forget function will take ownership of the provided value but neglect
28-
/// to run any required cleanup or memory management operations on it.
28+
/// This function will take ownership of its argument, but is distinct from the
29+
/// `mem::drop` function in that it **does not run the destructor**, leaking the
30+
/// value and any resources that it owns.
2931
///
30-
/// This function is the unsafe version of the `drop` function because it does
31-
/// not run any destructors.
32+
/// # Safety
33+
///
34+
/// This function is not marked as `unsafe` as Rust does not guarantee that the
35+
/// `Drop` implementation for a value will always run. Note, however, that
36+
/// leaking resources such as memory or I/O objects is likely not desired, so
37+
/// this function is only recommended for specialized use cases.
38+
///
39+
/// The safety of this function implies that when writing `unsafe` code
40+
/// yourself care must be taken when leveraging a destructor that is required to
41+
/// run to preserve memory safety. There are known situations where the
42+
/// destructor may not run (such as if ownership of the object with the
43+
/// destructor is returned) which must be taken into account.
44+
///
45+
/// # Other forms of Leakage
46+
///
47+
/// It's important to point out that this function is not the only method by
48+
/// which a value can be leaked in safe Rust code. Other known sources of
49+
/// leakage are:
50+
///
51+
/// * `Rc` and `Arc` cycles
52+
/// * `mpsc::{Sender, Receiver}` cycles (they use `Arc` internally)
53+
/// * Panicking destructors are likely to leak local resources
54+
///
55+
/// # Example
56+
///
57+
/// ```rust,no_run
58+
/// use std::mem;
59+
/// use std::fs::File;
60+
///
61+
/// // Leak some heap memory by never deallocating it
62+
/// let heap_memory = Box::new(3);
63+
/// mem::forget(heap_memory);
64+
///
65+
/// // Leak an I/O object, never closing the file
66+
/// let file = File::open("foo.txt").unwrap();
67+
/// mem::forget(file);
68+
/// ```
3269
#[stable(feature = "rust1", since = "1.0.0")]
33-
pub use intrinsics::forget;
70+
pub fn forget<T>(t: T) {
71+
unsafe { intrinsics::forget(t) }
72+
}
3473

3574
/// Returns the size of a type in bytes.
3675
///

src/libstd/sys/unix/fd.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,7 @@ impl FileDesc {
3131
/// Extracts the actual filedescriptor without closing it.
3232
pub fn into_raw(self) -> c_int {
3333
let fd = self.fd;
34-
unsafe { mem::forget(self) };
34+
mem::forget(self);
3535
fd
3636
}
3737

src/libstd/sys/windows/handle.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,7 @@ impl Handle {
3232

3333
pub fn into_raw(self) -> HANDLE {
3434
let ret = self.0;
35-
unsafe { mem::forget(self) }
35+
mem::forget(self);
3636
return ret;
3737
}
3838

0 commit comments

Comments
 (0)