[−][src]Union nom::lib::std::mem::MaybeUninit
maybe_uninit
)A wrapper to construct uninitialized instances of T
.
The compiler, in general, assumes that variables are properly initialized at their respective type. For example, a variable of reference type must be aligned and non-NULL. This is an invariant that must always be upheld, even in unsafe code. As a consequence, zero-initializing a variable of reference type causes instantaneous undefined behavior, no matter whether that reference ever gets used to access memory:
#![feature(maybe_uninit)] use std::mem::{self, MaybeUninit}; let x: &i32 = unsafe { mem::zeroed() }; // undefined behavior! // The equivalent code with `MaybeUninit<&i32>`: let x: &i32 = unsafe { MaybeUninit::zeroed().assume_init() }; // undefined behavior!
This is exploited by the compiler for various optimizations, such as eliding
run-time checks and optimizing enum
layout.
Similarly, entirely uninitialized memory may have any content, while a bool
must
always be true
or false
. Hence, creating an uninitialized bool
is undefined behavior:
#![feature(maybe_uninit)] use std::mem::{self, MaybeUninit}; let b: bool = unsafe { mem::uninitialized() }; // undefined behavior! // The equivalent code with `MaybeUninit<bool>`: let b: bool = unsafe { MaybeUninit::uninit().assume_init() }; // undefined behavior!
Moreover, uninitialized memory is special in that the compiler knows that it does not have a fixed value. This makes it undefined behavior to have uninitialized data in a variable even if that variable has an integer type, which otherwise can hold any bit pattern:
#![feature(maybe_uninit)] use std::mem::{self, MaybeUninit}; let x: i32 = unsafe { mem::uninitialized() }; // undefined behavior! // The equivalent code with `MaybeUninit<i32>`: let x: i32 = unsafe { MaybeUninit::uninit().assume_init() }; // undefined behavior!
(Notice that the rules around uninitialized integers are not finalized yet, but until they are, it is advisable to avoid them.)
MaybeUninit<T>
serves to enable unsafe code to deal with uninitialized data.
It is a signal to the compiler indicating that the data here might not
be initialized:
#![feature(maybe_uninit)] use std::mem::MaybeUninit; // Create an explicitly uninitialized reference. The compiler knows that data inside // a `MaybeUninit<T>` may be invalid, and hence this is not UB: let mut x = MaybeUninit::<&i32>::uninit(); // Set it to a valid value. x.write(&0); // Extract the initialized data -- this is only allowed *after* properly // initializing `x`! let x = unsafe { x.assume_init() };
The compiler then knows to not make any incorrect assumptions or optimizations on this code.
Methods
impl<T> MaybeUninit<T>
[src]
pub const fn new(val: T) -> MaybeUninit<T>
[src]
maybe_uninit
)Creates a new MaybeUninit<T>
initialized with the given value.
Note that dropping a MaybeUninit<T>
will never call T
's drop code.
It is your responsibility to make sure T
gets dropped if it got initialized.
pub const fn uninit() -> MaybeUninit<T>
[src]
maybe_uninit
)Creates a new MaybeUninit<T>
in an uninitialized state.
Note that dropping a MaybeUninit<T>
will never call T
's drop code.
It is your responsibility to make sure T
gets dropped if it got initialized.
pub fn zeroed() -> MaybeUninit<T>
[src]
maybe_uninit
)Creates a new MaybeUninit<T>
in an uninitialized state, with the memory being
filled with 0
bytes. It depends on T
whether that already makes for
proper initialization. For example, MaybeUninit<usize>::zeroed()
is initialized,
but MaybeUninit<&'static i32>::zeroed()
is not because references must not
be null.
Note that dropping a MaybeUninit<T>
will never call T
's drop code.
It is your responsibility to make sure T
gets dropped if it got initialized.
Example
Correct usage of this function: initializing a struct with zero, where all fields of the struct can hold the bit-pattern 0 as a valid value.
#![feature(maybe_uninit)] use std::mem::MaybeUninit; let x = MaybeUninit::<(u8, bool)>::zeroed(); let x = unsafe { x.assume_init() }; assert_eq!(x, (0, false));
Incorrect usage of this function: initializing a struct with zero, where some fields cannot hold 0 as a valid value.
#![feature(maybe_uninit)] use std::mem::MaybeUninit; enum NotZero { One = 1, Two = 2 }; let x = MaybeUninit::<(u8, NotZero)>::zeroed(); let x = unsafe { x.assume_init() }; // Inside a pair, we create a `NotZero` that does not have a valid discriminant. // This is undefined behavior.
ⓘImportant traits for &'_ mut Ipub fn write(&mut self, val: T) -> &mut T
[src]
maybe_uninit
)Sets the value of the MaybeUninit<T>
. This overwrites any previous value
without dropping it, so be careful not to use this twice unless you want to
skip running the destructor. For your convenience, this also returns a mutable
reference to the (now safely initialized) contents of self
.
pub fn as_ptr(&self) -> *const T
[src]
maybe_uninit
)Gets a pointer to the contained value. Reading from this pointer or turning it
into a reference is undefined behavior unless the MaybeUninit<T>
is initialized.
Examples
Correct usage of this method:
#![feature(maybe_uninit)] use std::mem::MaybeUninit; let mut x = MaybeUninit::<Vec<u32>>::uninit(); unsafe { x.as_mut_ptr().write(vec![0,1,2]); } // Create a reference into the `MaybeUninit<T>`. This is okay because we initialized it. let x_vec = unsafe { &*x.as_ptr() }; assert_eq!(x_vec.len(), 3);
Incorrect usage of this method:
#![feature(maybe_uninit)] use std::mem::MaybeUninit; let x = MaybeUninit::<Vec<u32>>::uninit(); let x_vec = unsafe { &*x.as_ptr() }; // We have created a reference to an uninitialized vector! This is undefined behavior.
(Notice that the rules around references to uninitialized data are not finalized yet, but until they are, it is advisable to avoid them.)
pub fn as_mut_ptr(&mut self) -> *mut T
[src]
maybe_uninit
)Gets a mutable pointer to the contained value. Reading from this pointer or turning it
into a reference is undefined behavior unless the MaybeUninit<T>
is initialized.
Examples
Correct usage of this method:
#![feature(maybe_uninit)] use std::mem::MaybeUninit; let mut x = MaybeUninit::<Vec<u32>>::uninit(); unsafe { x.as_mut_ptr().write(vec![0,1,2]); } // Create a reference into the `MaybeUninit<Vec<u32>>`. // This is okay because we initialized it. let x_vec = unsafe { &mut *x.as_mut_ptr() }; x_vec.push(3); assert_eq!(x_vec.len(), 4);
Incorrect usage of this method:
#![feature(maybe_uninit)] use std::mem::MaybeUninit; let mut x = MaybeUninit::<Vec<u32>>::uninit(); let x_vec = unsafe { &mut *x.as_mut_ptr() }; // We have created a reference to an uninitialized vector! This is undefined behavior.
(Notice that the rules around references to uninitialized data are not finalized yet, but until they are, it is advisable to avoid them.)
pub unsafe fn assume_init(self) -> T
[src]
maybe_uninit
)Extracts the value from the MaybeUninit<T>
container. This is a great way
to ensure that the data will get dropped, because the resulting T
is
subject to the usual drop handling.
Safety
It is up to the caller to guarantee that the MaybeUninit<T>
really is in an initialized
state. Calling this when the content is not yet fully initialized causes undefined
behavior.
Examples
Correct usage of this method:
#![feature(maybe_uninit)] use std::mem::MaybeUninit; let mut x = MaybeUninit::<bool>::uninit(); unsafe { x.as_mut_ptr().write(true); } let x_init = unsafe { x.assume_init() }; assert_eq!(x_init, true);
Incorrect usage of this method:
#![feature(maybe_uninit)] use std::mem::MaybeUninit; let x = MaybeUninit::<Vec<u32>>::uninit(); let x_init = unsafe { x.assume_init() }; // `x` had not been initialized yet, so this last line caused undefined behavior.
pub unsafe fn read(&self) -> T
[src]
maybe_uninit
)Reads the value from the MaybeUninit<T>
container. The resulting T
is subject
to the usual drop handling.
Whenever possible, it is preferrable to use assume_init
instead, which
prevents duplicating the content of the MaybeUninit<T>
.
Safety
It is up to the caller to guarantee that the MaybeUninit<T>
really is in an initialized
state. Calling this when the content is not yet fully initialized causes undefined
behavior.
Moreover, this leaves a copy of the same data behind in the MaybeUninit<T>
. When using
multiple copies of the data (by calling read
multiple times, or first
calling read
and then assume_init
), it is your responsibility
to ensure that that data may indeed be duplicated.
Examples
Correct usage of this method:
#![feature(maybe_uninit)] use std::mem::MaybeUninit; let mut x = MaybeUninit::<u32>::uninit(); x.write(13); let x1 = unsafe { x.read() }; // `u32` is `Copy`, so we may read multiple times. let x2 = unsafe { x.read() }; assert_eq!(x1, x2); let mut x = MaybeUninit::<Option<Vec<u32>>>::uninit(); x.write(None); let x1 = unsafe { x.read() }; // Duplicating a `None` value is okay, so we may read multiple times. let x2 = unsafe { x.read() }; assert_eq!(x1, x2);
Incorrect usage of this method:
#![feature(maybe_uninit)] use std::mem::MaybeUninit; let mut x = MaybeUninit::<Option<Vec<u32>>>::uninit(); x.write(Some(vec![0,1,2])); let x1 = unsafe { x.read() }; let x2 = unsafe { x.read() }; // We now created two copies of the same vector, leading to a double-free when // they both get dropped!
ⓘImportant traits for &'_ mut Ipub unsafe fn get_ref(&self) -> &T
[src]
maybe_uninit_ref
)Gets a reference to the contained value.
Safety
It is up to the caller to guarantee that the MaybeUninit<T>
really is in an initialized
state. Calling this when the content is not yet fully initialized causes undefined
behavior.
ⓘImportant traits for &'_ mut Ipub unsafe fn get_mut(&mut self) -> &mut T
[src]
maybe_uninit_ref
)Gets a mutable reference to the contained value.
Safety
It is up to the caller to guarantee that the MaybeUninit<T>
really is in an initialized
state. Calling this when the content is not yet fully initialized causes undefined
behavior.
pub fn first_ptr(this: &[MaybeUninit<T>]) -> *const T
[src]
maybe_uninit_slice
)Gets a pointer to the first element of the array.
pub fn first_ptr_mut(this: &mut [MaybeUninit<T>]) -> *mut T
[src]
maybe_uninit_slice
)Gets a mutable pointer to the first element of the array.
Trait Implementations
impl<T> Copy for MaybeUninit<T> where
T: Copy,
[src]
T: Copy,
impl<T> Clone for MaybeUninit<T> where
T: Copy,
[src]
T: Copy,
fn clone(&self) -> MaybeUninit<T>
[src]
fn clone_from(&mut self, source: &Self)
1.0.0[src]
Performs copy-assignment from source
. Read more
Auto Trait Implementations
impl<T> Send for MaybeUninit<T> where
T: Send,
T: Send,
impl<T> Sync for MaybeUninit<T> where
T: Sync,
T: Sync,
Blanket Implementations
impl<T, U> Into for T where
U: From<T>,
[src]
U: From<T>,
impl<T> ToOwned for T where
T: Clone,
[src]
T: Clone,
type Owned = T
The resulting type after obtaining ownership.
fn to_owned(&self) -> T
[src]
fn clone_into(&self, target: &mut T)
[src]
impl<T> From for T
[src]
impl<T, U> TryFrom for T where
U: Into<T>,
[src]
U: Into<T>,
type Error = Infallible
The type returned in the event of a conversion error.
fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>
[src]
impl<T> Borrow for T where
T: ?Sized,
[src]
T: ?Sized,
impl<T> Any for T where
T: 'static + ?Sized,
[src]
T: 'static + ?Sized,
impl<T> BorrowMut for T where
T: ?Sized,
[src]
T: ?Sized,
ⓘImportant traits for &'_ mut Ifn borrow_mut(&mut self) -> &mut T
[src]
impl<T, U> TryInto for T where
U: TryFrom<T>,
[src]
U: TryFrom<T>,