In Rust, we can use the Box<T>
type to allocate things on the heap. This type is used to safely abstract pointers to heap memory. Box<T>
is provided by the Rust standard library.
I was curious about how Box<T>
allocation is implemented, so I found its source code. Here is the code for Box<T>::new
(as of Rust 1.0):
impl<T> Box<T> {
/// Allocates memory on the heap and then moves `x` into it.
/// [...]
#[stable(feature = "rust1", since = "1.0.0")]
#[inline(always)]
pub fn new(x: T) -> Box<T> {
box x
}
}
The only line in the implementation returns the value box x
. This box
keyword is not explained anywhere in the official documentation; in fact it is only mentioned briefly on the std::boxed
documentation page.
box
does exactly whatBox::new()
does - it creates an owned box.I believe that you can't find implementation of
box
keyword because currently it is hardcoded to work with owned boxes, andBox
type is a lang item:Because it is a lang item, the compiler has special logic to handle its instantiation which it can link with
box
keyword.I believe that the compiler delegates box allocation to functions in
alloc::heap
module.As for what
box
keyword does and supposed to do in general, Shepmaster's answer describes perfectly.Before
box
was marked as unstable, it was used as a shorthand for callingBox::new
. However, it's always been intended to be able to allocate arbitrary types, such asRc
, or to use arbitrary allocators. Neither of these have been finalized, so it wasn't marked as stable for the 1.0 release. This is done to prevent supporting a bad decision for all of Rust 1.x.For further reference, you can read the RFC that changed the "placement new" syntax and also feature gated it.
What does
box x
usually uses to allocate and free memory?The answer is the functions marked with lang items
exchange_malloc
for allocation andexchange_free
for freeing. You can see the implementation of those in the default standard library at heap.rs#L112 and heap.rs#L125.In the end the
box x
syntax depends on the following lang items:owned_box
on aBox
struct to encapsulate the allocated pointer. This struct does not need aDrop
implementation, it is implemented automatically by the compiler.exchange_malloc
to allocate the memory.exchange_free
to free the previously allocated memory.This can be effectively seen in the lang items chapter of the rust book using this
no_std
example:Notice how
Drop
was not implemented for theBox
struct? Well let's see the LLVM IR generated formain
:The
allocate
(_ZN8allocate20hf9df30890c435d76naaE
) was called as expected to build theBox
, meanwhile... Look! ADrop
method for theBox
(_ZN14Box$LT$i32$GT$9drop.103617h8817b938807fc41eE
)! Let's see the IR for this method:There it is,
deallocate
(ZN10deallocate20he2bff5e01707ad50VaaE
) being called on the compiler generated Drop!Notice even on the standard library the
Drop
trait is not implemented by user-code. IndeedBox
is a bit of a magical struct.