Skip to content
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.

Commit 1529067

Browse files
committedMay 29, 2019
split libcore::mem into multiple files
1 parent 4b9d803 commit 1529067

File tree

4 files changed

+1417
-1406
lines changed

4 files changed

+1417
-1406
lines changed
 

‎src/libcore/mem.rs

Lines changed: 0 additions & 1406 deletions
This file was deleted.

‎src/libcore/mem/manually_drop.rs

Lines changed: 146 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,146 @@
1+
use crate::ptr;
2+
use crate::ops::{Deref, DerefMut};
3+
4+
/// A wrapper to inhibit compiler from automatically calling `T`’s destructor.
5+
///
6+
/// This wrapper is 0-cost.
7+
///
8+
/// `ManuallyDrop<T>` is subject to the same layout optimizations as `T`.
9+
/// As a consequence, it has *no effect* on the assumptions that the compiler makes
10+
/// about all values being initialized at their type. In particular, initializing
11+
/// a `ManuallyDrop<&mut T>` with [`mem::zeroed`] is undefined behavior.
12+
/// If you need to handle uninitialized data, use [`MaybeUninit<T>`] instead.
13+
///
14+
/// # Examples
15+
///
16+
/// This wrapper helps with explicitly documenting the drop order dependencies between fields of
17+
/// the type:
18+
///
19+
/// ```rust
20+
/// use std::mem::ManuallyDrop;
21+
/// struct Peach;
22+
/// struct Banana;
23+
/// struct Melon;
24+
/// struct FruitBox {
25+
/// // Immediately clear there’s something non-trivial going on with these fields.
26+
/// peach: ManuallyDrop<Peach>,
27+
/// melon: Melon, // Field that’s independent of the other two.
28+
/// banana: ManuallyDrop<Banana>,
29+
/// }
30+
///
31+
/// impl Drop for FruitBox {
32+
/// fn drop(&mut self) {
33+
/// unsafe {
34+
/// // Explicit ordering in which field destructors are run specified in the intuitive
35+
/// // location – the destructor of the structure containing the fields.
36+
/// // Moreover, one can now reorder fields within the struct however much they want.
37+
/// ManuallyDrop::drop(&mut self.peach);
38+
/// ManuallyDrop::drop(&mut self.banana);
39+
/// }
40+
/// // After destructor for `FruitBox` runs (this function), the destructor for Melon gets
41+
/// // invoked in the usual manner, as it is not wrapped in `ManuallyDrop`.
42+
/// }
43+
/// }
44+
/// ```
45+
///
46+
/// [`mem::zeroed`]: fn.zeroed.html
47+
/// [`MaybeUninit<T>`]: union.MaybeUninit.html
48+
#[stable(feature = "manually_drop", since = "1.20.0")]
49+
#[lang = "manually_drop"]
50+
#[derive(Copy, Clone, Debug, Default, PartialEq, Eq, PartialOrd, Ord, Hash)]
51+
#[repr(transparent)]
52+
pub struct ManuallyDrop<T: ?Sized> {
53+
value: T,
54+
}
55+
56+
impl<T> ManuallyDrop<T> {
57+
/// Wrap a value to be manually dropped.
58+
///
59+
/// # Examples
60+
///
61+
/// ```rust
62+
/// use std::mem::ManuallyDrop;
63+
/// ManuallyDrop::new(Box::new(()));
64+
/// ```
65+
#[stable(feature = "manually_drop", since = "1.20.0")]
66+
#[inline(always)]
67+
pub const fn new(value: T) -> ManuallyDrop<T> {
68+
ManuallyDrop { value }
69+
}
70+
71+
/// Extracts the value from the `ManuallyDrop` container.
72+
///
73+
/// This allows the value to be dropped again.
74+
///
75+
/// # Examples
76+
///
77+
/// ```rust
78+
/// use std::mem::ManuallyDrop;
79+
/// let x = ManuallyDrop::new(Box::new(()));
80+
/// let _: Box<()> = ManuallyDrop::into_inner(x); // This drops the `Box`.
81+
/// ```
82+
#[stable(feature = "manually_drop", since = "1.20.0")]
83+
#[inline(always)]
84+
pub const fn into_inner(slot: ManuallyDrop<T>) -> T {
85+
slot.value
86+
}
87+
88+
/// Takes the contained value out.
89+
///
90+
/// This method is primarily intended for moving out values in drop.
91+
/// Instead of using [`ManuallyDrop::drop`] to manually drop the value,
92+
/// you can use this method to take the value and use it however desired.
93+
/// `Drop` will be invoked on the returned value following normal end-of-scope rules.
94+
///
95+
/// If you have ownership of the container, you can use [`ManuallyDrop::into_inner`] instead.
96+
///
97+
/// # Safety
98+
///
99+
/// This function semantically moves out the contained value without preventing further usage.
100+
/// It is up to the user of this method to ensure that this container is not used again.
101+
///
102+
/// [`ManuallyDrop::drop`]: #method.drop
103+
/// [`ManuallyDrop::into_inner`]: #method.into_inner
104+
#[must_use = "if you don't need the value, you can use `ManuallyDrop::drop` instead"]
105+
#[unstable(feature = "manually_drop_take", issue = "55422")]
106+
#[inline]
107+
pub unsafe fn take(slot: &mut ManuallyDrop<T>) -> T {
108+
ManuallyDrop::into_inner(ptr::read(slot))
109+
}
110+
}
111+
112+
impl<T: ?Sized> ManuallyDrop<T> {
113+
/// Manually drops the contained value.
114+
///
115+
/// If you have ownership of the value, you can use [`ManuallyDrop::into_inner`] instead.
116+
///
117+
/// # Safety
118+
///
119+
/// This function runs the destructor of the contained value and thus the wrapped value
120+
/// now represents uninitialized data. It is up to the user of this method to ensure the
121+
/// uninitialized data is not actually used.
122+
///
123+
/// [`ManuallyDrop::into_inner`]: #method.into_inner
124+
#[stable(feature = "manually_drop", since = "1.20.0")]
125+
#[inline]
126+
pub unsafe fn drop(slot: &mut ManuallyDrop<T>) {
127+
ptr::drop_in_place(&mut slot.value)
128+
}
129+
}
130+
131+
#[stable(feature = "manually_drop", since = "1.20.0")]
132+
impl<T: ?Sized> Deref for ManuallyDrop<T> {
133+
type Target = T;
134+
#[inline(always)]
135+
fn deref(&self) -> &T {
136+
&self.value
137+
}
138+
}
139+
140+
#[stable(feature = "manually_drop", since = "1.20.0")]
141+
impl<T: ?Sized> DerefMut for ManuallyDrop<T> {
142+
#[inline(always)]
143+
fn deref_mut(&mut self) -> &mut T {
144+
&mut self.value
145+
}
146+
}

‎src/libcore/mem/maybe_uninit.rs

Lines changed: 519 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,519 @@
1+
use crate::intrinsics;
2+
use crate::mem::ManuallyDrop;
3+
4+
/// A wrapper type to construct uninitialized instances of `T`.
5+
///
6+
/// # Initialization invariant
7+
///
8+
/// The compiler, in general, assumes that variables are properly initialized
9+
/// at their respective type. For example, a variable of reference type must
10+
/// be aligned and non-NULL. This is an invariant that must *always* be upheld,
11+
/// even in unsafe code. As a consequence, zero-initializing a variable of reference
12+
/// type causes instantaneous [undefined behavior][ub], no matter whether that reference
13+
/// ever gets used to access memory:
14+
///
15+
/// ```rust,no_run
16+
/// use std::mem::{self, MaybeUninit};
17+
///
18+
/// let x: &i32 = unsafe { mem::zeroed() }; // undefined behavior!
19+
/// // The equivalent code with `MaybeUninit<&i32>`:
20+
/// let x: &i32 = unsafe { MaybeUninit::zeroed().assume_init() }; // undefined behavior!
21+
/// ```
22+
///
23+
/// This is exploited by the compiler for various optimizations, such as eliding
24+
/// run-time checks and optimizing `enum` layout.
25+
///
26+
/// Similarly, entirely uninitialized memory may have any content, while a `bool` must
27+
/// always be `true` or `false`. Hence, creating an uninitialized `bool` is undefined behavior:
28+
///
29+
/// ```rust,no_run
30+
/// use std::mem::{self, MaybeUninit};
31+
///
32+
/// let b: bool = unsafe { mem::uninitialized() }; // undefined behavior!
33+
/// // The equivalent code with `MaybeUninit<bool>`:
34+
/// let b: bool = unsafe { MaybeUninit::uninit().assume_init() }; // undefined behavior!
35+
/// ```
36+
///
37+
/// Moreover, uninitialized memory is special in that the compiler knows that
38+
/// it does not have a fixed value. This makes it undefined behavior to have
39+
/// uninitialized data in a variable even if that variable has an integer type,
40+
/// which otherwise can hold any *fixed* bit pattern:
41+
///
42+
/// ```rust,no_run
43+
/// use std::mem::{self, MaybeUninit};
44+
///
45+
/// let x: i32 = unsafe { mem::uninitialized() }; // undefined behavior!
46+
/// // The equivalent code with `MaybeUninit<i32>`:
47+
/// let x: i32 = unsafe { MaybeUninit::uninit().assume_init() }; // undefined behavior!
48+
/// ```
49+
/// (Notice that the rules around uninitialized integers are not finalized yet, but
50+
/// until they are, it is advisable to avoid them.)
51+
///
52+
/// On top of that, remember that most types have additional invariants beyond merely
53+
/// being considered initialized at the type level. For example, a `1`-initialized [`Vec<T>`]
54+
/// is considered initialized because the only requirement the compiler knows about it
55+
/// is that the data pointer must be non-null. Creating such a `Vec<T>` does not cause
56+
/// *immediate* undefined behavior, but will cause undefined behavior with most
57+
/// safe operations (including dropping it).
58+
///
59+
/// [`Vec<T>`]: ../../std/vec/struct.Vec.html
60+
///
61+
/// # Examples
62+
///
63+
/// `MaybeUninit<T>` serves to enable unsafe code to deal with uninitialized data.
64+
/// It is a signal to the compiler indicating that the data here might *not*
65+
/// be initialized:
66+
///
67+
/// ```rust
68+
/// use std::mem::MaybeUninit;
69+
///
70+
/// // Create an explicitly uninitialized reference. The compiler knows that data inside
71+
/// // a `MaybeUninit<T>` may be invalid, and hence this is not UB:
72+
/// let mut x = MaybeUninit::<&i32>::uninit();
73+
/// // Set it to a valid value.
74+
/// unsafe { x.as_mut_ptr().write(&0); }
75+
/// // Extract the initialized data -- this is only allowed *after* properly
76+
/// // initializing `x`!
77+
/// let x = unsafe { x.assume_init() };
78+
/// ```
79+
///
80+
/// The compiler then knows to not make any incorrect assumptions or optimizations on this code.
81+
///
82+
/// You can think of `MaybeUninit<T>` as being a bit like `Option<T>` but without
83+
/// any of the run-time tracking and without any of the safety checks.
84+
///
85+
/// ## out-pointers
86+
///
87+
/// You can use `MaybeUninit<T>` to implement "out-pointers": instead of returning data
88+
/// from a function, pass it a pointer to some (uninitialized) memory to put the
89+
/// result into. This can be useful when it is important for the caller to control
90+
/// how the memory the result is stored in gets allocated, and you want to avoid
91+
/// unnecessary moves.
92+
///
93+
/// ```
94+
/// use std::mem::MaybeUninit;
95+
///
96+
/// unsafe fn make_vec(out: *mut Vec<i32>) {
97+
/// // `write` does not drop the old contents, which is important.
98+
/// out.write(vec![1, 2, 3]);
99+
/// }
100+
///
101+
/// let mut v = MaybeUninit::uninit();
102+
/// unsafe { make_vec(v.as_mut_ptr()); }
103+
/// // Now we know `v` is initialized! This also makes sure the vector gets
104+
/// // properly dropped.
105+
/// let v = unsafe { v.assume_init() };
106+
/// assert_eq!(&v, &[1, 2, 3]);
107+
/// ```
108+
///
109+
/// ## Initializing an array element-by-element
110+
///
111+
/// `MaybeUninit<T>` can be used to initialize a large array element-by-element:
112+
///
113+
/// ```
114+
/// use std::mem::{self, MaybeUninit};
115+
/// use std::ptr;
116+
///
117+
/// let data = {
118+
/// // Create an uninitialized array of `MaybeUninit`. The `assume_init` is
119+
/// // safe because the type we are claiming to have initialized here is a
120+
/// // bunch of `MaybeUninit`s, which do not require initialization.
121+
/// let mut data: [MaybeUninit<Vec<u32>>; 1000] = unsafe {
122+
/// MaybeUninit::uninit().assume_init()
123+
/// };
124+
///
125+
/// // Dropping a `MaybeUninit` does nothing, so if there is a panic during this loop,
126+
/// // we have a memory leak, but there is no memory safety issue.
127+
/// for elem in &mut data[..] {
128+
/// unsafe { ptr::write(elem.as_mut_ptr(), vec![42]); }
129+
/// }
130+
///
131+
/// // Everything is initialized. Transmute the array to the
132+
/// // initialized type.
133+
/// unsafe { mem::transmute::<_, [Vec<u32>; 1000]>(data) }
134+
/// };
135+
///
136+
/// assert_eq!(&data[0], &[42]);
137+
/// ```
138+
///
139+
/// You can also work with partially initialized arrays, which could
140+
/// be found in low-level datastructures.
141+
///
142+
/// ```
143+
/// use std::mem::MaybeUninit;
144+
/// use std::ptr;
145+
///
146+
/// // Create an uninitialized array of `MaybeUninit`. The `assume_init` is
147+
/// // safe because the type we are claiming to have initialized here is a
148+
/// // bunch of `MaybeUninit`s, which do not require initialization.
149+
/// let mut data: [MaybeUninit<String>; 1000] = unsafe { MaybeUninit::uninit().assume_init() };
150+
/// // Count the number of elements we have assigned.
151+
/// let mut data_len: usize = 0;
152+
///
153+
/// for elem in &mut data[0..500] {
154+
/// unsafe { ptr::write(elem.as_mut_ptr(), String::from("hello")); }
155+
/// data_len += 1;
156+
/// }
157+
///
158+
/// // For each item in the array, drop if we allocated it.
159+
/// for elem in &mut data[0..data_len] {
160+
/// unsafe { ptr::drop_in_place(elem.as_mut_ptr()); }
161+
/// }
162+
/// ```
163+
///
164+
/// ## Initializing a struct field-by-field
165+
///
166+
/// There is currently no supported way to create a raw pointer or reference
167+
/// to a field of a struct inside `MaybeUninit<Struct>`. That means it is not possible
168+
/// to create a struct by calling `MaybeUninit::uninit::<Struct>()` and then writing
169+
/// to its fields.
170+
///
171+
/// [ub]: ../../reference/behavior-considered-undefined.html
172+
///
173+
/// # Layout
174+
///
175+
/// `MaybeUninit<T>` is guaranteed to have the same size and alignment as `T`:
176+
///
177+
/// ```rust
178+
/// use std::mem::{MaybeUninit, size_of, align_of};
179+
/// assert_eq!(size_of::<MaybeUninit<u64>>(), size_of::<u64>());
180+
/// assert_eq!(align_of::<MaybeUninit<u64>>(), align_of::<u64>());
181+
/// ```
182+
///
183+
/// However remember that a type *containing* a `MaybeUninit<T>` is not necessarily the same
184+
/// layout; Rust does not in general guarantee that the fields of a `Foo<T>` have the same order as
185+
/// a `Foo<U>` even if `T` and `U` have the same size and alignment. Furthermore because any bit
186+
/// value is valid for a `MaybeUninit<T>` the compiler can't apply non-zero/niche-filling
187+
/// optimizations, potentially resulting in a larger size:
188+
///
189+
/// ```rust
190+
/// # use std::mem::{MaybeUninit, size_of};
191+
/// assert_eq!(size_of::<Option<bool>>(), 1);
192+
/// assert_eq!(size_of::<Option<MaybeUninit<bool>>>(), 2);
193+
/// ```
194+
#[allow(missing_debug_implementations)]
195+
#[stable(feature = "maybe_uninit", since = "1.36.0")]
196+
#[derive(Copy)]
197+
pub union MaybeUninit<T> {
198+
uninit: (),
199+
value: ManuallyDrop<T>,
200+
}
201+
202+
#[stable(feature = "maybe_uninit", since = "1.36.0")]
203+
impl<T: Copy> Clone for MaybeUninit<T> {
204+
#[inline(always)]
205+
fn clone(&self) -> Self {
206+
// Not calling `T::clone()`, we cannot know if we are initialized enough for that.
207+
*self
208+
}
209+
}
210+
211+
impl<T> MaybeUninit<T> {
212+
/// Creates a new `MaybeUninit<T>` initialized with the given value.
213+
/// It is safe to call [`assume_init`] on the return value of this function.
214+
///
215+
/// Note that dropping a `MaybeUninit<T>` will never call `T`'s drop code.
216+
/// It is your responsibility to make sure `T` gets dropped if it got initialized.
217+
///
218+
/// [`assume_init`]: #method.assume_init
219+
#[stable(feature = "maybe_uninit", since = "1.36.0")]
220+
#[inline(always)]
221+
pub const fn new(val: T) -> MaybeUninit<T> {
222+
MaybeUninit { value: ManuallyDrop::new(val) }
223+
}
224+
225+
/// Creates a new `MaybeUninit<T>` in an uninitialized state.
226+
///
227+
/// Note that dropping a `MaybeUninit<T>` will never call `T`'s drop code.
228+
/// It is your responsibility to make sure `T` gets dropped if it got initialized.
229+
///
230+
/// See the [type-level documentation][type] for some examples.
231+
///
232+
/// [type]: union.MaybeUninit.html
233+
#[stable(feature = "maybe_uninit", since = "1.36.0")]
234+
#[inline(always)]
235+
pub const fn uninit() -> MaybeUninit<T> {
236+
MaybeUninit { uninit: () }
237+
}
238+
239+
/// Creates a new `MaybeUninit<T>` in an uninitialized state, with the memory being
240+
/// filled with `0` bytes. It depends on `T` whether that already makes for
241+
/// proper initialization. For example, `MaybeUninit<usize>::zeroed()` is initialized,
242+
/// but `MaybeUninit<&'static i32>::zeroed()` is not because references must not
243+
/// be null.
244+
///
245+
/// Note that dropping a `MaybeUninit<T>` will never call `T`'s drop code.
246+
/// It is your responsibility to make sure `T` gets dropped if it got initialized.
247+
///
248+
/// # Example
249+
///
250+
/// Correct usage of this function: initializing a struct with zero, where all
251+
/// fields of the struct can hold the bit-pattern 0 as a valid value.
252+
///
253+
/// ```rust
254+
/// use std::mem::MaybeUninit;
255+
///
256+
/// let x = MaybeUninit::<(u8, bool)>::zeroed();
257+
/// let x = unsafe { x.assume_init() };
258+
/// assert_eq!(x, (0, false));
259+
/// ```
260+
///
261+
/// *Incorrect* usage of this function: initializing a struct with zero, where some fields
262+
/// cannot hold 0 as a valid value.
263+
///
264+
/// ```rust,no_run
265+
/// use std::mem::MaybeUninit;
266+
///
267+
/// enum NotZero { One = 1, Two = 2 };
268+
///
269+
/// let x = MaybeUninit::<(u8, NotZero)>::zeroed();
270+
/// let x = unsafe { x.assume_init() };
271+
/// // Inside a pair, we create a `NotZero` that does not have a valid discriminant.
272+
/// // This is undefined behavior.
273+
/// ```
274+
#[stable(feature = "maybe_uninit", since = "1.36.0")]
275+
#[inline]
276+
pub fn zeroed() -> MaybeUninit<T> {
277+
let mut u = MaybeUninit::<T>::uninit();
278+
unsafe {
279+
u.as_mut_ptr().write_bytes(0u8, 1);
280+
}
281+
u
282+
}
283+
284+
/// Sets the value of the `MaybeUninit<T>`. This overwrites any previous value
285+
/// without dropping it, so be careful not to use this twice unless you want to
286+
/// skip running the destructor. For your convenience, this also returns a mutable
287+
/// reference to the (now safely initialized) contents of `self`.
288+
#[unstable(feature = "maybe_uninit_extra", issue = "53491")]
289+
#[inline(always)]
290+
pub fn write(&mut self, val: T) -> &mut T {
291+
unsafe {
292+
self.value = ManuallyDrop::new(val);
293+
self.get_mut()
294+
}
295+
}
296+
297+
/// Gets a pointer to the contained value. Reading from this pointer or turning it
298+
/// into a reference is undefined behavior unless the `MaybeUninit<T>` is initialized.
299+
/// Writing to memory that this pointer (non-transitively) points to is undefined behavior
300+
/// (except inside an `UnsafeCell<T>`).
301+
///
302+
/// # Examples
303+
///
304+
/// Correct usage of this method:
305+
///
306+
/// ```rust
307+
/// use std::mem::MaybeUninit;
308+
///
309+
/// let mut x = MaybeUninit::<Vec<u32>>::uninit();
310+
/// unsafe { x.as_mut_ptr().write(vec![0,1,2]); }
311+
/// // Create a reference into the `MaybeUninit<T>`. This is okay because we initialized it.
312+
/// let x_vec = unsafe { &*x.as_ptr() };
313+
/// assert_eq!(x_vec.len(), 3);
314+
/// ```
315+
///
316+
/// *Incorrect* usage of this method:
317+
///
318+
/// ```rust,no_run
319+
/// use std::mem::MaybeUninit;
320+
///
321+
/// let x = MaybeUninit::<Vec<u32>>::uninit();
322+
/// let x_vec = unsafe { &*x.as_ptr() };
323+
/// // We have created a reference to an uninitialized vector! This is undefined behavior.
324+
/// ```
325+
///
326+
/// (Notice that the rules around references to uninitialized data are not finalized yet, but
327+
/// until they are, it is advisable to avoid them.)
328+
#[stable(feature = "maybe_uninit", since = "1.36.0")]
329+
#[inline(always)]
330+
pub fn as_ptr(&self) -> *const T {
331+
unsafe { &*self.value as *const T }
332+
}
333+
334+
/// Gets a mutable pointer to the contained value. Reading from this pointer or turning it
335+
/// into a reference is undefined behavior unless the `MaybeUninit<T>` is initialized.
336+
///
337+
/// # Examples
338+
///
339+
/// Correct usage of this method:
340+
///
341+
/// ```rust
342+
/// use std::mem::MaybeUninit;
343+
///
344+
/// let mut x = MaybeUninit::<Vec<u32>>::uninit();
345+
/// unsafe { x.as_mut_ptr().write(vec![0,1,2]); }
346+
/// // Create a reference into the `MaybeUninit<Vec<u32>>`.
347+
/// // This is okay because we initialized it.
348+
/// let x_vec = unsafe { &mut *x.as_mut_ptr() };
349+
/// x_vec.push(3);
350+
/// assert_eq!(x_vec.len(), 4);
351+
/// ```
352+
///
353+
/// *Incorrect* usage of this method:
354+
///
355+
/// ```rust,no_run
356+
/// use std::mem::MaybeUninit;
357+
///
358+
/// let mut x = MaybeUninit::<Vec<u32>>::uninit();
359+
/// let x_vec = unsafe { &mut *x.as_mut_ptr() };
360+
/// // We have created a reference to an uninitialized vector! This is undefined behavior.
361+
/// ```
362+
///
363+
/// (Notice that the rules around references to uninitialized data are not finalized yet, but
364+
/// until they are, it is advisable to avoid them.)
365+
#[stable(feature = "maybe_uninit", since = "1.36.0")]
366+
#[inline(always)]
367+
pub fn as_mut_ptr(&mut self) -> *mut T {
368+
unsafe { &mut *self.value as *mut T }
369+
}
370+
371+
/// Extracts the value from the `MaybeUninit<T>` container. This is a great way
372+
/// to ensure that the data will get dropped, because the resulting `T` is
373+
/// subject to the usual drop handling.
374+
///
375+
/// # Safety
376+
///
377+
/// It is up to the caller to guarantee that the `MaybeUninit<T>` really is in an initialized
378+
/// state. Calling this when the content is not yet fully initialized causes immediate undefined
379+
/// behavior. The [type-level documentation][inv] contains more information about
380+
/// this initialization invariant.
381+
///
382+
/// [inv]: #initialization-invariant
383+
///
384+
/// # Examples
385+
///
386+
/// Correct usage of this method:
387+
///
388+
/// ```rust
389+
/// use std::mem::MaybeUninit;
390+
///
391+
/// let mut x = MaybeUninit::<bool>::uninit();
392+
/// unsafe { x.as_mut_ptr().write(true); }
393+
/// let x_init = unsafe { x.assume_init() };
394+
/// assert_eq!(x_init, true);
395+
/// ```
396+
///
397+
/// *Incorrect* usage of this method:
398+
///
399+
/// ```rust,no_run
400+
/// use std::mem::MaybeUninit;
401+
///
402+
/// let x = MaybeUninit::<Vec<u32>>::uninit();
403+
/// let x_init = unsafe { x.assume_init() };
404+
/// // `x` had not been initialized yet, so this last line caused undefined behavior.
405+
/// ```
406+
#[stable(feature = "maybe_uninit", since = "1.36.0")]
407+
#[inline(always)]
408+
pub unsafe fn assume_init(self) -> T {
409+
intrinsics::panic_if_uninhabited::<T>();
410+
ManuallyDrop::into_inner(self.value)
411+
}
412+
413+
/// Reads the value from the `MaybeUninit<T>` container. The resulting `T` is subject
414+
/// to the usual drop handling.
415+
///
416+
/// Whenever possible, it is preferrable to use [`assume_init`] instead, which
417+
/// prevents duplicating the content of the `MaybeUninit<T>`.
418+
///
419+
/// # Safety
420+
///
421+
/// It is up to the caller to guarantee that the `MaybeUninit<T>` really is in an initialized
422+
/// state. Calling this when the content is not yet fully initialized causes undefined
423+
/// behavior. The [type-level documentation][inv] contains more information about
424+
/// this initialization invariant.
425+
///
426+
/// Moreover, this leaves a copy of the same data behind in the `MaybeUninit<T>`. When using
427+
/// multiple copies of the data (by calling `read` multiple times, or first
428+
/// calling `read` and then [`assume_init`]), it is your responsibility
429+
/// to ensure that that data may indeed be duplicated.
430+
///
431+
/// [inv]: #initialization-invariant
432+
/// [`assume_init`]: #method.assume_init
433+
///
434+
/// # Examples
435+
///
436+
/// Correct usage of this method:
437+
///
438+
/// ```rust
439+
/// #![feature(maybe_uninit_extra)]
440+
/// use std::mem::MaybeUninit;
441+
///
442+
/// let mut x = MaybeUninit::<u32>::uninit();
443+
/// x.write(13);
444+
/// let x1 = unsafe { x.read() };
445+
/// // `u32` is `Copy`, so we may read multiple times.
446+
/// let x2 = unsafe { x.read() };
447+
/// assert_eq!(x1, x2);
448+
///
449+
/// let mut x = MaybeUninit::<Option<Vec<u32>>>::uninit();
450+
/// x.write(None);
451+
/// let x1 = unsafe { x.read() };
452+
/// // Duplicating a `None` value is okay, so we may read multiple times.
453+
/// let x2 = unsafe { x.read() };
454+
/// assert_eq!(x1, x2);
455+
/// ```
456+
///
457+
/// *Incorrect* usage of this method:
458+
///
459+
/// ```rust,no_run
460+
/// #![feature(maybe_uninit_extra)]
461+
/// use std::mem::MaybeUninit;
462+
///
463+
/// let mut x = MaybeUninit::<Option<Vec<u32>>>::uninit();
464+
/// x.write(Some(vec![0,1,2]));
465+
/// let x1 = unsafe { x.read() };
466+
/// let x2 = unsafe { x.read() };
467+
/// // We now created two copies of the same vector, leading to a double-free when
468+
/// // they both get dropped!
469+
/// ```
470+
#[unstable(feature = "maybe_uninit_extra", issue = "53491")]
471+
#[inline(always)]
472+
pub unsafe fn read(&self) -> T {
473+
intrinsics::panic_if_uninhabited::<T>();
474+
self.as_ptr().read()
475+
}
476+
477+
/// Gets a reference to the contained value.
478+
///
479+
/// # Safety
480+
///
481+
/// It is up to the caller to guarantee that the `MaybeUninit<T>` really is in an initialized
482+
/// state. Calling this when the content is not yet fully initialized causes undefined
483+
/// behavior.
484+
#[unstable(feature = "maybe_uninit_ref", issue = "53491")]
485+
#[inline(always)]
486+
pub unsafe fn get_ref(&self) -> &T {
487+
&*self.value
488+
}
489+
490+
/// Gets a mutable reference to the contained value.
491+
///
492+
/// # Safety
493+
///
494+
/// It is up to the caller to guarantee that the `MaybeUninit<T>` really is in an initialized
495+
/// state. Calling this when the content is not yet fully initialized causes undefined
496+
/// behavior.
497+
// FIXME(#53491): We currently rely on the above being incorrect, i.e., we have references
498+
// to uninitialized data (e.g., in `libcore/fmt/float.rs`). We should make
499+
// a final decision about the rules before stabilization.
500+
#[unstable(feature = "maybe_uninit_ref", issue = "53491")]
501+
#[inline(always)]
502+
pub unsafe fn get_mut(&mut self) -> &mut T {
503+
&mut *self.value
504+
}
505+
506+
/// Gets a pointer to the first element of the array.
507+
#[unstable(feature = "maybe_uninit_slice", issue = "53491")]
508+
#[inline(always)]
509+
pub fn first_ptr(this: &[MaybeUninit<T>]) -> *const T {
510+
this as *const [MaybeUninit<T>] as *const T
511+
}
512+
513+
/// Gets a mutable pointer to the first element of the array.
514+
#[unstable(feature = "maybe_uninit_slice", issue = "53491")]
515+
#[inline(always)]
516+
pub fn first_ptr_mut(this: &mut [MaybeUninit<T>]) -> *mut T {
517+
this as *mut [MaybeUninit<T>] as *mut T
518+
}
519+
}

‎src/libcore/mem/mod.rs

Lines changed: 752 additions & 0 deletions
Large diffs are not rendered by default.

0 commit comments

Comments
 (0)
Please sign in to comment.