pub struct LeakBox<'ctx, T: ?Sized> { /* private fields */ }
Expand description

Represents an allocation within a Bump.

This is an owning pointer comparable to Box. It drops the contained value when it is dropped itself. The difference is that no deallocation logic is ever executed.

FIXME(non-breaking): the name is rather confusing. Maybe it should be BumpBox or RefBox? Not StackBox because the value’s location in memory is not the defining feature.

§Usage

This box can be used to manage one valid instance constructed within the memory provided by a MaybeUninit instance.

use core::mem::MaybeUninit;
use static_alloc::leaked::LeakBox;

let mut storage = MaybeUninit::uninit();
let leak_box = LeakBox::from(&mut storage);
// The string itself is not managed by `static_alloc`.
let mut instance = LeakBox::write(leak_box, String::new());

instance.push_str("Hello world!");

This box is the result of allocating from one of the Bump allocators using its explicit API.

Being a box-like type, an Option has the same size.

use core::mem::size_of;
use static_alloc::leaked::LeakBox;

type Boxed = LeakBox<'static, usize>;
type Optional = Option<Boxed>;

assert_eq!(size_of::<Boxed>(), size_of::<Optional>());

TODO: On nightly the inner type should be unsizable.

Implementations§

source§

impl<'ctx, T: ?Sized> LeakBox<'ctx, T>

source

pub fn into_raw(this: Self) -> *mut T

Retrieve the raw pointer wrapped by this box.

After this method the caller is responsible for managing the value in the place behind the pointer. It will need to be dropped manually.

§Usage

You might manually drop the contained instance at a later point.

use static_alloc::{Bump, leaked::LeakBox};

let bump: Bump<[usize; 128]> = Bump::uninit();
let leak_box = bump.leak_box(String::from("Hello"))?;
let ptr = LeakBox::into_raw(leak_box);

unsafe {
    core::ptr::drop_in_place(ptr);
}

An alternative is to later re-wrap the pointer

use static_alloc::{Bump, leaked::LeakBox};

let bump: Bump<[usize; 128]> = Bump::uninit();
let leak_box = bump.leak_box(String::from("Hello"))?;
let ptr = LeakBox::into_raw(leak_box);

unsafe {
    let _ = LeakBox::from_raw(ptr);
};
source

pub unsafe fn from_raw(pointer: *mut T) -> Self

Wrap a raw pointer.

The most immediate use is to rewrap a pointer returned from into_raw.

§Safety

The pointer must point to a valid instance of T that is not aliased by any other reference for the lifetime 'ctx. In particular it must be valid aligned and initialized. Dropping this LeakBox will drop the instance, which the caller must also guarantee to be sound.

source

pub unsafe fn from_mut_unchecked(val: &'ctx mut T) -> Self

Wrap a mutable reference to a complex value as if it were owned.

§Safety

The value must be owned by the caller. That is, the mutable reference must not be used after the LeakBox is dropped. In particular the value must not be dropped by the caller.

§Example
use core::mem::ManuallyDrop;
use static_alloc::leaked::LeakBox;

fn with_stack_drop<T>(val: T) {
    let mut val = ManuallyDrop::new(val);
    // Safety:
    // - Shadows the variable, rendering the prior inaccessible.
    // - Dropping is now the responsibility of `LeakBox`.
    let val = unsafe { LeakBox::from_mut_unchecked(&mut *val) };
}

// Demonstrate that it is correctly dropped.
let variable = core::cell::RefCell::new(0);
with_stack_drop(variable.borrow_mut());
assert!(variable.try_borrow_mut().is_ok());
source

pub fn leak<'a>(this: Self) -> &'a mut T
where 'ctx: 'a,

Leak the instances as a mutable reference.

After calling this method the value is no longer managed by LeakBox. Its Drop impl will not be automatically called.

§Usage
use static_alloc::{Bump, leaked::LeakBox};

let bump: Bump<[usize; 128]> = Bump::uninit();
let leak_box = bump.leak_box(String::from("Hello"))?;

let st: &mut String = LeakBox::leak(leak_box);

You can’t leak past the lifetime of the allocator.

let bump: Bump<[usize; 128]> = Bump::uninit();
let leak_box = bump.leak_box(String::from("Hello"))?;
let st: &mut String = LeakBox::leak(leak_box);

drop(bump);
// error[E0505]: cannot move out of `bump` because it is borrowed
st.to_lowercase();
//-- borrow later used here
source§

impl<T: 'static> LeakBox<'static, T>

source

pub fn into_pin(this: Self) -> Pin<Self>

Pin an instance that’s leaked for the remaining program runtime.

After calling this method the value can only safely be referenced mutably if it is Unpin, otherwise it is only accessible behind a Pin. Note that this does not imply that the Drop glue, or explicit Drop-impl, is guaranteed to run.

§Usage

A decent portion of futures must be pinned before the can be awaited inside another future. In particular this is required for self-referential futures that store pointers into their own object’s memory. This is the case for the future type of an asnyc fn if there are potentially any stack references when it is suspended/waiting on another future. Consider this example:

use static_alloc::{Bump, leaked::LeakBox}; 

async fn example(x: usize) -> usize {
    // Holding reference across yield point.
    // This requires pinning to run this future.
    let y = &x;
    core::future::ready(()).await;
    *y
}

static POOL: Bump<[usize; 128]> = Bump::uninit();
let mut future = POOL.leak_box(example(0))
    .expect("Enough space for small async fn");

let usage = async move {
// error[E0277]: `GenFuture<[static generator@src/leaked.rs …]>` cannot be unpinned
    let _ = (&mut *future).await;
};

This method can be used to pin instances allocated from a global pool without requiring the use of a macro or unsafe on the caller’s part. Now, with the correct usage of into_pin:

use static_alloc::{Bump, leaked::LeakBox}; 

async fn example(x: usize) -> usize {
    // Holding reference across yield point.
    // This requires pinning to run this future.
    let y = &x;
    core::future::ready(()).await;
    *y
}

static POOL: Bump<[usize; 128]> = Bump::uninit();
let future = POOL.leak_box(example(0))
    .expect("Enough space for small async fn");

// PIN this future!
let mut future = LeakBox::into_pin(future);

let usage = async move {
    let _ = future.as_mut().await;
};
source§

impl<'ctx, T> LeakBox<'ctx, T>

source

pub fn take(this: Self) -> T

Remove the value, forgetting the box in the process.

This is similar to dereferencing a box (*leak_box) but no deallocation is involved. This becomes useful when the allocator turns out to have too short of a lifetime.

§Usage

You may want to move a long-lived value out of the current scope where it’s been allocated.

use static_alloc::{Bump, leaked::LeakBox};

let cell = RefCell::new(0usize);

let guard = {
    let bump: Bump<[usize; 128]> = Bump::uninit();

    let mut leaked = bump.leak_box(cell.borrow_mut()).unwrap();
    **leaked = 1usize;

    // Take the value, allowing use independent of the lifetime of bump
    LeakBox::take(leaked)
};

assert!(cell.try_borrow().is_err());
drop(guard);
assert!(cell.try_borrow().is_ok());
source

pub fn from_mut(val: &'ctx mut T) -> Self
where T: Copy,

Wrap a mutable reference to a trivial value as if it were a box.

This is safe because such values can not have any Drop code and can be duplicated at will.

The usefulness of this operation is questionable but the author would be delighted to hear about any actual use case.

source§

impl<'ctx, T> LeakBox<'ctx, MaybeUninit<T>>

source

pub fn write(this: Self, val: T) -> LeakBox<'ctx, T>

Write a value into this box, initializing it.

This can be used to delay the computation of a value until after an allocation succeeded while maintaining all types necessary for a safe initialization.

§Usage
use static_alloc::{Bump, leaked::LeakBox};

let bump: Bump<[usize; 128]> = Bump::uninit();
let memory = bump.leak_box(MaybeUninit::uninit())?;

let value = LeakBox::write(memory, some_expensive_operation());
source

pub unsafe fn assume_init(this: Self) -> LeakBox<'ctx, T>

Converts to LeakBox<T>.

§Safety

The value must have been initialized as required by MaybeUninit::assume_init. Calling this when the content is not yet fully initialized causes immediate undefined behavior.

Trait Implementations§

source§

impl<T: ?Sized> AsMut<T> for LeakBox<'_, T>

source§

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

Converts this type into a mutable reference of the (usually inferred) input type.
source§

impl<T: ?Sized> AsRef<T> for LeakBox<'_, T>

source§

fn as_ref(&self) -> &T

Converts this type into a shared reference of the (usually inferred) input type.
source§

impl<T: Debug + ?Sized> Debug for LeakBox<'_, T>

source§

fn fmt(&self, f: &mut Formatter<'_>) -> Result

Formats the value using the given formatter. Read more
source§

impl<'ctx, T: ?Sized> Deref for LeakBox<'ctx, T>

§

type Target = T

The resulting type after dereferencing.
source§

fn deref(&self) -> &Self::Target

Dereferences the value.
source§

impl<'ctx, T: ?Sized> DerefMut for LeakBox<'ctx, T>

source§

fn deref_mut(&mut self) -> &mut Self::Target

Mutably dereferences the value.
source§

impl<T: Display + ?Sized> Display for LeakBox<'_, T>

source§

fn fmt(&self, f: &mut Formatter<'_>) -> Result

Formats the value using the given formatter. Read more
source§

impl<T: ?Sized> Drop for LeakBox<'_, T>

source§

fn drop(&mut self)

Executes the destructor for this type. Read more
source§

impl<'ctx, T> From<&'ctx mut [MaybeUninit<T>]> for LeakBox<'ctx, [MaybeUninit<T>]>

Construct a LeakBox to an existing slice of MaybeUninit.

source§

fn from(uninit: &'ctx mut [MaybeUninit<T>]) -> Self

Converts to this type from the input type.
source§

impl<'ctx, T> From<&'ctx mut MaybeUninit<T>> for LeakBox<'ctx, MaybeUninit<T>>

Construct a LeakBox to an existing MaybeUninit.

The MaybeUninit type is special in that we can treat any unique reference to an owned value as an owned value itself since it has no representational invariants.

source§

fn from(uninit: &'ctx mut MaybeUninit<T>) -> Self

Converts to this type from the input type.
source§

impl<T: Hash + ?Sized> Hash for LeakBox<'_, T>

source§

fn hash<H: Hasher>(&self, h: &mut H)

Feeds this value into the given Hasher. Read more
1.3.0 · source§

fn hash_slice<H>(data: &[Self], state: &mut H)
where H: Hasher, Self: Sized,

Feeds a slice of this type into the given Hasher. Read more
source§

impl<T: ?Sized> Pointer for LeakBox<'_, T>

source§

fn fmt(&self, f: &mut Formatter<'_>) -> Result

Formats the value using the given formatter.

Auto Trait Implementations§

§

impl<'ctx, T: ?Sized> RefUnwindSafe for LeakBox<'ctx, T>
where T: RefUnwindSafe,

§

impl<'ctx, T> !Send for LeakBox<'ctx, T>

§

impl<'ctx, T> !Sync for LeakBox<'ctx, T>

§

impl<'ctx, T: ?Sized> Unpin for LeakBox<'ctx, T>

§

impl<'ctx, T: ?Sized> UnwindSafe for LeakBox<'ctx, T>
where T: RefUnwindSafe,

Blanket Implementations§

source§

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

source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
source§

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

source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
source§

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

source§

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

Mutably borrows from an owned value. Read more
source§

impl<T> From<T> for T

source§

fn from(t: T) -> T

Returns the argument unchanged.

source§

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

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> ToString for T
where T: Display + ?Sized,

source§

default fn to_string(&self) -> String

Converts the given value to a String. Read more
source§

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

§

type Error = Infallible

The type returned in the event of a conversion error.
source§

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

Performs the conversion.
source§

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

§

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

The type returned in the event of a conversion error.
source§

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

Performs the conversion.