@@ -45,8 +45,9 @@ pub use crate::intrinsics::transmute;
45
45
/// `mem::forget` from safe code does not fundamentally change Rust's safety
46
46
/// guarantees.
47
47
///
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.
50
51
///
51
52
/// Because forgetting a value is allowed, any `unsafe` code you write must
52
53
/// allow for this possibility. You cannot return a value and expect that the
@@ -68,7 +69,35 @@ pub use crate::intrinsics::transmute;
68
69
/// ```
69
70
///
70
71
/// 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.
72
101
///
73
102
/// [drop]: fn.drop.html
74
103
/// [uninit]: fn.uninitialized.html
@@ -78,6 +107,7 @@ pub use crate::intrinsics::transmute;
78
107
/// [leak]: ../../std/boxed/struct.Box.html#method.leak
79
108
/// [into_raw]: ../../std/boxed/struct.Box.html#method.into_raw
80
109
/// [ub]: ../../reference/behavior-considered-undefined.html
110
+ /// [`ManuallyDrop`]: struct.ManuallyDrop.html
81
111
#[ inline]
82
112
#[ stable( feature = "rust1" , since = "1.0.0" ) ]
83
113
pub fn forget < T > ( t : T ) {
0 commit comments