@@ -45,8 +45,9 @@ pub use crate::intrinsics::transmute;
4545/// `mem::forget` from safe code does not fundamentally change Rust's safety
4646/// guarantees.
4747///
48- /// That said, leaking resources such as memory or I/O objects is usually undesirable,
49- /// so `forget` is only recommended for specialized use cases like those shown below.
48+ /// That said, leaking resources such as memory or I/O objects is usually undesirable.
49+ /// The need comes up in some specialized use cases for FFI or unsafe code, but even
50+ /// then, [`ManuallyDrop`] is typically preferred.
5051///
5152/// Because forgetting a value is allowed, any `unsafe` code you write must
5253/// allow for this possibility. You cannot return a value and expect that the
@@ -68,7 +69,35 @@ pub use crate::intrinsics::transmute;
6869/// ```
6970///
7071/// The practical use cases for `forget` are rather specialized and mainly come
71- /// up in unsafe or FFI code.
72+ /// up in unsafe or FFI code. However, [`ManuallyDrop`] is usually preferred
73+ /// for such cases, e.g.:
74+ ///
75+ /// ```
76+ /// use std::mem::ManuallyDrop;
77+ ///
78+ /// let v = vec![65, 122];
79+ /// // Before we disassemble `v` into its raw parts, make sure it
80+ /// // does not get dropped!
81+ /// let mut v = ManuallyDrop::new(v);
82+ /// // Now disassemble `v`. These operations cannot panic, so there cannot be a leak.
83+ /// let ptr = v.as_mut_ptr();
84+ /// let cap = v.capacity();
85+ /// // Finally, build a `String`.
86+ /// let s = unsafe { String::from_raw_parts(ptr, 2, cap) };
87+ /// assert_eq!(s, "Az");
88+ /// // `s` is implicitly dropped and its memory deallocated.
89+ /// ```
90+ ///
91+ /// Using `ManuallyDrop` here has two advantages:
92+ ///
93+ /// * We do not "touch" `v` after disassembling it. For some types, operations
94+ /// such as passing ownership (to a funcion like `mem::forget`) requires them to actually
95+ /// be fully owned right now; that is a promise we do not want to make here as we are
96+ /// in the process of transferring ownership to the new `String` we are building.
97+ /// * In case of an unexpected panic, `ManuallyDrop` is not dropped, but if the panic
98+ /// occurs before `mem::forget` was called we might end up dropping invalid data,
99+ /// or double-dropping. In other words, `ManuallyDrop` errs on the side of leaking
100+ /// instead of erring on the side of dropping.
72101///
73102/// [drop]: fn.drop.html
74103/// [uninit]: fn.uninitialized.html
@@ -78,6 +107,7 @@ pub use crate::intrinsics::transmute;
78107/// [leak]: ../../std/boxed/struct.Box.html#method.leak
79108/// [into_raw]: ../../std/boxed/struct.Box.html#method.into_raw
80109/// [ub]: ../../reference/behavior-considered-undefined.html
110+ /// [`ManuallyDrop`]: struct.ManuallyDrop.html
81111#[ inline]
82112#[ stable( feature = "rust1" , since = "1.0.0" ) ]
83113pub fn forget < T > ( t : T ) {
0 commit comments