pub struct ConstAllocator { /* private fields */ }
Expand description

Compile-time allocator.

This is implemented on top of core::intrinsics::const_allocate.

Stability

This type is subject to the kernel-side API stability guarantee.

Implementations§

source§

impl ConstAllocator

source

pub const fn with<F, R>(f: F) -> Rwhere F: FnOnce(&ConstAllocator) -> R,

Call the specified closure, passing a reference to a Self constructed on the stack.

Does not work at runtime.

All clones of Self and all allocations must be destroyed before the closure returns. This is because leaking const-allocated (interior-)mutable references to runtime code is unsound. See https://github.com/rust-lang/rust/pull/91884#discussion_r774659436.

Examples
#![feature(const_eval_limit)]
#![feature(const_trait_impl)]
#![feature(const_mut_refs)]
#![feature(const_option)]
#![const_eval_limit = "500000"]
use core::{alloc::Layout, ptr::NonNull};
use r3_core::utils::{ConstAllocator, Allocator};
const _: () = ConstAllocator::with(doit);
const fn doit(al: &ConstAllocator) {
    // You can clone `*al`, but you must destroy the clone before this
    // function returns
    let al = al.clone();

    unsafe {
        let mut blocks = [None; 256];
        let mut i = 0;
        while i < blocks.len() {
            // Allocate a memory block
            let Ok(layout) = Layout::from_size_align(i * 64, 8) else { unreachable!() };
            let Ok(alloc) = al.allocate(layout) else { unreachable!() };

            // Write something
            let alloc = alloc.cast::<u8>();
            if i > 0 { *alloc.as_ptr() = i as u8; }

            // Remember the allocation
            blocks[i] = Some((alloc, layout));

            i += 1;
        }

        i = 1;
        while i < blocks.len() {
            // Check the value inside the allocation
            let (ptr, _) = blocks[i].unwrap();
            assert!(*ptr.as_ptr() == i as u8);
            i += 1;
        }

        // You must deallocate all allocations before this
        // function returns
        i = 0;
        while i < blocks.len() {
            let (ptr, layout) = blocks[i].unwrap();
            al.deallocate(ptr, layout);
            i += 1;
        }
    }
}

It’s an error to leak allocations:

const fn doit(al: &ConstAllocator) {
    let Ok(layout) = Layout::from_size_align(64, 8) else { unreachable!() };
    let _ = al.allocate(layout);
}
const fn doit(al: &ConstAllocator) {
    core::mem::forget(al.clone());
}
source

pub const fn with_parametric<P, F, R>(p: P, f: F) -> Rwhere F: FnOnce(P, &ConstAllocator) -> R,

The variant of Self::with that lets you pass an additional parameter to the closure.

This can be used to work around the lack of compiler support for const closures.

Trait Implementations§

source§

impl Allocator for ConstAllocator

source§

const fn allocate(&self, layout: Layout) -> Result<NonNull<[u8]>, AllocError>

Attempts to allocate a block of memory.
source§

const unsafe fn deallocate(&self, ptr: NonNull<u8>, layout: Layout)

Deallocates the memory referenced by ptr. Read more
source§

fn allocate_zeroed(&self, layout: Layout) -> Result<NonNull<[u8]>, AllocError>

Behaves like allocate, but also ensures that the returned memory is zero-initialized.
source§

unsafe fn grow( &self, ptr: NonNull<u8>, old_layout: Layout, new_layout: Layout ) -> Result<NonNull<[u8]>, AllocError>

Attempts to extend the memory block. Read more
source§

unsafe fn grow_zeroed( &self, ptr: NonNull<u8>, old_layout: Layout, new_layout: Layout ) -> Result<NonNull<[u8]>, AllocError>

Behaves like grow, but also ensures that the new contents are set to zero before being returned. Read more
source§

unsafe fn shrink( &self, ptr: NonNull<u8>, old_layout: Layout, new_layout: Layout ) -> Result<NonNull<[u8]>, AllocError>

Attempts to shrink the memory block. Read more
source§

fn by_ref(&self) -> &Selfwhere Self: Sized,

Creates a “by reference” adapter for this instance of Allocator.
source§

impl Clone for ConstAllocator

source§

const fn clone(&self) -> Self

Returns a copy of the value. Read more
1.0.0 · source§

fn clone_from(&mut self, source: &Self)

Performs copy-assignment from source. Read more
source§

impl Drop for ConstAllocator

source§

const fn drop(&mut self)

Executes the destructor for this type. Read more

Auto Trait Implementations§

Blanket Implementations§

source§

impl<T> Any for Twhere T: 'static + ?Sized,

source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
source§

impl<T> Borrow<T> for Twhere T: ?Sized,

const: unstable · source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
source§

impl<T> BorrowMut<T> for Twhere T: ?Sized,

const: unstable · source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
source§

impl<T> From<T> for T

const: unstable · source§

fn from(t: T) -> T

Returns the argument unchanged.

source§

impl<T, U> Into<U> for Twhere U: From<T>,

const: unstable · source§

fn into(self) -> U

Calls U::from(self).

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

source§

impl<T, U> TryFrom<U> for Twhere U: Into<T>,

§

type Error = Infallible

The type returned in the event of a conversion error.
const: unstable · source§

fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>

Performs the conversion.
source§

impl<T, U> TryInto<U> for Twhere U: TryFrom<T>,

§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
const: unstable · source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.