Skip to content

Commit 4d2934e

Browse files
author
Stjepan Glavina
committed
Add forget_unsized only
1 parent f211581 commit 4d2934e

File tree

1 file changed

+15
-107
lines changed

1 file changed

+15
-107
lines changed

src/libcore/mem.rs

+15-107
Original file line numberDiff line numberDiff line change
@@ -139,126 +139,34 @@ pub use intrinsics::transmute;
139139
/// [ub]: ../../reference/behavior-considered-undefined.html
140140
#[inline]
141141
#[stable(feature = "rust1", since = "1.0.0")]
142-
#[cfg(not(stage0))]
143-
pub fn forget<T: ?Sized>(t: T) {
144-
unsafe { intrinsics::forget(t) }
142+
pub fn forget<T>(t: T) {
143+
ManuallyDrop::new(t);
145144
}
146145

147146
/// Takes ownership and "forgets" about the value **without running its destructor**.
148147
///
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.
148+
/// This function works exactly the same as [`forget`], except it also accepts unsized values. It
149+
/// will never be stabilized and is only available because we haven't decided to relax the bounds
150+
/// on [`forget`] just yet.
173151
///
174-
/// [rc]: ../../std/rc/struct.Rc.html
175-
/// [exit]: ../../std/process/fn.exit.html
152+
/// [`forget`]: fn.forget.html
176153
///
177154
/// # Examples
178155
///
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-
/// }
215156
/// ```
157+
/// #![feature(forget_unsized)]
216158
///
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-
/// ```
226159
/// 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();
234160
///
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-
/// }
161+
/// let f: Box<FnOnce()> = Box::new(|| ());
162+
/// let f = *f;
163+
/// mem::forget_unsized(f);
246164
/// ```
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
257165
#[inline]
258-
#[cfg(stage0)]
259-
#[stable(feature = "rust1", since = "1.0.0")]
260-
pub fn forget<T>(t: T) {
261-
ManuallyDrop::new(t);
166+
#[cfg(not(stage0))]
167+
#[unstable(feature = "forget_unsized", issue = "0")]
168+
pub fn forget_unsized<T: ?Sized>(t: T) {
169+
unsafe { intrinsics::forget(t) }
262170
}
263171

264172
/// Returns the size of a type in bytes.
@@ -881,7 +789,7 @@ pub fn replace<T>(dest: &mut T, mut src: T) -> T {
881789
/// [`Copy`]: ../../std/marker/trait.Copy.html
882790
#[inline]
883791
#[stable(feature = "rust1", since = "1.0.0")]
884-
pub fn drop<T: ?Sized>(_x: T) { }
792+
pub fn drop<T>(_x: T) { }
885793

886794
/// Interprets `src` as having type `&U`, and then reads `src` without moving
887795
/// the contained value.

0 commit comments

Comments
 (0)