Browse the docs

silk.mem.box.

One owned value on the heap, for recursive data and for values that must have a fixed-size handle.

When to use#

Use Box when a type must contain itself, such as a tree node that owns child nodes. A field of type Box<Node> has a fixed size, so the compiler can lay out Node. Use make to allocate, get or getMut to borrow the value, and into to get the value back.

Details#

A box owns one allocation and one value. get and getMut return a slice of length 1, because a Silk function cannot return a bare borrowed value. Dropping a box drops its value and releases the allocation. into moves the value out and releases the allocation one time.

Gotchas#

Dropping a chain of boxes uses one stack frame for each link. For a very long chain, take the links apart with into in a loop.

Examples#

Store and recover one owned value#

silk
import silk.mem.box { Box }
import silk.mem.allocator { Allocator, OutOfMemoryError }
import silk.core.effect { Effect }

pub effect fn main() -> i32
  ! OutOfMemoryError {
  let mut allocator = Allocator.systemAllocatorProvider()
  let mut boxed = run Box<i32>.make(40) |> Effect.provideMut<Allocator>(&mut allocator)
  let mut slot = Box<i32>.getMut(&mut boxed)
  slot[0] = slot[0] + 2
  drop slot
  let value = Box<i32>.into(move boxed)
  if value != 42 {
    return 1
  }
  return 0
}

Import as Box with import silk.mem.box { Box }.

Public declarations: 3.

Vacant#

silk
pub struct Vacant

The state marker of a Box whose value into has moved out. User code does not use it.

Occupied#

silk
pub struct Occupied

The state marker of a Box that owns its value. User code does not use it.

Box#

silk
pub struct Box<T>

An owner of one heap-allocated value of type T.

When to use#

Use a box when a type must contain itself, such as a tree node that owns child nodes. A field of type Box<Node> has a fixed size, so the compiler can lay out Node. Use make to allocate, get or getMut to borrow the value, and into to get the value back.

Details#

The size of Box<T> does not depend on T, so a type can contain a box of itself. Dropping a box drops the value and then releases the allocation. A box is affine. It is not Copy.

Gotchas#

Dropping a chain of boxes uses one stack frame for each link. For a very long chain, take the links apart with into in a loop.

Implementation Box<T>#

silk
impl<T> Box<T>

Associated function make#

silk
pub effect<'env> fn make<'env>(value: T) -> Box<T> ! OutOfMemoryError ? &mut Allocator

Allocates space for one T, moves value into it, and returns the box.

Details#

The allocation comes from the active Allocator. The box owns the value and the allocation.

Errors#

  • OutOfMemoryError if the Allocator cannot supply the memory. No box is made, and value is dropped.

Method get#

silk
pub fn get(self: &Self) -> &[T]

Returns a shared borrow of the value, as a slice of length 1.

Details#

Read the value as slice[0]. The slice borrows the box. The box cannot change or move while the slice is live.

Method getMut#

silk
pub fn getMut(self: &mut Self) -> &mut [T]

Returns an exclusive borrow of the value, as a slice of length 1.

Details#

Change the value through slice[0]. The slice borrows the box exclusively. No other use of the box is possible while the slice is live. Drop the slice to end the borrow early.

Method into#

silk
pub fn into(self: Self) -> T

Moves the value out of the box, releases the allocation, and returns the value.

When to use#

Use into when the caller needs the value itself, not a borrow. Use it in a loop to take apart a long chain of boxes without deep recursion. A plain drop of such a chain uses one stack frame for each link.

Implementation Drop for Box<T>#

silk
impl<T> Drop for Box<T>

Operation drop#

silk
fn drop(self: &mut Box<T>) -> ()

Category: Memory.

Profiles: aarch64-apple-darwin, aarch64-unknown-linux-gnu, aarch64-unknown-linux-gnu-no-libc, x86_64-unknown-linux-gnu, x86_64-unknown-linux-gnu-no-libc, wasm32-unknown-unknown, wasm32-wasip1, wasm32-wasip2.

View the source of this page