Skip to content

Commit 8746b1a

Browse files
committed
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.
1 parent 9c30394 commit 8746b1a

File tree

1 file changed

+48
-6
lines changed

1 file changed

+48
-6
lines changed

src/libcore/mem.rs

Lines changed: 48 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -52,20 +52,61 @@ pub use intrinsics::transmute;
5252
/// * `mpsc::{Sender, Receiver}` cycles (they use `Arc` internally)
5353
/// * Panicking destructors are likely to leak local resources
5454
///
55+
/// # When To Use
56+
///
57+
/// There's only a few reasons to use this function. They mainly come
58+
/// up in unsafe code or FFI code.
59+
///
60+
/// * You have an uninitialized value, perhaps for performance reasons, and
61+
/// need to prevent the destructor from running on it.
62+
/// * You have two copies of a value (like `std::mem::swap`), but need the
63+
/// destructor to only run once to prevent a double free.
64+
/// * Transferring resources across FFI boundries.
65+
///
5566
/// # Example
5667
///
57-
/// ```rust,no_run
68+
/// Leak some heap memory by never deallocating it.
69+
///
70+
/// ```rust
5871
/// use std::mem;
59-
/// use std::fs::File;
6072
///
61-
/// // Leak some heap memory by never deallocating it
6273
/// let heap_memory = Box::new(3);
6374
/// mem::forget(heap_memory);
75+
/// ```
76+
///
77+
/// Leak an I/O object, never closing the file.
78+
///
79+
/// ```rust,no_run
80+
/// use std::mem;
81+
/// use std::fs::File;
6482
///
65-
/// // Leak an I/O object, never closing the file
6683
/// let file = File::open("foo.txt").unwrap();
6784
/// mem::forget(file);
6885
/// ```
86+
///
87+
/// The swap function uses forget to good effect.
88+
///
89+
/// ```rust
90+
/// use std::mem;
91+
/// use std::ptr;
92+
///
93+
/// fn swap<T>(x: &mut T, y: &mut T) {
94+
/// unsafe {
95+
/// // Give ourselves some scratch space to work with
96+
/// let mut t: T = mem::uninitialized();
97+
///
98+
/// // Perform the swap, `&mut` pointers never alias
99+
/// ptr::copy_nonoverlapping(&*x, &mut t, 1);
100+
/// ptr::copy_nonoverlapping(&*y, x, 1);
101+
/// ptr::copy_nonoverlapping(&t, y, 1);
102+
///
103+
/// // y and t now point to the same thing, but we need to completely
104+
/// // forget `t` because we do not want to run the destructor for `T`
105+
/// // on its value, which is still owned somewhere outside this function.
106+
/// mem::forget(t);
107+
/// }
108+
/// }
109+
/// ```
69110
#[stable(feature = "rust1", since = "1.0.0")]
70111
pub fn forget<T>(t: T) {
71112
unsafe { intrinsics::forget(t) }
@@ -267,8 +308,9 @@ pub fn swap<T>(x: &mut T, y: &mut T) {
267308
ptr::copy_nonoverlapping(&*y, x, 1);
268309
ptr::copy_nonoverlapping(&t, y, 1);
269310

270-
// y and t now point to the same thing, but we need to completely forget `t`
271-
// because it's no longer relevant.
311+
// y and t now point to the same thing, but we need to completely
312+
// forget `t` because we do not want to run the destructor for `T`
313+
// on its value, which is still owned somewhere outside this function.
272314
forget(t);
273315
}
274316
}

0 commit comments

Comments
 (0)