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

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.

Returns a pointer to the underlying memory.

Returns a mutable pointer to the underlying memory.

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).

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.

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.

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.

Returns a Slot of the internal contents.

Converts a Frame<T> into a Frame<[T]>.

This conversion does not allocate on the heap and happens in place.

Allocates memory in the given allocator.

This doesn’t actually allocate if T is zero-sized.

Sets the value of the underlying memory and converts the frame to a box.

This overwrites any previous value without dropping it, so be careful not to use this after initializing the frame unless you want to skip running the destructor.

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.

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.

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.

Allocates memory on the heap.

This doesn’t actually allocate if T is zero-sized.

Methods from Deref<Target = MaybeUninit<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_) }
    }
}

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.)

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.)

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!

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.

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!
}

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()
};
🔬This is a nightly-only experimental API. (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());
🔬This is a nightly-only experimental API. (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);

Trait Implementations

Returns the “default value” for a type. Read more
The resulting type after dereferencing.
Dereferences the value.
Mutably dereferences the value.
Executes the destructor for this type. Read more
The target value of this type.
Returns a pointer to this type’s target.

Auto Trait Implementations

Blanket Implementations

Gets the TypeId of self. Read more
Immutably borrows from an owned value. Read more
Mutably borrows from an owned value. Read more

Returns the argument unchanged.

Calls U::from(self).

That is, this conversion is whatever the implementation of From<T> for U chooses to do.

The type for metadata in pointers and references to Self.
The type returned in the event of a conversion error.
Performs the conversion.
The type returned in the event of a conversion error.
Performs the conversion.