pub struct Frame<T: Pointee + ?Sized, A: Allocator = Global>where
T::Metadata: Metadata<T>,{ /* private fields */ }
Expand description
A box that may be uninitialized.
Frames have the same memory layouts as Boxes
.
Implementations
sourceimpl<T: Pointee + ?Sized, A: Allocator> Frame<T, A>where
T::Metadata: Metadata<T>,
impl<T: Pointee + ?Sized, A: Allocator> Frame<T, A>where
T::Metadata: Metadata<T>,
sourcepub fn allocator(f: &Self) -> &A
pub fn allocator(f: &Self) -> &A
Returns a reference to the underlying allocator.
Note: this is an associated function, which means that you have to call
it as Frame::allocator(&f)
instead of f.allocator()
. This is so that
there is no conflict with a method on the inner type.
sourcepub fn as_mut_ptr(&mut self) -> *mut T
pub fn as_mut_ptr(&mut self) -> *mut T
Returns a mutable pointer to the underlying memory.
sourcepub unsafe fn assume_init(self) -> Box<T, A>
pub unsafe fn assume_init(self) -> Box<T, A>
Converts to Box<T, A>
.
This does not move the value pointed to by the frame.
Safety
The contents of the frame must be initialized. Calling this when the content is not yet initialized causes immediate undefined behavior.
Additionally, most types have additional invariants beyond merely being
considered initialized at the type level. For example, a 1
-initialized
Vec<T>
is considered initialized (under the current implementation;
this does not constitute a stable guarantee) because the only
requirement the compiler knows about it is that the data pointer must be
non-null. Creating such a Vec<T>
does not cause immediate undefined
behavior, but will cause undefined behavior with most safe operations
(including dropping it).
sourcepub unsafe fn from_raw_in(raw: *mut T, alloc: A) -> Self
pub unsafe fn from_raw_in(raw: *mut T, alloc: A) -> Self
Constructs a frame from a raw pointer in the given allocator.
After calling this function, the raw pointer is owned by the resulting
Frame
. Specifically, the Frame
destructor will free the allocated
memory. For this to be safe, the memory must have been allocated in
accordance with the memory layout used by Frame
.
Safety
raw
must be non-null and allocated by alloc
according to the memory
layout used by Frame
.
sourcepub fn into_raw_with_allocator(f: Self) -> (*mut T, A)
pub fn into_raw_with_allocator(f: Self) -> (*mut T, A)
Consumes the Frame
, returning a raw pointer and the allocator.
The pointer will be properly aligned and non-null.
After calling this function, the caller is responsible for the memory
previously managed by the Frame
. In particular, the caller should
properly release the memory, taking into account the memory layout used
by Frame
. The easiest way to do this is to convert the raw pointer
back into a Frame
with the Frame::from_raw_in
function, allowing
the Frame
destructor to perform the cleanup.
Note: this is an associated function, which means that you have to call
it as Frame::into_raw_with_allocator(f)
instead of
f.into_raw_with_allocator()
. This is so that there is no conflict with
a method on the inner type.
sourcepub unsafe fn new_unsized_in(metadata: T::Metadata, alloc: A) -> Self
pub unsafe fn new_unsized_in(metadata: T::Metadata, alloc: A) -> Self
Allocates memory for an unsized type with the given metadata in the given allocator.
This doesn’t actually allocate if the metadata provides a layout with zero size.
Safety
metadata
must be valid for a pointer to T
.
sourceimpl<T, A: Allocator> Frame<T, A>
impl<T, A: Allocator> Frame<T, A>
sourceimpl<T: Pointee + ?Sized> Frame<T, Global>where
T::Metadata: Metadata<T>,
impl<T: Pointee + ?Sized> Frame<T, Global>where
T::Metadata: Metadata<T>,
sourcepub unsafe fn from_raw(raw: *mut T) -> Self
pub unsafe fn from_raw(raw: *mut T) -> Self
Constructs a frame from a raw pointer.
After calling this function, the raw pointer is owned by the resulting
Frame
. Specifically, the Frame
destructor will free the allocated
memory. For this to be safe, the memory must have been allocated in
accordance with the memory layout used by Frame
.
Safety
This function is unsafe because improper use may lead to memory problems. For example, a double-free may occur if the function is called twice on the same raw pointer.
The safety conditions are described in the memory layout section.
sourcepub fn into_raw(f: Self) -> *mut T
pub fn into_raw(f: Self) -> *mut T
Consumes the Frame
, returning a raw pointer.
The pointer will be properly aligned and non-null.
After calling this function, the caller is responsible for the memory
previously managed by the Frame
. In particular, the caller should
properly release the memory, taking into account the memory layout used
by Frame
. The easiest way to do this is to convert the raw pointer
back into a Frame
with the Frame::from_raw
function, allowing the
Frame
destructor to perform the cleanup.
Note: this is an associated function, which means that you have to call
it as Frame::into_raw(f)
instead of f.into_raw()
. This is so that
there is no conflict with a method on the inner type.
sourcepub unsafe fn new_unsized(metadata: T::Metadata) -> Self
pub unsafe fn new_unsized(metadata: T::Metadata) -> Self
Allocates memory for an object with the given metadata on the heap.
This doesn’t actually allocate if the metadata provides a layout with zero size.
Safety
metadata
must be valid for a pointer to T
.
Methods from Deref<Target = MaybeUninit<T>>
1.55.0 · sourcepub fn write(&mut self, val: T) -> &mut T
pub fn write(&mut self, val: T) -> &mut T
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
.
As the content is stored inside a MaybeUninit
, the destructor is not
run for the inner data if the MaybeUninit leaves scope without a call to
assume_init
, assume_init_drop
, or similar. Code that receives
the mutable reference returned by this function needs to keep this in
mind. The safety model of Rust regards leaks as safe, but they are
usually still undesirable. This being said, the mutable reference
behaves like any other mutable reference would, so assigning a new value
to it will drop the old content.
Examples
Correct usage of this method:
use std::mem::MaybeUninit;
let mut x = MaybeUninit::<Vec<u8>>::uninit();
{
let hello = x.write((&b"Hello, world!").to_vec());
// Setting hello does not leak prior allocations, but drops them
*hello = (&b"Hello").to_vec();
hello[0] = 'h' as u8;
}
// x is initialized now:
let s = unsafe { x.assume_init() };
assert_eq!(b"hello", s.as_slice());
This usage of the method causes a leak:
use std::mem::MaybeUninit;
let mut x = MaybeUninit::<String>::uninit();
x.write("Hello".to_string());
// This leaks the contained string:
x.write("hello".to_string());
// x is initialized now:
let s = unsafe { x.assume_init() };
This method can be used to avoid unsafe in some cases. The example below
shows a part of an implementation of a fixed sized arena that lends out
pinned references.
With write
, we can avoid the need to write through a raw pointer:
use core::pin::Pin;
use core::mem::MaybeUninit;
struct PinArena<T> {
memory: Box<[MaybeUninit<T>]>,
len: usize,
}
impl <T> PinArena<T> {
pub fn capacity(&self) -> usize {
self.memory.len()
}
pub fn push(&mut self, val: T) -> Pin<&mut T> {
if self.len >= self.capacity() {
panic!("Attempted to push to a full pin arena!");
}
let ref_ = self.memory[self.len].write(val);
self.len += 1;
unsafe { Pin::new_unchecked(ref_) }
}
}
1.36.0 · sourcepub fn as_ptr(&self) -> *const T
pub fn as_ptr(&self) -> *const T
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.
Writing to memory that this pointer (non-transitively) points to is undefined behavior
(except inside an UnsafeCell<T>
).
Examples
Correct usage of this method:
use std::mem::MaybeUninit;
let mut x = MaybeUninit::<Vec<u32>>::uninit();
x.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:
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.)
1.36.0 · sourcepub fn as_mut_ptr(&mut self) -> *mut T
pub fn as_mut_ptr(&mut self) -> *mut T
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:
use std::mem::MaybeUninit;
let mut x = MaybeUninit::<Vec<u32>>::uninit();
x.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:
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.)
1.60.0 · sourcepub unsafe fn assume_init_read(&self) -> T
pub unsafe fn assume_init_read(&self) -> T
Reads the value from the MaybeUninit<T>
container. The resulting T
is subject
to the usual drop handling.
Whenever possible, it is preferable 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. The type-level documentation contains more information about
this initialization invariant.
Moreover, similar to the ptr::read
function, this function creates a
bitwise copy of the contents, regardless whether the contained type
implements the Copy
trait or not. When using multiple copies of the
data (by calling assume_init_read
multiple times, or first calling
assume_init_read
and then assume_init
), it is your responsibility
to ensure that data may indeed be duplicated.
Examples
Correct usage of this method:
use std::mem::MaybeUninit;
let mut x = MaybeUninit::<u32>::uninit();
x.write(13);
let x1 = unsafe { x.assume_init_read() };
// `u32` is `Copy`, so we may read multiple times.
let x2 = unsafe { x.assume_init_read() };
assert_eq!(x1, x2);
let mut x = MaybeUninit::<Option<Vec<u32>>>::uninit();
x.write(None);
let x1 = unsafe { x.assume_init_read() };
// Duplicating a `None` value is okay, so we may read multiple times.
let x2 = unsafe { x.assume_init_read() };
assert_eq!(x1, x2);
Incorrect usage of this method:
use std::mem::MaybeUninit;
let mut x = MaybeUninit::<Option<Vec<u32>>>::uninit();
x.write(Some(vec![0, 1, 2]));
let x1 = unsafe { x.assume_init_read() };
let x2 = unsafe { x.assume_init_read() };
// We now created two copies of the same vector, leading to a double-free ⚠️ when
// they both get dropped!
1.60.0 · sourcepub unsafe fn assume_init_drop(&mut self)
pub unsafe fn assume_init_drop(&mut self)
Drops the contained value in place.
If you have ownership of the MaybeUninit
, you can also use
assume_init
as an alternative.
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.
On top of that, all additional invariants of the type T
must be
satisfied, as the Drop
implementation of T
(or its members) may
rely on this. For example, setting a Vec<T>
to an invalid but
non-null address makes it initialized (under the current implementation;
this does not constitute a stable guarantee), because the only
requirement the compiler knows about it is that the data pointer must be
non-null. Dropping such a Vec<T>
however will cause undefined
behaviour.
1.55.0 · sourcepub unsafe fn assume_init_ref(&self) -> &T
pub unsafe fn assume_init_ref(&self) -> &T
Gets a shared reference to the contained value.
This can be useful when we want to access a MaybeUninit
that has been
initialized but don’t have ownership of the MaybeUninit
(preventing the use
of .assume_init()
).
Safety
Calling this when the content is not yet fully initialized causes undefined
behavior: it is up to the caller to guarantee that the MaybeUninit<T>
really
is in an initialized state.
Examples
Correct usage of this method:
use std::mem::MaybeUninit;
let mut x = MaybeUninit::<Vec<u32>>::uninit();
// Initialize `x`:
x.write(vec![1, 2, 3]);
// Now that our `MaybeUninit<_>` is known to be initialized, it is okay to
// create a shared reference to it:
let x: &Vec<u32> = unsafe {
// SAFETY: `x` has been initialized.
x.assume_init_ref()
};
assert_eq!(x, &vec![1, 2, 3]);
Incorrect usages of this method:
use std::mem::MaybeUninit;
let x = MaybeUninit::<Vec<u32>>::uninit();
let x_vec: &Vec<u32> = unsafe { x.assume_init_ref() };
// We have created a reference to an uninitialized vector! This is undefined behavior. ⚠️
use std::{cell::Cell, mem::MaybeUninit};
let b = MaybeUninit::<Cell<bool>>::uninit();
// Initialize the `MaybeUninit` using `Cell::set`:
unsafe {
b.assume_init_ref().set(true);
// ^^^^^^^^^^^^^^^
// Reference to an uninitialized `Cell<bool>`: UB!
}
1.55.0 · sourcepub unsafe fn assume_init_mut(&mut self) -> &mut T
pub unsafe fn assume_init_mut(&mut self) -> &mut T
Gets a mutable (unique) reference to the contained value.
This can be useful when we want to access a MaybeUninit
that has been
initialized but don’t have ownership of the MaybeUninit
(preventing the use
of .assume_init()
).
Safety
Calling this when the content is not yet fully initialized causes undefined
behavior: it is up to the caller to guarantee that the MaybeUninit<T>
really
is in an initialized state. For instance, .assume_init_mut()
cannot be used to
initialize a MaybeUninit
.
Examples
Correct usage of this method:
use std::mem::MaybeUninit;
extern "C" {
/// Initializes *all* the bytes of the input buffer.
fn initialize_buffer(buf: *mut [u8; 1024]);
}
let mut buf = MaybeUninit::<[u8; 1024]>::uninit();
// Initialize `buf`:
unsafe { initialize_buffer(buf.as_mut_ptr()); }
// Now we know that `buf` has been initialized, so we could `.assume_init()` it.
// However, using `.assume_init()` may trigger a `memcpy` of the 1024 bytes.
// To assert our buffer has been initialized without copying it, we upgrade
// the `&mut MaybeUninit<[u8; 1024]>` to a `&mut [u8; 1024]`:
let buf: &mut [u8; 1024] = unsafe {
// SAFETY: `buf` has been initialized.
buf.assume_init_mut()
};
// Now we can use `buf` as a normal slice:
buf.sort_unstable();
assert!(
buf.windows(2).all(|pair| pair[0] <= pair[1]),
"buffer is sorted",
);
Incorrect usages of this method:
You cannot use .assume_init_mut()
to initialize a value:
use std::mem::MaybeUninit;
let mut b = MaybeUninit::<bool>::uninit();
unsafe {
*b.assume_init_mut() = true;
// We have created a (mutable) reference to an uninitialized `bool`!
// This is undefined behavior. ⚠️
}
For instance, you cannot Read
into an uninitialized buffer:
use std::{io, mem::MaybeUninit};
fn read_chunk (reader: &'_ mut dyn io::Read) -> io::Result<[u8; 64]>
{
let mut buffer = MaybeUninit::<[u8; 64]>::uninit();
reader.read_exact(unsafe { buffer.assume_init_mut() })?;
// ^^^^^^^^^^^^^^^^^^^^^^^^
// (mutable) reference to uninitialized memory!
// This is undefined behavior.
Ok(unsafe { buffer.assume_init() })
}
Nor can you use direct field access to do field-by-field gradual initialization:
use std::{mem::MaybeUninit, ptr};
struct Foo {
a: u32,
b: u8,
}
let foo: Foo = unsafe {
let mut foo = MaybeUninit::<Foo>::uninit();
ptr::write(&mut foo.assume_init_mut().a as *mut u32, 1337);
// ^^^^^^^^^^^^^^^^^^^^^
// (mutable) reference to uninitialized memory!
// This is undefined behavior.
ptr::write(&mut foo.assume_init_mut().b as *mut u8, 42);
// ^^^^^^^^^^^^^^^^^^^^^
// (mutable) reference to uninitialized memory!
// This is undefined behavior.
foo.assume_init()
};
sourcepub fn as_bytes(&self) -> &[MaybeUninit<u8>]
🔬This is a nightly-only experimental API. (maybe_uninit_as_bytes
)
pub fn as_bytes(&self) -> &[MaybeUninit<u8>]
maybe_uninit_as_bytes
)Returns the contents of this MaybeUninit
as a slice of potentially uninitialized bytes.
Note that even if the contents of a MaybeUninit
have been initialized, the value may still
contain padding bytes which are left uninitialized.
Examples
#![feature(maybe_uninit_as_bytes, maybe_uninit_slice)]
use std::mem::MaybeUninit;
let val = 0x12345678i32;
let uninit = MaybeUninit::new(val);
let uninit_bytes = uninit.as_bytes();
let bytes = unsafe { MaybeUninit::slice_assume_init_ref(uninit_bytes) };
assert_eq!(bytes, val.to_ne_bytes());
sourcepub fn as_bytes_mut(&mut self) -> &mut [MaybeUninit<u8>]
🔬This is a nightly-only experimental API. (maybe_uninit_as_bytes
)
pub fn as_bytes_mut(&mut self) -> &mut [MaybeUninit<u8>]
maybe_uninit_as_bytes
)Returns the contents of this MaybeUninit
as a mutable slice of potentially uninitialized
bytes.
Note that even if the contents of a MaybeUninit
have been initialized, the value may still
contain padding bytes which are left uninitialized.
Examples
#![feature(maybe_uninit_as_bytes)]
use std::mem::MaybeUninit;
let val = 0x12345678i32;
let mut uninit = MaybeUninit::new(val);
let uninit_bytes = uninit.as_bytes_mut();
if cfg!(target_endian = "little") {
uninit_bytes[0].write(0xcd);
} else {
uninit_bytes[3].write(0xcd);
}
let val2 = unsafe { uninit.assume_init() };
assert_eq!(val2, 0x123456cd);