@@ -139,6 +139,124 @@ pub use intrinsics::transmute;
139
139
/// [ub]: ../../reference/behavior-considered-undefined.html
140
140
#[ inline]
141
141
#[ stable( feature = "rust1" , since = "1.0.0" ) ]
142
+ #[ cfg( not( stage0) ) ]
143
+ pub fn forget < T : ?Sized > ( t : T ) {
144
+ unsafe { intrinsics:: forget ( t) }
145
+ }
146
+
147
+ /// Takes ownership and "forgets" about the value **without running its destructor**.
148
+ ///
149
+ /// Any resources the value manages, such as heap memory or a file handle, will linger
150
+ /// forever in an unreachable state. However, it does not guarantee that pointers
151
+ /// to this memory will remain valid.
152
+ ///
153
+ /// * If you want to leak memory, see [`Box::leak`][leak].
154
+ /// * If you want to obtain a raw pointer to the memory, see [`Box::into_raw`][into_raw].
155
+ /// * If you want to dispose of a value properly, running its destructor, see
156
+ /// [`mem::drop`][drop].
157
+ ///
158
+ /// # Safety
159
+ ///
160
+ /// `forget` is not marked as `unsafe`, because Rust's safety guarantees
161
+ /// do not include a guarantee that destructors will always run. For example,
162
+ /// a program can create a reference cycle using [`Rc`][rc], or call
163
+ /// [`process::exit`][exit] to exit without running destructors. Thus, allowing
164
+ /// `mem::forget` from safe code does not fundamentally change Rust's safety
165
+ /// guarantees.
166
+ ///
167
+ /// That said, leaking resources such as memory or I/O objects is usually undesirable,
168
+ /// so `forget` is only recommended for specialized use cases like those shown below.
169
+ ///
170
+ /// Because forgetting a value is allowed, any `unsafe` code you write must
171
+ /// allow for this possibility. You cannot return a value and expect that the
172
+ /// caller will necessarily run the value's destructor.
173
+ ///
174
+ /// [rc]: ../../std/rc/struct.Rc.html
175
+ /// [exit]: ../../std/process/fn.exit.html
176
+ ///
177
+ /// # Examples
178
+ ///
179
+ /// Leak an I/O object, never closing the file:
180
+ ///
181
+ /// ```no_run
182
+ /// use std::mem;
183
+ /// use std::fs::File;
184
+ ///
185
+ /// let file = File::open("foo.txt").unwrap();
186
+ /// mem::forget(file);
187
+ /// ```
188
+ ///
189
+ /// The practical use cases for `forget` are rather specialized and mainly come
190
+ /// up in unsafe or FFI code.
191
+ ///
192
+ /// ## Use case 1
193
+ ///
194
+ /// You have created an uninitialized value using [`mem::uninitialized`][uninit].
195
+ /// You must either initialize or `forget` it on every computation path before
196
+ /// Rust drops it automatically, like at the end of a scope or after a panic.
197
+ /// Running the destructor on an uninitialized value would be [undefined behavior][ub].
198
+ ///
199
+ /// ```
200
+ /// use std::mem;
201
+ /// use std::ptr;
202
+ ///
203
+ /// # let some_condition = false;
204
+ /// unsafe {
205
+ /// let mut uninit_vec: Vec<u32> = mem::uninitialized();
206
+ ///
207
+ /// if some_condition {
208
+ /// // Initialize the variable.
209
+ /// ptr::write(&mut uninit_vec, Vec::new());
210
+ /// } else {
211
+ /// // Forget the uninitialized value so its destructor doesn't run.
212
+ /// mem::forget(uninit_vec);
213
+ /// }
214
+ /// }
215
+ /// ```
216
+ ///
217
+ /// ## Use case 2
218
+ ///
219
+ /// You have duplicated the bytes making up a value, without doing a proper
220
+ /// [`Clone`][clone]. You need the value's destructor to run only once,
221
+ /// because a double `free` is undefined behavior.
222
+ ///
223
+ /// An example is a possible implementation of [`mem::swap`][swap]:
224
+ ///
225
+ /// ```
226
+ /// use std::mem;
227
+ /// use std::ptr;
228
+ ///
229
+ /// # #[allow(dead_code)]
230
+ /// fn swap<T>(x: &mut T, y: &mut T) {
231
+ /// unsafe {
232
+ /// // Give ourselves some scratch space to work with
233
+ /// let mut t: T = mem::uninitialized();
234
+ ///
235
+ /// // Perform the swap, `&mut` pointers never alias
236
+ /// ptr::copy_nonoverlapping(&*x, &mut t, 1);
237
+ /// ptr::copy_nonoverlapping(&*y, x, 1);
238
+ /// ptr::copy_nonoverlapping(&t, y, 1);
239
+ ///
240
+ /// // y and t now point to the same thing, but we need to completely
241
+ /// // forget `t` because we do not want to run the destructor for `T`
242
+ /// // on its value, which is still owned somewhere outside this function.
243
+ /// mem::forget(t);
244
+ /// }
245
+ /// }
246
+ /// ```
247
+ ///
248
+ /// [drop]: fn.drop.html
249
+ /// [uninit]: fn.uninitialized.html
250
+ /// [clone]: ../clone/trait.Clone.html
251
+ /// [swap]: fn.swap.html
252
+ /// [FFI]: ../../book/first-edition/ffi.html
253
+ /// [box]: ../../std/boxed/struct.Box.html
254
+ /// [leak]: ../../std/boxed/struct.Box.html#method.leak
255
+ /// [into_raw]: ../../std/boxed/struct.Box.html#method.into_raw
256
+ /// [ub]: ../../reference/behavior-considered-undefined.html
257
+ #[ inline]
258
+ #[ cfg( stage0) ]
259
+ #[ stable( feature = "rust1" , since = "1.0.0" ) ]
142
260
pub fn forget < T > ( t : T ) {
143
261
ManuallyDrop :: new ( t) ;
144
262
}
@@ -763,7 +881,7 @@ pub fn replace<T>(dest: &mut T, mut src: T) -> T {
763
881
/// [`Copy`]: ../../std/marker/trait.Copy.html
764
882
#[ inline]
765
883
#[ stable( feature = "rust1" , since = "1.0.0" ) ]
766
- pub fn drop < T > ( _x : T ) { }
884
+ pub fn drop < T : ? Sized > ( _x : T ) { }
767
885
768
886
/// Interprets `src` as having type `&U`, and then reads `src` without moving
769
887
/// the contained value.
0 commit comments