Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

bumpalo

The bumpalo crate provides a fast bump allocation arena for Rust that dramatically improves allocation performance in compiler workloads. Bump allocation, also known as linear or arena allocation, allocates memory by simply incrementing a pointer through a contiguous block of memory. This makes allocation extremely fast - just a pointer bump and bounds check - at the cost of not being able to deallocate individual objects. Instead, the entire arena is deallocated at once when dropped.

For compiler development, bump allocation is ideal because compilation naturally proceeds in phases where large numbers of temporary allocations are created, used, and then all discarded together. AST nodes, type information, and intermediate representations can all be allocated in arenas that live only as long as needed. This allocation strategy eliminates the overhead of reference counting or garbage collection while providing excellent cache locality.

Basic Allocation

The simplest use of bumpalo is allocating individual values:

#![allow(unused)]
fn main() {
use std::fmt::Debug;
use bumpalo::Bump;
use bumpalo::boxed::Box as BumpBox;
use bumpalo::collections::Vec as BumpVec;
/// Shows how to allocate strings in the bump allocator
pub fn allocate_strings(bump: &Bump) -> &str {
    // Allocate a string slice
    let hello = bump.alloc_str("Hello, ");
    let world = bump.alloc_str("World!");

    // Concatenate using bump allocation

    (bump.alloc_str(&format!("{}{}", hello, world))) as _
}
/// Allocates slices efficiently in the bump allocator
pub fn allocate_slices(bump: &Bump) -> &[i32] {
    // Allocate a slice from a vector
    let data = vec![1, 2, 3, 4, 5];
    bump.alloc_slice_copy(&data)
}
/// Demonstrates using bump-allocated collections
pub fn bump_collections() -> Vec<i32> {
    let bump = Bump::new();

    // Create a bump-allocated vector
    let mut vec = BumpVec::new_in(&bump);
    vec.push(1);
    vec.push(2);
    vec.push(3);

    // Convert to standard Vec for return
    vec.iter().copied().collect()
}
/// Shows arena-style allocation for AST nodes
#[derive(Debug, Clone)]
pub enum Expr<'a> {
    Number(i64),
    Add(&'a Expr<'a>, &'a Expr<'a>),
    Multiply(&'a Expr<'a>, &'a Expr<'a>),
}
pub fn build_ast<'a>(bump: &'a Bump) -> &'a Expr<'a> {
    // Build expression: (2 + 3) * 4
    let two = bump.alloc(Expr::Number(2));
    let three = bump.alloc(Expr::Number(3));
    let four = bump.alloc(Expr::Number(4));

    let add = bump.alloc(Expr::Add(two, three));
    bump.alloc(Expr::Multiply(add, four))
}
/// Evaluates an AST expression
pub fn eval_expr(expr: &Expr) -> i64 {
    match expr {
        Expr::Number(n) => *n,
        Expr::Add(a, b) => eval_expr(a) + eval_expr(b),
        Expr::Multiply(a, b) => eval_expr(a) * eval_expr(b),
    }
}
/// Demonstrates using bump allocation for a simple compiler IR
pub struct Function<'a> {
    pub name: &'a str,
    pub params: BumpVec<'a, &'a str>,
    pub body: BumpVec<'a, Statement<'a>>,
}
pub enum Statement<'a> {
    Let(&'a str, &'a Expr<'a>),
    Return(&'a Expr<'a>),
}
pub fn build_function<'a>(bump: &'a Bump) -> Function<'a> {
    let mut params = BumpVec::new_in(bump);
    let x = bump.alloc_str("x");
    let y = bump.alloc_str("y");
    params.push(&*x);
    params.push(&*y);

    let mut body = BumpVec::new_in(bump);

    // let sum = x + y
    let x = bump.alloc(Expr::Number(10));
    let y = bump.alloc(Expr::Number(20));
    let sum_expr = bump.alloc(Expr::Add(x, y));
    body.push(Statement::Let("sum", sum_expr));

    // return sum * 2
    let two = bump.alloc(Expr::Number(2));
    let result = bump.alloc(Expr::Multiply(sum_expr, two));
    body.push(Statement::Return(result));

    Function {
        name: bump.alloc_str("calculate"),
        params,
        body,
    }
}
/// Shows how to reset and reuse a bump allocator
pub fn reset_and_reuse() -> (Vec<i32>, Vec<i32>) {
    let mut bump = Bump::new();

    // First allocation cycle
    let first = {
        let vec = BumpVec::new_in(&bump);
        let mut vec = vec;
        vec.extend([1, 2, 3].iter().copied());
        vec.iter().copied().collect::<Vec<_>>()
    };

    // Reset the allocator to reclaim all memory
    bump.reset();

    // Second allocation cycle reuses the same memory
    let second = {
        let vec = BumpVec::new_in(&bump);
        let mut vec = vec;
        vec.extend([4, 5, 6].iter().copied());
        vec.iter().copied().collect::<Vec<_>>()
    };

    (first, second)
}
/// Demonstrates scoped allocation for temporary computations
pub fn scoped_allocation() -> i32 {
    let bump = Bump::new();

    // Create a temporary allocation scope

    // Memory is automatically freed when bump goes out of scope
    {
        // Allocate temporary working data
        let mut temps = BumpVec::new_in(&bump);
        for i in 0..100 {
            temps.push(i);
        }

        // Process data
        temps.iter().sum::<i32>()
    }
}
/// Shows using bump allocation with closures
pub fn with_allocator<F, R>(f: F) -> R
where
    F: FnOnce(&Bump) -> R, {
    let bump = Bump::new();
    f(&bump)
}
pub fn closure_example() -> i32 {
    with_allocator(|bump| {
        let numbers = bump.alloc_slice_copy(&[1, 2, 3, 4, 5]);
        numbers.iter().sum()
    })
}
/// Custom type that uses bump allocation internally
pub struct SymbolTable<'a> {
    bump: &'a Bump,
    symbols: BumpVec<'a, &'a str>,
}
impl<'a> SymbolTable<'a> {
    pub fn new(bump: &'a Bump) -> Self {
        Self {
            bump,
            symbols: BumpVec::new_in(bump),
        }
    }

    pub fn intern(&mut self, s: &str) -> usize {
        // Check if symbol already exists
        for (i, &sym) in self.symbols.iter().enumerate() {
            if sym == s {
                return i;
            }
        }

        // Allocate new symbol
        let symbol = self.bump.alloc_str(s);
        let id = self.symbols.len();
        self.symbols.push(symbol);
        id
    }

    pub fn get(&self, id: usize) -> Option<&'a str> {
        self.symbols.get(id).copied()
    }
}
/// Demonstrates using bump allocation for graph structures
pub struct Node<'a> {
    pub value: i32,
    pub children: BumpVec<'a, &'a Node<'a>>,
}
pub fn build_tree<'a>(bump: &'a Bump) -> &'a Node<'a> {
    // Build a simple tree structure
    let leaf1 = bump.alloc(Node {
        value: 1,
        children: BumpVec::new_in(bump),
    });

    let leaf2 = bump.alloc(Node {
        value: 2,
        children: BumpVec::new_in(bump),
    });

    let mut branch_children = BumpVec::new_in(bump);
    branch_children.push(&*leaf1);
    branch_children.push(&*leaf2);

    bump.alloc(Node {
        value: 3,
        children: branch_children,
    })
}
/// Shows statistics about memory usage
pub fn allocation_stats() {
    let mut bump = Bump::new();

    // Allocate some data
    for i in 0..1000 {
        bump.alloc(i);
    }

    // Get allocation statistics
    let allocated = bump.allocated_bytes();
    println!("Allocated: {} bytes", allocated);

    // Reset and check again
    bump.reset();
    let after_reset = bump.allocated_bytes();
    println!("After reset: {} bytes", after_reset);
}
/// Demonstrates bump boxes for single-value allocation
pub fn bump_box_example() -> i32 {
    let bump = Bump::new();

    // Create a bump-allocated box
    let boxed: BumpBox<i32> = BumpBox::new_in(100, &bump);

    // Bump boxes can be dereferenced like regular boxes
    *boxed
}
/// Shows efficient string building with bump allocation
pub struct StringBuilder<'a> {
    bump: &'a Bump,
    parts: BumpVec<'a, &'a str>,
}
impl<'a> StringBuilder<'a> {
    pub fn new(bump: &'a Bump) -> Self {
        Self {
            bump,
            parts: BumpVec::new_in(bump),
        }
    }

    pub fn append(&mut self, s: &str) {
        let part = self.bump.alloc_str(s);
        self.parts.push(part);
    }

    pub fn build(&self) -> String {
        self.parts.iter().flat_map(|s| s.chars()).collect()
    }
}
#[cfg(test)]
mod tests {
    use super::*;

    #[test]
    fn test_basic_allocation() {
        let result = basic_allocation();
        assert_eq!(result, vec![10, 20, 30]);
    }

    #[test]
    fn test_string_allocation() {
        let bump = Bump::new();
        let result = allocate_strings(&bump);
        assert_eq!(result, "Hello, World!");
    }

    #[test]
    fn test_ast_evaluation() {
        let bump = Bump::new();
        let ast = build_ast(&bump);
        assert_eq!(eval_expr(ast), 20); // (2 + 3) * 4 = 20
    }

    #[test]
    fn test_reset_reuse() {
        let (first, second) = reset_and_reuse();
        assert_eq!(first, vec![1, 2, 3]);
        assert_eq!(second, vec![4, 5, 6]);
    }

    #[test]
    fn test_symbol_table() {
        let bump = Bump::new();
        let mut table = SymbolTable::new(&bump);

        let id1 = table.intern("hello");
        let id2 = table.intern("world");
        let id3 = table.intern("hello"); // Should return same ID

        assert_eq!(id1, id3);
        assert_ne!(id1, id2);
        assert_eq!(table.get(id1), Some("hello"));
        assert_eq!(table.get(id2), Some("world"));
    }

    #[test]
    fn test_tree_building() {
        let bump = Bump::new();
        let tree = build_tree(&bump);

        assert_eq!(tree.value, 3);
        assert_eq!(tree.children.len(), 2);
        assert_eq!(tree.children[0].value, 1);
        assert_eq!(tree.children[1].value, 2);
    }

    #[test]
    fn test_string_builder() {
        let bump = Bump::new();
        let mut builder = StringBuilder::new(&bump);

        builder.append("Hello");
        builder.append(", ");
        builder.append("World!");

        assert_eq!(builder.build(), "Hello, World!");
    }
}
/// Demonstrates basic bump allocation with simple types
pub fn basic_allocation() -> Vec<i32> {
    let bump = Bump::new();

    // Allocate individual values
    let x = bump.alloc(10);
    let y = bump.alloc(20);
    let z = bump.alloc(30);

    // Values are valid for the lifetime of the bump allocator
    vec![*x, *y, *z]
}
}

Values allocated in the bump allocator are returned as references with the allocator’s lifetime. This ensures they remain valid as long as the allocator exists.

String Allocation

Bumpalo provides specialized methods for string allocation:

#![allow(unused)]
fn main() {
use std::fmt::Debug;
use bumpalo::Bump;
use bumpalo::boxed::Box as BumpBox;
use bumpalo::collections::Vec as BumpVec;
/// Demonstrates basic bump allocation with simple types
pub fn basic_allocation() -> Vec<i32> {
    let bump = Bump::new();

    // Allocate individual values
    let x = bump.alloc(10);
    let y = bump.alloc(20);
    let z = bump.alloc(30);

    // Values are valid for the lifetime of the bump allocator
    vec![*x, *y, *z]
}
/// Allocates slices efficiently in the bump allocator
pub fn allocate_slices(bump: &Bump) -> &[i32] {
    // Allocate a slice from a vector
    let data = vec![1, 2, 3, 4, 5];
    bump.alloc_slice_copy(&data)
}
/// Demonstrates using bump-allocated collections
pub fn bump_collections() -> Vec<i32> {
    let bump = Bump::new();

    // Create a bump-allocated vector
    let mut vec = BumpVec::new_in(&bump);
    vec.push(1);
    vec.push(2);
    vec.push(3);

    // Convert to standard Vec for return
    vec.iter().copied().collect()
}
/// Shows arena-style allocation for AST nodes
#[derive(Debug, Clone)]
pub enum Expr<'a> {
    Number(i64),
    Add(&'a Expr<'a>, &'a Expr<'a>),
    Multiply(&'a Expr<'a>, &'a Expr<'a>),
}
pub fn build_ast<'a>(bump: &'a Bump) -> &'a Expr<'a> {
    // Build expression: (2 + 3) * 4
    let two = bump.alloc(Expr::Number(2));
    let three = bump.alloc(Expr::Number(3));
    let four = bump.alloc(Expr::Number(4));

    let add = bump.alloc(Expr::Add(two, three));
    bump.alloc(Expr::Multiply(add, four))
}
/// Evaluates an AST expression
pub fn eval_expr(expr: &Expr) -> i64 {
    match expr {
        Expr::Number(n) => *n,
        Expr::Add(a, b) => eval_expr(a) + eval_expr(b),
        Expr::Multiply(a, b) => eval_expr(a) * eval_expr(b),
    }
}
/// Demonstrates using bump allocation for a simple compiler IR
pub struct Function<'a> {
    pub name: &'a str,
    pub params: BumpVec<'a, &'a str>,
    pub body: BumpVec<'a, Statement<'a>>,
}
pub enum Statement<'a> {
    Let(&'a str, &'a Expr<'a>),
    Return(&'a Expr<'a>),
}
pub fn build_function<'a>(bump: &'a Bump) -> Function<'a> {
    let mut params = BumpVec::new_in(bump);
    let x = bump.alloc_str("x");
    let y = bump.alloc_str("y");
    params.push(&*x);
    params.push(&*y);

    let mut body = BumpVec::new_in(bump);

    // let sum = x + y
    let x = bump.alloc(Expr::Number(10));
    let y = bump.alloc(Expr::Number(20));
    let sum_expr = bump.alloc(Expr::Add(x, y));
    body.push(Statement::Let("sum", sum_expr));

    // return sum * 2
    let two = bump.alloc(Expr::Number(2));
    let result = bump.alloc(Expr::Multiply(sum_expr, two));
    body.push(Statement::Return(result));

    Function {
        name: bump.alloc_str("calculate"),
        params,
        body,
    }
}
/// Shows how to reset and reuse a bump allocator
pub fn reset_and_reuse() -> (Vec<i32>, Vec<i32>) {
    let mut bump = Bump::new();

    // First allocation cycle
    let first = {
        let vec = BumpVec::new_in(&bump);
        let mut vec = vec;
        vec.extend([1, 2, 3].iter().copied());
        vec.iter().copied().collect::<Vec<_>>()
    };

    // Reset the allocator to reclaim all memory
    bump.reset();

    // Second allocation cycle reuses the same memory
    let second = {
        let vec = BumpVec::new_in(&bump);
        let mut vec = vec;
        vec.extend([4, 5, 6].iter().copied());
        vec.iter().copied().collect::<Vec<_>>()
    };

    (first, second)
}
/// Demonstrates scoped allocation for temporary computations
pub fn scoped_allocation() -> i32 {
    let bump = Bump::new();

    // Create a temporary allocation scope

    // Memory is automatically freed when bump goes out of scope
    {
        // Allocate temporary working data
        let mut temps = BumpVec::new_in(&bump);
        for i in 0..100 {
            temps.push(i);
        }

        // Process data
        temps.iter().sum::<i32>()
    }
}
/// Shows using bump allocation with closures
pub fn with_allocator<F, R>(f: F) -> R
where
    F: FnOnce(&Bump) -> R, {
    let bump = Bump::new();
    f(&bump)
}
pub fn closure_example() -> i32 {
    with_allocator(|bump| {
        let numbers = bump.alloc_slice_copy(&[1, 2, 3, 4, 5]);
        numbers.iter().sum()
    })
}
/// Custom type that uses bump allocation internally
pub struct SymbolTable<'a> {
    bump: &'a Bump,
    symbols: BumpVec<'a, &'a str>,
}
impl<'a> SymbolTable<'a> {
    pub fn new(bump: &'a Bump) -> Self {
        Self {
            bump,
            symbols: BumpVec::new_in(bump),
        }
    }

    pub fn intern(&mut self, s: &str) -> usize {
        // Check if symbol already exists
        for (i, &sym) in self.symbols.iter().enumerate() {
            if sym == s {
                return i;
            }
        }

        // Allocate new symbol
        let symbol = self.bump.alloc_str(s);
        let id = self.symbols.len();
        self.symbols.push(symbol);
        id
    }

    pub fn get(&self, id: usize) -> Option<&'a str> {
        self.symbols.get(id).copied()
    }
}
/// Demonstrates using bump allocation for graph structures
pub struct Node<'a> {
    pub value: i32,
    pub children: BumpVec<'a, &'a Node<'a>>,
}
pub fn build_tree<'a>(bump: &'a Bump) -> &'a Node<'a> {
    // Build a simple tree structure
    let leaf1 = bump.alloc(Node {
        value: 1,
        children: BumpVec::new_in(bump),
    });

    let leaf2 = bump.alloc(Node {
        value: 2,
        children: BumpVec::new_in(bump),
    });

    let mut branch_children = BumpVec::new_in(bump);
    branch_children.push(&*leaf1);
    branch_children.push(&*leaf2);

    bump.alloc(Node {
        value: 3,
        children: branch_children,
    })
}
/// Shows statistics about memory usage
pub fn allocation_stats() {
    let mut bump = Bump::new();

    // Allocate some data
    for i in 0..1000 {
        bump.alloc(i);
    }

    // Get allocation statistics
    let allocated = bump.allocated_bytes();
    println!("Allocated: {} bytes", allocated);

    // Reset and check again
    bump.reset();
    let after_reset = bump.allocated_bytes();
    println!("After reset: {} bytes", after_reset);
}
/// Demonstrates bump boxes for single-value allocation
pub fn bump_box_example() -> i32 {
    let bump = Bump::new();

    // Create a bump-allocated box
    let boxed: BumpBox<i32> = BumpBox::new_in(100, &bump);

    // Bump boxes can be dereferenced like regular boxes
    *boxed
}
/// Shows efficient string building with bump allocation
pub struct StringBuilder<'a> {
    bump: &'a Bump,
    parts: BumpVec<'a, &'a str>,
}
impl<'a> StringBuilder<'a> {
    pub fn new(bump: &'a Bump) -> Self {
        Self {
            bump,
            parts: BumpVec::new_in(bump),
        }
    }

    pub fn append(&mut self, s: &str) {
        let part = self.bump.alloc_str(s);
        self.parts.push(part);
    }

    pub fn build(&self) -> String {
        self.parts.iter().flat_map(|s| s.chars()).collect()
    }
}
#[cfg(test)]
mod tests {
    use super::*;

    #[test]
    fn test_basic_allocation() {
        let result = basic_allocation();
        assert_eq!(result, vec![10, 20, 30]);
    }

    #[test]
    fn test_string_allocation() {
        let bump = Bump::new();
        let result = allocate_strings(&bump);
        assert_eq!(result, "Hello, World!");
    }

    #[test]
    fn test_ast_evaluation() {
        let bump = Bump::new();
        let ast = build_ast(&bump);
        assert_eq!(eval_expr(ast), 20); // (2 + 3) * 4 = 20
    }

    #[test]
    fn test_reset_reuse() {
        let (first, second) = reset_and_reuse();
        assert_eq!(first, vec![1, 2, 3]);
        assert_eq!(second, vec![4, 5, 6]);
    }

    #[test]
    fn test_symbol_table() {
        let bump = Bump::new();
        let mut table = SymbolTable::new(&bump);

        let id1 = table.intern("hello");
        let id2 = table.intern("world");
        let id3 = table.intern("hello"); // Should return same ID

        assert_eq!(id1, id3);
        assert_ne!(id1, id2);
        assert_eq!(table.get(id1), Some("hello"));
        assert_eq!(table.get(id2), Some("world"));
    }

    #[test]
    fn test_tree_building() {
        let bump = Bump::new();
        let tree = build_tree(&bump);

        assert_eq!(tree.value, 3);
        assert_eq!(tree.children.len(), 2);
        assert_eq!(tree.children[0].value, 1);
        assert_eq!(tree.children[1].value, 2);
    }

    #[test]
    fn test_string_builder() {
        let bump = Bump::new();
        let mut builder = StringBuilder::new(&bump);

        builder.append("Hello");
        builder.append(", ");
        builder.append("World!");

        assert_eq!(builder.build(), "Hello, World!");
    }
}
/// Shows how to allocate strings in the bump allocator
pub fn allocate_strings(bump: &Bump) -> &str {
    // Allocate a string slice
    let hello = bump.alloc_str("Hello, ");
    let world = bump.alloc_str("World!");

    // Concatenate using bump allocation

    (bump.alloc_str(&format!("{}{}", hello, world))) as _
}
}

The alloc_str method is particularly efficient for building up strings during parsing or code generation, as it avoids the overhead of String’s capacity management.

Slice Allocation

Copying slices into the arena is straightforward:

#![allow(unused)]
fn main() {
use std::fmt::Debug;
use bumpalo::Bump;
use bumpalo::boxed::Box as BumpBox;
use bumpalo::collections::Vec as BumpVec;
/// Demonstrates basic bump allocation with simple types
pub fn basic_allocation() -> Vec<i32> {
    let bump = Bump::new();

    // Allocate individual values
    let x = bump.alloc(10);
    let y = bump.alloc(20);
    let z = bump.alloc(30);

    // Values are valid for the lifetime of the bump allocator
    vec![*x, *y, *z]
}
/// Shows how to allocate strings in the bump allocator
pub fn allocate_strings(bump: &Bump) -> &str {
    // Allocate a string slice
    let hello = bump.alloc_str("Hello, ");
    let world = bump.alloc_str("World!");

    // Concatenate using bump allocation

    (bump.alloc_str(&format!("{}{}", hello, world))) as _
}
/// Demonstrates using bump-allocated collections
pub fn bump_collections() -> Vec<i32> {
    let bump = Bump::new();

    // Create a bump-allocated vector
    let mut vec = BumpVec::new_in(&bump);
    vec.push(1);
    vec.push(2);
    vec.push(3);

    // Convert to standard Vec for return
    vec.iter().copied().collect()
}
/// Shows arena-style allocation for AST nodes
#[derive(Debug, Clone)]
pub enum Expr<'a> {
    Number(i64),
    Add(&'a Expr<'a>, &'a Expr<'a>),
    Multiply(&'a Expr<'a>, &'a Expr<'a>),
}
pub fn build_ast<'a>(bump: &'a Bump) -> &'a Expr<'a> {
    // Build expression: (2 + 3) * 4
    let two = bump.alloc(Expr::Number(2));
    let three = bump.alloc(Expr::Number(3));
    let four = bump.alloc(Expr::Number(4));

    let add = bump.alloc(Expr::Add(two, three));
    bump.alloc(Expr::Multiply(add, four))
}
/// Evaluates an AST expression
pub fn eval_expr(expr: &Expr) -> i64 {
    match expr {
        Expr::Number(n) => *n,
        Expr::Add(a, b) => eval_expr(a) + eval_expr(b),
        Expr::Multiply(a, b) => eval_expr(a) * eval_expr(b),
    }
}
/// Demonstrates using bump allocation for a simple compiler IR
pub struct Function<'a> {
    pub name: &'a str,
    pub params: BumpVec<'a, &'a str>,
    pub body: BumpVec<'a, Statement<'a>>,
}
pub enum Statement<'a> {
    Let(&'a str, &'a Expr<'a>),
    Return(&'a Expr<'a>),
}
pub fn build_function<'a>(bump: &'a Bump) -> Function<'a> {
    let mut params = BumpVec::new_in(bump);
    let x = bump.alloc_str("x");
    let y = bump.alloc_str("y");
    params.push(&*x);
    params.push(&*y);

    let mut body = BumpVec::new_in(bump);

    // let sum = x + y
    let x = bump.alloc(Expr::Number(10));
    let y = bump.alloc(Expr::Number(20));
    let sum_expr = bump.alloc(Expr::Add(x, y));
    body.push(Statement::Let("sum", sum_expr));

    // return sum * 2
    let two = bump.alloc(Expr::Number(2));
    let result = bump.alloc(Expr::Multiply(sum_expr, two));
    body.push(Statement::Return(result));

    Function {
        name: bump.alloc_str("calculate"),
        params,
        body,
    }
}
/// Shows how to reset and reuse a bump allocator
pub fn reset_and_reuse() -> (Vec<i32>, Vec<i32>) {
    let mut bump = Bump::new();

    // First allocation cycle
    let first = {
        let vec = BumpVec::new_in(&bump);
        let mut vec = vec;
        vec.extend([1, 2, 3].iter().copied());
        vec.iter().copied().collect::<Vec<_>>()
    };

    // Reset the allocator to reclaim all memory
    bump.reset();

    // Second allocation cycle reuses the same memory
    let second = {
        let vec = BumpVec::new_in(&bump);
        let mut vec = vec;
        vec.extend([4, 5, 6].iter().copied());
        vec.iter().copied().collect::<Vec<_>>()
    };

    (first, second)
}
/// Demonstrates scoped allocation for temporary computations
pub fn scoped_allocation() -> i32 {
    let bump = Bump::new();

    // Create a temporary allocation scope

    // Memory is automatically freed when bump goes out of scope
    {
        // Allocate temporary working data
        let mut temps = BumpVec::new_in(&bump);
        for i in 0..100 {
            temps.push(i);
        }

        // Process data
        temps.iter().sum::<i32>()
    }
}
/// Shows using bump allocation with closures
pub fn with_allocator<F, R>(f: F) -> R
where
    F: FnOnce(&Bump) -> R, {
    let bump = Bump::new();
    f(&bump)
}
pub fn closure_example() -> i32 {
    with_allocator(|bump| {
        let numbers = bump.alloc_slice_copy(&[1, 2, 3, 4, 5]);
        numbers.iter().sum()
    })
}
/// Custom type that uses bump allocation internally
pub struct SymbolTable<'a> {
    bump: &'a Bump,
    symbols: BumpVec<'a, &'a str>,
}
impl<'a> SymbolTable<'a> {
    pub fn new(bump: &'a Bump) -> Self {
        Self {
            bump,
            symbols: BumpVec::new_in(bump),
        }
    }

    pub fn intern(&mut self, s: &str) -> usize {
        // Check if symbol already exists
        for (i, &sym) in self.symbols.iter().enumerate() {
            if sym == s {
                return i;
            }
        }

        // Allocate new symbol
        let symbol = self.bump.alloc_str(s);
        let id = self.symbols.len();
        self.symbols.push(symbol);
        id
    }

    pub fn get(&self, id: usize) -> Option<&'a str> {
        self.symbols.get(id).copied()
    }
}
/// Demonstrates using bump allocation for graph structures
pub struct Node<'a> {
    pub value: i32,
    pub children: BumpVec<'a, &'a Node<'a>>,
}
pub fn build_tree<'a>(bump: &'a Bump) -> &'a Node<'a> {
    // Build a simple tree structure
    let leaf1 = bump.alloc(Node {
        value: 1,
        children: BumpVec::new_in(bump),
    });

    let leaf2 = bump.alloc(Node {
        value: 2,
        children: BumpVec::new_in(bump),
    });

    let mut branch_children = BumpVec::new_in(bump);
    branch_children.push(&*leaf1);
    branch_children.push(&*leaf2);

    bump.alloc(Node {
        value: 3,
        children: branch_children,
    })
}
/// Shows statistics about memory usage
pub fn allocation_stats() {
    let mut bump = Bump::new();

    // Allocate some data
    for i in 0..1000 {
        bump.alloc(i);
    }

    // Get allocation statistics
    let allocated = bump.allocated_bytes();
    println!("Allocated: {} bytes", allocated);

    // Reset and check again
    bump.reset();
    let after_reset = bump.allocated_bytes();
    println!("After reset: {} bytes", after_reset);
}
/// Demonstrates bump boxes for single-value allocation
pub fn bump_box_example() -> i32 {
    let bump = Bump::new();

    // Create a bump-allocated box
    let boxed: BumpBox<i32> = BumpBox::new_in(100, &bump);

    // Bump boxes can be dereferenced like regular boxes
    *boxed
}
/// Shows efficient string building with bump allocation
pub struct StringBuilder<'a> {
    bump: &'a Bump,
    parts: BumpVec<'a, &'a str>,
}
impl<'a> StringBuilder<'a> {
    pub fn new(bump: &'a Bump) -> Self {
        Self {
            bump,
            parts: BumpVec::new_in(bump),
        }
    }

    pub fn append(&mut self, s: &str) {
        let part = self.bump.alloc_str(s);
        self.parts.push(part);
    }

    pub fn build(&self) -> String {
        self.parts.iter().flat_map(|s| s.chars()).collect()
    }
}
#[cfg(test)]
mod tests {
    use super::*;

    #[test]
    fn test_basic_allocation() {
        let result = basic_allocation();
        assert_eq!(result, vec![10, 20, 30]);
    }

    #[test]
    fn test_string_allocation() {
        let bump = Bump::new();
        let result = allocate_strings(&bump);
        assert_eq!(result, "Hello, World!");
    }

    #[test]
    fn test_ast_evaluation() {
        let bump = Bump::new();
        let ast = build_ast(&bump);
        assert_eq!(eval_expr(ast), 20); // (2 + 3) * 4 = 20
    }

    #[test]
    fn test_reset_reuse() {
        let (first, second) = reset_and_reuse();
        assert_eq!(first, vec![1, 2, 3]);
        assert_eq!(second, vec![4, 5, 6]);
    }

    #[test]
    fn test_symbol_table() {
        let bump = Bump::new();
        let mut table = SymbolTable::new(&bump);

        let id1 = table.intern("hello");
        let id2 = table.intern("world");
        let id3 = table.intern("hello"); // Should return same ID

        assert_eq!(id1, id3);
        assert_ne!(id1, id2);
        assert_eq!(table.get(id1), Some("hello"));
        assert_eq!(table.get(id2), Some("world"));
    }

    #[test]
    fn test_tree_building() {
        let bump = Bump::new();
        let tree = build_tree(&bump);

        assert_eq!(tree.value, 3);
        assert_eq!(tree.children.len(), 2);
        assert_eq!(tree.children[0].value, 1);
        assert_eq!(tree.children[1].value, 2);
    }

    #[test]
    fn test_string_builder() {
        let bump = Bump::new();
        let mut builder = StringBuilder::new(&bump);

        builder.append("Hello");
        builder.append(", ");
        builder.append("World!");

        assert_eq!(builder.build(), "Hello, World!");
    }
}
/// Allocates slices efficiently in the bump allocator
pub fn allocate_slices(bump: &Bump) -> &[i32] {
    // Allocate a slice from a vector
    let data = vec![1, 2, 3, 4, 5];
    bump.alloc_slice_copy(&data)
}
}

This is useful for storing parsed tokens, symbol tables, or any sequence of data that needs to outlive its original source.

Bump-Allocated Collections

Bumpalo provides arena-allocated versions of common collections:

#![allow(unused)]
fn main() {
use std::fmt::Debug;
use bumpalo::Bump;
use bumpalo::boxed::Box as BumpBox;
use bumpalo::collections::Vec as BumpVec;
/// Demonstrates basic bump allocation with simple types
pub fn basic_allocation() -> Vec<i32> {
    let bump = Bump::new();

    // Allocate individual values
    let x = bump.alloc(10);
    let y = bump.alloc(20);
    let z = bump.alloc(30);

    // Values are valid for the lifetime of the bump allocator
    vec![*x, *y, *z]
}
/// Shows how to allocate strings in the bump allocator
pub fn allocate_strings(bump: &Bump) -> &str {
    // Allocate a string slice
    let hello = bump.alloc_str("Hello, ");
    let world = bump.alloc_str("World!");

    // Concatenate using bump allocation

    (bump.alloc_str(&format!("{}{}", hello, world))) as _
}
/// Allocates slices efficiently in the bump allocator
pub fn allocate_slices(bump: &Bump) -> &[i32] {
    // Allocate a slice from a vector
    let data = vec![1, 2, 3, 4, 5];
    bump.alloc_slice_copy(&data)
}
/// Shows arena-style allocation for AST nodes
#[derive(Debug, Clone)]
pub enum Expr<'a> {
    Number(i64),
    Add(&'a Expr<'a>, &'a Expr<'a>),
    Multiply(&'a Expr<'a>, &'a Expr<'a>),
}
pub fn build_ast<'a>(bump: &'a Bump) -> &'a Expr<'a> {
    // Build expression: (2 + 3) * 4
    let two = bump.alloc(Expr::Number(2));
    let three = bump.alloc(Expr::Number(3));
    let four = bump.alloc(Expr::Number(4));

    let add = bump.alloc(Expr::Add(two, three));
    bump.alloc(Expr::Multiply(add, four))
}
/// Evaluates an AST expression
pub fn eval_expr(expr: &Expr) -> i64 {
    match expr {
        Expr::Number(n) => *n,
        Expr::Add(a, b) => eval_expr(a) + eval_expr(b),
        Expr::Multiply(a, b) => eval_expr(a) * eval_expr(b),
    }
}
/// Demonstrates using bump allocation for a simple compiler IR
pub struct Function<'a> {
    pub name: &'a str,
    pub params: BumpVec<'a, &'a str>,
    pub body: BumpVec<'a, Statement<'a>>,
}
pub enum Statement<'a> {
    Let(&'a str, &'a Expr<'a>),
    Return(&'a Expr<'a>),
}
pub fn build_function<'a>(bump: &'a Bump) -> Function<'a> {
    let mut params = BumpVec::new_in(bump);
    let x = bump.alloc_str("x");
    let y = bump.alloc_str("y");
    params.push(&*x);
    params.push(&*y);

    let mut body = BumpVec::new_in(bump);

    // let sum = x + y
    let x = bump.alloc(Expr::Number(10));
    let y = bump.alloc(Expr::Number(20));
    let sum_expr = bump.alloc(Expr::Add(x, y));
    body.push(Statement::Let("sum", sum_expr));

    // return sum * 2
    let two = bump.alloc(Expr::Number(2));
    let result = bump.alloc(Expr::Multiply(sum_expr, two));
    body.push(Statement::Return(result));

    Function {
        name: bump.alloc_str("calculate"),
        params,
        body,
    }
}
/// Shows how to reset and reuse a bump allocator
pub fn reset_and_reuse() -> (Vec<i32>, Vec<i32>) {
    let mut bump = Bump::new();

    // First allocation cycle
    let first = {
        let vec = BumpVec::new_in(&bump);
        let mut vec = vec;
        vec.extend([1, 2, 3].iter().copied());
        vec.iter().copied().collect::<Vec<_>>()
    };

    // Reset the allocator to reclaim all memory
    bump.reset();

    // Second allocation cycle reuses the same memory
    let second = {
        let vec = BumpVec::new_in(&bump);
        let mut vec = vec;
        vec.extend([4, 5, 6].iter().copied());
        vec.iter().copied().collect::<Vec<_>>()
    };

    (first, second)
}
/// Demonstrates scoped allocation for temporary computations
pub fn scoped_allocation() -> i32 {
    let bump = Bump::new();

    // Create a temporary allocation scope

    // Memory is automatically freed when bump goes out of scope
    {
        // Allocate temporary working data
        let mut temps = BumpVec::new_in(&bump);
        for i in 0..100 {
            temps.push(i);
        }

        // Process data
        temps.iter().sum::<i32>()
    }
}
/// Shows using bump allocation with closures
pub fn with_allocator<F, R>(f: F) -> R
where
    F: FnOnce(&Bump) -> R, {
    let bump = Bump::new();
    f(&bump)
}
pub fn closure_example() -> i32 {
    with_allocator(|bump| {
        let numbers = bump.alloc_slice_copy(&[1, 2, 3, 4, 5]);
        numbers.iter().sum()
    })
}
/// Custom type that uses bump allocation internally
pub struct SymbolTable<'a> {
    bump: &'a Bump,
    symbols: BumpVec<'a, &'a str>,
}
impl<'a> SymbolTable<'a> {
    pub fn new(bump: &'a Bump) -> Self {
        Self {
            bump,
            symbols: BumpVec::new_in(bump),
        }
    }

    pub fn intern(&mut self, s: &str) -> usize {
        // Check if symbol already exists
        for (i, &sym) in self.symbols.iter().enumerate() {
            if sym == s {
                return i;
            }
        }

        // Allocate new symbol
        let symbol = self.bump.alloc_str(s);
        let id = self.symbols.len();
        self.symbols.push(symbol);
        id
    }

    pub fn get(&self, id: usize) -> Option<&'a str> {
        self.symbols.get(id).copied()
    }
}
/// Demonstrates using bump allocation for graph structures
pub struct Node<'a> {
    pub value: i32,
    pub children: BumpVec<'a, &'a Node<'a>>,
}
pub fn build_tree<'a>(bump: &'a Bump) -> &'a Node<'a> {
    // Build a simple tree structure
    let leaf1 = bump.alloc(Node {
        value: 1,
        children: BumpVec::new_in(bump),
    });

    let leaf2 = bump.alloc(Node {
        value: 2,
        children: BumpVec::new_in(bump),
    });

    let mut branch_children = BumpVec::new_in(bump);
    branch_children.push(&*leaf1);
    branch_children.push(&*leaf2);

    bump.alloc(Node {
        value: 3,
        children: branch_children,
    })
}
/// Shows statistics about memory usage
pub fn allocation_stats() {
    let mut bump = Bump::new();

    // Allocate some data
    for i in 0..1000 {
        bump.alloc(i);
    }

    // Get allocation statistics
    let allocated = bump.allocated_bytes();
    println!("Allocated: {} bytes", allocated);

    // Reset and check again
    bump.reset();
    let after_reset = bump.allocated_bytes();
    println!("After reset: {} bytes", after_reset);
}
/// Demonstrates bump boxes for single-value allocation
pub fn bump_box_example() -> i32 {
    let bump = Bump::new();

    // Create a bump-allocated box
    let boxed: BumpBox<i32> = BumpBox::new_in(100, &bump);

    // Bump boxes can be dereferenced like regular boxes
    *boxed
}
/// Shows efficient string building with bump allocation
pub struct StringBuilder<'a> {
    bump: &'a Bump,
    parts: BumpVec<'a, &'a str>,
}
impl<'a> StringBuilder<'a> {
    pub fn new(bump: &'a Bump) -> Self {
        Self {
            bump,
            parts: BumpVec::new_in(bump),
        }
    }

    pub fn append(&mut self, s: &str) {
        let part = self.bump.alloc_str(s);
        self.parts.push(part);
    }

    pub fn build(&self) -> String {
        self.parts.iter().flat_map(|s| s.chars()).collect()
    }
}
#[cfg(test)]
mod tests {
    use super::*;

    #[test]
    fn test_basic_allocation() {
        let result = basic_allocation();
        assert_eq!(result, vec![10, 20, 30]);
    }

    #[test]
    fn test_string_allocation() {
        let bump = Bump::new();
        let result = allocate_strings(&bump);
        assert_eq!(result, "Hello, World!");
    }

    #[test]
    fn test_ast_evaluation() {
        let bump = Bump::new();
        let ast = build_ast(&bump);
        assert_eq!(eval_expr(ast), 20); // (2 + 3) * 4 = 20
    }

    #[test]
    fn test_reset_reuse() {
        let (first, second) = reset_and_reuse();
        assert_eq!(first, vec![1, 2, 3]);
        assert_eq!(second, vec![4, 5, 6]);
    }

    #[test]
    fn test_symbol_table() {
        let bump = Bump::new();
        let mut table = SymbolTable::new(&bump);

        let id1 = table.intern("hello");
        let id2 = table.intern("world");
        let id3 = table.intern("hello"); // Should return same ID

        assert_eq!(id1, id3);
        assert_ne!(id1, id2);
        assert_eq!(table.get(id1), Some("hello"));
        assert_eq!(table.get(id2), Some("world"));
    }

    #[test]
    fn test_tree_building() {
        let bump = Bump::new();
        let tree = build_tree(&bump);

        assert_eq!(tree.value, 3);
        assert_eq!(tree.children.len(), 2);
        assert_eq!(tree.children[0].value, 1);
        assert_eq!(tree.children[1].value, 2);
    }

    #[test]
    fn test_string_builder() {
        let bump = Bump::new();
        let mut builder = StringBuilder::new(&bump);

        builder.append("Hello");
        builder.append(", ");
        builder.append("World!");

        assert_eq!(builder.build(), "Hello, World!");
    }
}
/// Demonstrates using bump-allocated collections
pub fn bump_collections() -> Vec<i32> {
    let bump = Bump::new();

    // Create a bump-allocated vector
    let mut vec = BumpVec::new_in(&bump);
    vec.push(1);
    vec.push(2);
    vec.push(3);

    // Convert to standard Vec for return
    vec.iter().copied().collect()
}
}

These collections avoid heap allocations entirely, storing their data directly in the arena. This is perfect for temporary collections during compilation passes.

AST Construction

Arena allocation shines for building recursive data structures like ASTs:

#![allow(unused)]
fn main() {
use std::fmt::Debug;
use bumpalo::Bump;
use bumpalo::boxed::Box as BumpBox;
use bumpalo::collections::Vec as BumpVec;
/// Demonstrates basic bump allocation with simple types
pub fn basic_allocation() -> Vec<i32> {
    let bump = Bump::new();

    // Allocate individual values
    let x = bump.alloc(10);
    let y = bump.alloc(20);
    let z = bump.alloc(30);

    // Values are valid for the lifetime of the bump allocator
    vec![*x, *y, *z]
}
/// Shows how to allocate strings in the bump allocator
pub fn allocate_strings(bump: &Bump) -> &str {
    // Allocate a string slice
    let hello = bump.alloc_str("Hello, ");
    let world = bump.alloc_str("World!");

    // Concatenate using bump allocation

    (bump.alloc_str(&format!("{}{}", hello, world))) as _
}
/// Allocates slices efficiently in the bump allocator
pub fn allocate_slices(bump: &Bump) -> &[i32] {
    // Allocate a slice from a vector
    let data = vec![1, 2, 3, 4, 5];
    bump.alloc_slice_copy(&data)
}
/// Demonstrates using bump-allocated collections
pub fn bump_collections() -> Vec<i32> {
    let bump = Bump::new();

    // Create a bump-allocated vector
    let mut vec = BumpVec::new_in(&bump);
    vec.push(1);
    vec.push(2);
    vec.push(3);

    // Convert to standard Vec for return
    vec.iter().copied().collect()
}
pub fn build_ast<'a>(bump: &'a Bump) -> &'a Expr<'a> {
    // Build expression: (2 + 3) * 4
    let two = bump.alloc(Expr::Number(2));
    let three = bump.alloc(Expr::Number(3));
    let four = bump.alloc(Expr::Number(4));

    let add = bump.alloc(Expr::Add(two, three));
    bump.alloc(Expr::Multiply(add, four))
}
/// Evaluates an AST expression
pub fn eval_expr(expr: &Expr) -> i64 {
    match expr {
        Expr::Number(n) => *n,
        Expr::Add(a, b) => eval_expr(a) + eval_expr(b),
        Expr::Multiply(a, b) => eval_expr(a) * eval_expr(b),
    }
}
/// Demonstrates using bump allocation for a simple compiler IR
pub struct Function<'a> {
    pub name: &'a str,
    pub params: BumpVec<'a, &'a str>,
    pub body: BumpVec<'a, Statement<'a>>,
}
pub enum Statement<'a> {
    Let(&'a str, &'a Expr<'a>),
    Return(&'a Expr<'a>),
}
pub fn build_function<'a>(bump: &'a Bump) -> Function<'a> {
    let mut params = BumpVec::new_in(bump);
    let x = bump.alloc_str("x");
    let y = bump.alloc_str("y");
    params.push(&*x);
    params.push(&*y);

    let mut body = BumpVec::new_in(bump);

    // let sum = x + y
    let x = bump.alloc(Expr::Number(10));
    let y = bump.alloc(Expr::Number(20));
    let sum_expr = bump.alloc(Expr::Add(x, y));
    body.push(Statement::Let("sum", sum_expr));

    // return sum * 2
    let two = bump.alloc(Expr::Number(2));
    let result = bump.alloc(Expr::Multiply(sum_expr, two));
    body.push(Statement::Return(result));

    Function {
        name: bump.alloc_str("calculate"),
        params,
        body,
    }
}
/// Shows how to reset and reuse a bump allocator
pub fn reset_and_reuse() -> (Vec<i32>, Vec<i32>) {
    let mut bump = Bump::new();

    // First allocation cycle
    let first = {
        let vec = BumpVec::new_in(&bump);
        let mut vec = vec;
        vec.extend([1, 2, 3].iter().copied());
        vec.iter().copied().collect::<Vec<_>>()
    };

    // Reset the allocator to reclaim all memory
    bump.reset();

    // Second allocation cycle reuses the same memory
    let second = {
        let vec = BumpVec::new_in(&bump);
        let mut vec = vec;
        vec.extend([4, 5, 6].iter().copied());
        vec.iter().copied().collect::<Vec<_>>()
    };

    (first, second)
}
/// Demonstrates scoped allocation for temporary computations
pub fn scoped_allocation() -> i32 {
    let bump = Bump::new();

    // Create a temporary allocation scope

    // Memory is automatically freed when bump goes out of scope
    {
        // Allocate temporary working data
        let mut temps = BumpVec::new_in(&bump);
        for i in 0..100 {
            temps.push(i);
        }

        // Process data
        temps.iter().sum::<i32>()
    }
}
/// Shows using bump allocation with closures
pub fn with_allocator<F, R>(f: F) -> R
where
    F: FnOnce(&Bump) -> R, {
    let bump = Bump::new();
    f(&bump)
}
pub fn closure_example() -> i32 {
    with_allocator(|bump| {
        let numbers = bump.alloc_slice_copy(&[1, 2, 3, 4, 5]);
        numbers.iter().sum()
    })
}
/// Custom type that uses bump allocation internally
pub struct SymbolTable<'a> {
    bump: &'a Bump,
    symbols: BumpVec<'a, &'a str>,
}
impl<'a> SymbolTable<'a> {
    pub fn new(bump: &'a Bump) -> Self {
        Self {
            bump,
            symbols: BumpVec::new_in(bump),
        }
    }

    pub fn intern(&mut self, s: &str) -> usize {
        // Check if symbol already exists
        for (i, &sym) in self.symbols.iter().enumerate() {
            if sym == s {
                return i;
            }
        }

        // Allocate new symbol
        let symbol = self.bump.alloc_str(s);
        let id = self.symbols.len();
        self.symbols.push(symbol);
        id
    }

    pub fn get(&self, id: usize) -> Option<&'a str> {
        self.symbols.get(id).copied()
    }
}
/// Demonstrates using bump allocation for graph structures
pub struct Node<'a> {
    pub value: i32,
    pub children: BumpVec<'a, &'a Node<'a>>,
}
pub fn build_tree<'a>(bump: &'a Bump) -> &'a Node<'a> {
    // Build a simple tree structure
    let leaf1 = bump.alloc(Node {
        value: 1,
        children: BumpVec::new_in(bump),
    });

    let leaf2 = bump.alloc(Node {
        value: 2,
        children: BumpVec::new_in(bump),
    });

    let mut branch_children = BumpVec::new_in(bump);
    branch_children.push(&*leaf1);
    branch_children.push(&*leaf2);

    bump.alloc(Node {
        value: 3,
        children: branch_children,
    })
}
/// Shows statistics about memory usage
pub fn allocation_stats() {
    let mut bump = Bump::new();

    // Allocate some data
    for i in 0..1000 {
        bump.alloc(i);
    }

    // Get allocation statistics
    let allocated = bump.allocated_bytes();
    println!("Allocated: {} bytes", allocated);

    // Reset and check again
    bump.reset();
    let after_reset = bump.allocated_bytes();
    println!("After reset: {} bytes", after_reset);
}
/// Demonstrates bump boxes for single-value allocation
pub fn bump_box_example() -> i32 {
    let bump = Bump::new();

    // Create a bump-allocated box
    let boxed: BumpBox<i32> = BumpBox::new_in(100, &bump);

    // Bump boxes can be dereferenced like regular boxes
    *boxed
}
/// Shows efficient string building with bump allocation
pub struct StringBuilder<'a> {
    bump: &'a Bump,
    parts: BumpVec<'a, &'a str>,
}
impl<'a> StringBuilder<'a> {
    pub fn new(bump: &'a Bump) -> Self {
        Self {
            bump,
            parts: BumpVec::new_in(bump),
        }
    }

    pub fn append(&mut self, s: &str) {
        let part = self.bump.alloc_str(s);
        self.parts.push(part);
    }

    pub fn build(&self) -> String {
        self.parts.iter().flat_map(|s| s.chars()).collect()
    }
}
#[cfg(test)]
mod tests {
    use super::*;

    #[test]
    fn test_basic_allocation() {
        let result = basic_allocation();
        assert_eq!(result, vec![10, 20, 30]);
    }

    #[test]
    fn test_string_allocation() {
        let bump = Bump::new();
        let result = allocate_strings(&bump);
        assert_eq!(result, "Hello, World!");
    }

    #[test]
    fn test_ast_evaluation() {
        let bump = Bump::new();
        let ast = build_ast(&bump);
        assert_eq!(eval_expr(ast), 20); // (2 + 3) * 4 = 20
    }

    #[test]
    fn test_reset_reuse() {
        let (first, second) = reset_and_reuse();
        assert_eq!(first, vec![1, 2, 3]);
        assert_eq!(second, vec![4, 5, 6]);
    }

    #[test]
    fn test_symbol_table() {
        let bump = Bump::new();
        let mut table = SymbolTable::new(&bump);

        let id1 = table.intern("hello");
        let id2 = table.intern("world");
        let id3 = table.intern("hello"); // Should return same ID

        assert_eq!(id1, id3);
        assert_ne!(id1, id2);
        assert_eq!(table.get(id1), Some("hello"));
        assert_eq!(table.get(id2), Some("world"));
    }

    #[test]
    fn test_tree_building() {
        let bump = Bump::new();
        let tree = build_tree(&bump);

        assert_eq!(tree.value, 3);
        assert_eq!(tree.children.len(), 2);
        assert_eq!(tree.children[0].value, 1);
        assert_eq!(tree.children[1].value, 2);
    }

    #[test]
    fn test_string_builder() {
        let bump = Bump::new();
        let mut builder = StringBuilder::new(&bump);

        builder.append("Hello");
        builder.append(", ");
        builder.append("World!");

        assert_eq!(builder.build(), "Hello, World!");
    }
}
/// Shows arena-style allocation for AST nodes
#[derive(Debug, Clone)]
pub enum Expr<'a> {
    Number(i64),
    Add(&'a Expr<'a>, &'a Expr<'a>),
    Multiply(&'a Expr<'a>, &'a Expr<'a>),
}
}
#![allow(unused)]
fn main() {
use std::fmt::Debug;
use bumpalo::Bump;
use bumpalo::boxed::Box as BumpBox;
use bumpalo::collections::Vec as BumpVec;
/// Demonstrates basic bump allocation with simple types
pub fn basic_allocation() -> Vec<i32> {
    let bump = Bump::new();

    // Allocate individual values
    let x = bump.alloc(10);
    let y = bump.alloc(20);
    let z = bump.alloc(30);

    // Values are valid for the lifetime of the bump allocator
    vec![*x, *y, *z]
}
/// Shows how to allocate strings in the bump allocator
pub fn allocate_strings(bump: &Bump) -> &str {
    // Allocate a string slice
    let hello = bump.alloc_str("Hello, ");
    let world = bump.alloc_str("World!");

    // Concatenate using bump allocation

    (bump.alloc_str(&format!("{}{}", hello, world))) as _
}
/// Allocates slices efficiently in the bump allocator
pub fn allocate_slices(bump: &Bump) -> &[i32] {
    // Allocate a slice from a vector
    let data = vec![1, 2, 3, 4, 5];
    bump.alloc_slice_copy(&data)
}
/// Demonstrates using bump-allocated collections
pub fn bump_collections() -> Vec<i32> {
    let bump = Bump::new();

    // Create a bump-allocated vector
    let mut vec = BumpVec::new_in(&bump);
    vec.push(1);
    vec.push(2);
    vec.push(3);

    // Convert to standard Vec for return
    vec.iter().copied().collect()
}
/// Shows arena-style allocation for AST nodes
#[derive(Debug, Clone)]
pub enum Expr<'a> {
    Number(i64),
    Add(&'a Expr<'a>, &'a Expr<'a>),
    Multiply(&'a Expr<'a>, &'a Expr<'a>),
}
/// Evaluates an AST expression
pub fn eval_expr(expr: &Expr) -> i64 {
    match expr {
        Expr::Number(n) => *n,
        Expr::Add(a, b) => eval_expr(a) + eval_expr(b),
        Expr::Multiply(a, b) => eval_expr(a) * eval_expr(b),
    }
}
/// Demonstrates using bump allocation for a simple compiler IR
pub struct Function<'a> {
    pub name: &'a str,
    pub params: BumpVec<'a, &'a str>,
    pub body: BumpVec<'a, Statement<'a>>,
}
pub enum Statement<'a> {
    Let(&'a str, &'a Expr<'a>),
    Return(&'a Expr<'a>),
}
pub fn build_function<'a>(bump: &'a Bump) -> Function<'a> {
    let mut params = BumpVec::new_in(bump);
    let x = bump.alloc_str("x");
    let y = bump.alloc_str("y");
    params.push(&*x);
    params.push(&*y);

    let mut body = BumpVec::new_in(bump);

    // let sum = x + y
    let x = bump.alloc(Expr::Number(10));
    let y = bump.alloc(Expr::Number(20));
    let sum_expr = bump.alloc(Expr::Add(x, y));
    body.push(Statement::Let("sum", sum_expr));

    // return sum * 2
    let two = bump.alloc(Expr::Number(2));
    let result = bump.alloc(Expr::Multiply(sum_expr, two));
    body.push(Statement::Return(result));

    Function {
        name: bump.alloc_str("calculate"),
        params,
        body,
    }
}
/// Shows how to reset and reuse a bump allocator
pub fn reset_and_reuse() -> (Vec<i32>, Vec<i32>) {
    let mut bump = Bump::new();

    // First allocation cycle
    let first = {
        let vec = BumpVec::new_in(&bump);
        let mut vec = vec;
        vec.extend([1, 2, 3].iter().copied());
        vec.iter().copied().collect::<Vec<_>>()
    };

    // Reset the allocator to reclaim all memory
    bump.reset();

    // Second allocation cycle reuses the same memory
    let second = {
        let vec = BumpVec::new_in(&bump);
        let mut vec = vec;
        vec.extend([4, 5, 6].iter().copied());
        vec.iter().copied().collect::<Vec<_>>()
    };

    (first, second)
}
/// Demonstrates scoped allocation for temporary computations
pub fn scoped_allocation() -> i32 {
    let bump = Bump::new();

    // Create a temporary allocation scope

    // Memory is automatically freed when bump goes out of scope
    {
        // Allocate temporary working data
        let mut temps = BumpVec::new_in(&bump);
        for i in 0..100 {
            temps.push(i);
        }

        // Process data
        temps.iter().sum::<i32>()
    }
}
/// Shows using bump allocation with closures
pub fn with_allocator<F, R>(f: F) -> R
where
    F: FnOnce(&Bump) -> R, {
    let bump = Bump::new();
    f(&bump)
}
pub fn closure_example() -> i32 {
    with_allocator(|bump| {
        let numbers = bump.alloc_slice_copy(&[1, 2, 3, 4, 5]);
        numbers.iter().sum()
    })
}
/// Custom type that uses bump allocation internally
pub struct SymbolTable<'a> {
    bump: &'a Bump,
    symbols: BumpVec<'a, &'a str>,
}
impl<'a> SymbolTable<'a> {
    pub fn new(bump: &'a Bump) -> Self {
        Self {
            bump,
            symbols: BumpVec::new_in(bump),
        }
    }

    pub fn intern(&mut self, s: &str) -> usize {
        // Check if symbol already exists
        for (i, &sym) in self.symbols.iter().enumerate() {
            if sym == s {
                return i;
            }
        }

        // Allocate new symbol
        let symbol = self.bump.alloc_str(s);
        let id = self.symbols.len();
        self.symbols.push(symbol);
        id
    }

    pub fn get(&self, id: usize) -> Option<&'a str> {
        self.symbols.get(id).copied()
    }
}
/// Demonstrates using bump allocation for graph structures
pub struct Node<'a> {
    pub value: i32,
    pub children: BumpVec<'a, &'a Node<'a>>,
}
pub fn build_tree<'a>(bump: &'a Bump) -> &'a Node<'a> {
    // Build a simple tree structure
    let leaf1 = bump.alloc(Node {
        value: 1,
        children: BumpVec::new_in(bump),
    });

    let leaf2 = bump.alloc(Node {
        value: 2,
        children: BumpVec::new_in(bump),
    });

    let mut branch_children = BumpVec::new_in(bump);
    branch_children.push(&*leaf1);
    branch_children.push(&*leaf2);

    bump.alloc(Node {
        value: 3,
        children: branch_children,
    })
}
/// Shows statistics about memory usage
pub fn allocation_stats() {
    let mut bump = Bump::new();

    // Allocate some data
    for i in 0..1000 {
        bump.alloc(i);
    }

    // Get allocation statistics
    let allocated = bump.allocated_bytes();
    println!("Allocated: {} bytes", allocated);

    // Reset and check again
    bump.reset();
    let after_reset = bump.allocated_bytes();
    println!("After reset: {} bytes", after_reset);
}
/// Demonstrates bump boxes for single-value allocation
pub fn bump_box_example() -> i32 {
    let bump = Bump::new();

    // Create a bump-allocated box
    let boxed: BumpBox<i32> = BumpBox::new_in(100, &bump);

    // Bump boxes can be dereferenced like regular boxes
    *boxed
}
/// Shows efficient string building with bump allocation
pub struct StringBuilder<'a> {
    bump: &'a Bump,
    parts: BumpVec<'a, &'a str>,
}
impl<'a> StringBuilder<'a> {
    pub fn new(bump: &'a Bump) -> Self {
        Self {
            bump,
            parts: BumpVec::new_in(bump),
        }
    }

    pub fn append(&mut self, s: &str) {
        let part = self.bump.alloc_str(s);
        self.parts.push(part);
    }

    pub fn build(&self) -> String {
        self.parts.iter().flat_map(|s| s.chars()).collect()
    }
}
#[cfg(test)]
mod tests {
    use super::*;

    #[test]
    fn test_basic_allocation() {
        let result = basic_allocation();
        assert_eq!(result, vec![10, 20, 30]);
    }

    #[test]
    fn test_string_allocation() {
        let bump = Bump::new();
        let result = allocate_strings(&bump);
        assert_eq!(result, "Hello, World!");
    }

    #[test]
    fn test_ast_evaluation() {
        let bump = Bump::new();
        let ast = build_ast(&bump);
        assert_eq!(eval_expr(ast), 20); // (2 + 3) * 4 = 20
    }

    #[test]
    fn test_reset_reuse() {
        let (first, second) = reset_and_reuse();
        assert_eq!(first, vec![1, 2, 3]);
        assert_eq!(second, vec![4, 5, 6]);
    }

    #[test]
    fn test_symbol_table() {
        let bump = Bump::new();
        let mut table = SymbolTable::new(&bump);

        let id1 = table.intern("hello");
        let id2 = table.intern("world");
        let id3 = table.intern("hello"); // Should return same ID

        assert_eq!(id1, id3);
        assert_ne!(id1, id2);
        assert_eq!(table.get(id1), Some("hello"));
        assert_eq!(table.get(id2), Some("world"));
    }

    #[test]
    fn test_tree_building() {
        let bump = Bump::new();
        let tree = build_tree(&bump);

        assert_eq!(tree.value, 3);
        assert_eq!(tree.children.len(), 2);
        assert_eq!(tree.children[0].value, 1);
        assert_eq!(tree.children[1].value, 2);
    }

    #[test]
    fn test_string_builder() {
        let bump = Bump::new();
        let mut builder = StringBuilder::new(&bump);

        builder.append("Hello");
        builder.append(", ");
        builder.append("World!");

        assert_eq!(builder.build(), "Hello, World!");
    }
}
pub fn build_ast<'a>(bump: &'a Bump) -> &'a Expr<'a> {
    // Build expression: (2 + 3) * 4
    let two = bump.alloc(Expr::Number(2));
    let three = bump.alloc(Expr::Number(3));
    let four = bump.alloc(Expr::Number(4));

    let add = bump.alloc(Expr::Add(two, three));
    bump.alloc(Expr::Multiply(add, four))
}
}
#![allow(unused)]
fn main() {
use std::fmt::Debug;
use bumpalo::Bump;
use bumpalo::boxed::Box as BumpBox;
use bumpalo::collections::Vec as BumpVec;
/// Demonstrates basic bump allocation with simple types
pub fn basic_allocation() -> Vec<i32> {
    let bump = Bump::new();

    // Allocate individual values
    let x = bump.alloc(10);
    let y = bump.alloc(20);
    let z = bump.alloc(30);

    // Values are valid for the lifetime of the bump allocator
    vec![*x, *y, *z]
}
/// Shows how to allocate strings in the bump allocator
pub fn allocate_strings(bump: &Bump) -> &str {
    // Allocate a string slice
    let hello = bump.alloc_str("Hello, ");
    let world = bump.alloc_str("World!");

    // Concatenate using bump allocation

    (bump.alloc_str(&format!("{}{}", hello, world))) as _
}
/// Allocates slices efficiently in the bump allocator
pub fn allocate_slices(bump: &Bump) -> &[i32] {
    // Allocate a slice from a vector
    let data = vec![1, 2, 3, 4, 5];
    bump.alloc_slice_copy(&data)
}
/// Demonstrates using bump-allocated collections
pub fn bump_collections() -> Vec<i32> {
    let bump = Bump::new();

    // Create a bump-allocated vector
    let mut vec = BumpVec::new_in(&bump);
    vec.push(1);
    vec.push(2);
    vec.push(3);

    // Convert to standard Vec for return
    vec.iter().copied().collect()
}
/// Shows arena-style allocation for AST nodes
#[derive(Debug, Clone)]
pub enum Expr<'a> {
    Number(i64),
    Add(&'a Expr<'a>, &'a Expr<'a>),
    Multiply(&'a Expr<'a>, &'a Expr<'a>),
}
pub fn build_ast<'a>(bump: &'a Bump) -> &'a Expr<'a> {
    // Build expression: (2 + 3) * 4
    let two = bump.alloc(Expr::Number(2));
    let three = bump.alloc(Expr::Number(3));
    let four = bump.alloc(Expr::Number(4));

    let add = bump.alloc(Expr::Add(two, three));
    bump.alloc(Expr::Multiply(add, four))
}
/// Demonstrates using bump allocation for a simple compiler IR
pub struct Function<'a> {
    pub name: &'a str,
    pub params: BumpVec<'a, &'a str>,
    pub body: BumpVec<'a, Statement<'a>>,
}
pub enum Statement<'a> {
    Let(&'a str, &'a Expr<'a>),
    Return(&'a Expr<'a>),
}
pub fn build_function<'a>(bump: &'a Bump) -> Function<'a> {
    let mut params = BumpVec::new_in(bump);
    let x = bump.alloc_str("x");
    let y = bump.alloc_str("y");
    params.push(&*x);
    params.push(&*y);

    let mut body = BumpVec::new_in(bump);

    // let sum = x + y
    let x = bump.alloc(Expr::Number(10));
    let y = bump.alloc(Expr::Number(20));
    let sum_expr = bump.alloc(Expr::Add(x, y));
    body.push(Statement::Let("sum", sum_expr));

    // return sum * 2
    let two = bump.alloc(Expr::Number(2));
    let result = bump.alloc(Expr::Multiply(sum_expr, two));
    body.push(Statement::Return(result));

    Function {
        name: bump.alloc_str("calculate"),
        params,
        body,
    }
}
/// Shows how to reset and reuse a bump allocator
pub fn reset_and_reuse() -> (Vec<i32>, Vec<i32>) {
    let mut bump = Bump::new();

    // First allocation cycle
    let first = {
        let vec = BumpVec::new_in(&bump);
        let mut vec = vec;
        vec.extend([1, 2, 3].iter().copied());
        vec.iter().copied().collect::<Vec<_>>()
    };

    // Reset the allocator to reclaim all memory
    bump.reset();

    // Second allocation cycle reuses the same memory
    let second = {
        let vec = BumpVec::new_in(&bump);
        let mut vec = vec;
        vec.extend([4, 5, 6].iter().copied());
        vec.iter().copied().collect::<Vec<_>>()
    };

    (first, second)
}
/// Demonstrates scoped allocation for temporary computations
pub fn scoped_allocation() -> i32 {
    let bump = Bump::new();

    // Create a temporary allocation scope

    // Memory is automatically freed when bump goes out of scope
    {
        // Allocate temporary working data
        let mut temps = BumpVec::new_in(&bump);
        for i in 0..100 {
            temps.push(i);
        }

        // Process data
        temps.iter().sum::<i32>()
    }
}
/// Shows using bump allocation with closures
pub fn with_allocator<F, R>(f: F) -> R
where
    F: FnOnce(&Bump) -> R, {
    let bump = Bump::new();
    f(&bump)
}
pub fn closure_example() -> i32 {
    with_allocator(|bump| {
        let numbers = bump.alloc_slice_copy(&[1, 2, 3, 4, 5]);
        numbers.iter().sum()
    })
}
/// Custom type that uses bump allocation internally
pub struct SymbolTable<'a> {
    bump: &'a Bump,
    symbols: BumpVec<'a, &'a str>,
}
impl<'a> SymbolTable<'a> {
    pub fn new(bump: &'a Bump) -> Self {
        Self {
            bump,
            symbols: BumpVec::new_in(bump),
        }
    }

    pub fn intern(&mut self, s: &str) -> usize {
        // Check if symbol already exists
        for (i, &sym) in self.symbols.iter().enumerate() {
            if sym == s {
                return i;
            }
        }

        // Allocate new symbol
        let symbol = self.bump.alloc_str(s);
        let id = self.symbols.len();
        self.symbols.push(symbol);
        id
    }

    pub fn get(&self, id: usize) -> Option<&'a str> {
        self.symbols.get(id).copied()
    }
}
/// Demonstrates using bump allocation for graph structures
pub struct Node<'a> {
    pub value: i32,
    pub children: BumpVec<'a, &'a Node<'a>>,
}
pub fn build_tree<'a>(bump: &'a Bump) -> &'a Node<'a> {
    // Build a simple tree structure
    let leaf1 = bump.alloc(Node {
        value: 1,
        children: BumpVec::new_in(bump),
    });

    let leaf2 = bump.alloc(Node {
        value: 2,
        children: BumpVec::new_in(bump),
    });

    let mut branch_children = BumpVec::new_in(bump);
    branch_children.push(&*leaf1);
    branch_children.push(&*leaf2);

    bump.alloc(Node {
        value: 3,
        children: branch_children,
    })
}
/// Shows statistics about memory usage
pub fn allocation_stats() {
    let mut bump = Bump::new();

    // Allocate some data
    for i in 0..1000 {
        bump.alloc(i);
    }

    // Get allocation statistics
    let allocated = bump.allocated_bytes();
    println!("Allocated: {} bytes", allocated);

    // Reset and check again
    bump.reset();
    let after_reset = bump.allocated_bytes();
    println!("After reset: {} bytes", after_reset);
}
/// Demonstrates bump boxes for single-value allocation
pub fn bump_box_example() -> i32 {
    let bump = Bump::new();

    // Create a bump-allocated box
    let boxed: BumpBox<i32> = BumpBox::new_in(100, &bump);

    // Bump boxes can be dereferenced like regular boxes
    *boxed
}
/// Shows efficient string building with bump allocation
pub struct StringBuilder<'a> {
    bump: &'a Bump,
    parts: BumpVec<'a, &'a str>,
}
impl<'a> StringBuilder<'a> {
    pub fn new(bump: &'a Bump) -> Self {
        Self {
            bump,
            parts: BumpVec::new_in(bump),
        }
    }

    pub fn append(&mut self, s: &str) {
        let part = self.bump.alloc_str(s);
        self.parts.push(part);
    }

    pub fn build(&self) -> String {
        self.parts.iter().flat_map(|s| s.chars()).collect()
    }
}
#[cfg(test)]
mod tests {
    use super::*;

    #[test]
    fn test_basic_allocation() {
        let result = basic_allocation();
        assert_eq!(result, vec![10, 20, 30]);
    }

    #[test]
    fn test_string_allocation() {
        let bump = Bump::new();
        let result = allocate_strings(&bump);
        assert_eq!(result, "Hello, World!");
    }

    #[test]
    fn test_ast_evaluation() {
        let bump = Bump::new();
        let ast = build_ast(&bump);
        assert_eq!(eval_expr(ast), 20); // (2 + 3) * 4 = 20
    }

    #[test]
    fn test_reset_reuse() {
        let (first, second) = reset_and_reuse();
        assert_eq!(first, vec![1, 2, 3]);
        assert_eq!(second, vec![4, 5, 6]);
    }

    #[test]
    fn test_symbol_table() {
        let bump = Bump::new();
        let mut table = SymbolTable::new(&bump);

        let id1 = table.intern("hello");
        let id2 = table.intern("world");
        let id3 = table.intern("hello"); // Should return same ID

        assert_eq!(id1, id3);
        assert_ne!(id1, id2);
        assert_eq!(table.get(id1), Some("hello"));
        assert_eq!(table.get(id2), Some("world"));
    }

    #[test]
    fn test_tree_building() {
        let bump = Bump::new();
        let tree = build_tree(&bump);

        assert_eq!(tree.value, 3);
        assert_eq!(tree.children.len(), 2);
        assert_eq!(tree.children[0].value, 1);
        assert_eq!(tree.children[1].value, 2);
    }

    #[test]
    fn test_string_builder() {
        let bump = Bump::new();
        let mut builder = StringBuilder::new(&bump);

        builder.append("Hello");
        builder.append(", ");
        builder.append("World!");

        assert_eq!(builder.build(), "Hello, World!");
    }
}
/// Evaluates an AST expression
pub fn eval_expr(expr: &Expr) -> i64 {
    match expr {
        Expr::Number(n) => *n,
        Expr::Add(a, b) => eval_expr(a) + eval_expr(b),
        Expr::Multiply(a, b) => eval_expr(a) * eval_expr(b),
    }
}
}

The entire AST is allocated in a single contiguous memory region, providing excellent cache locality during traversal. Nodes can freely reference each other without worrying about ownership or lifetimes beyond the arena’s lifetime.

Compiler IR Structures

More complex compiler structures benefit from arena allocation:

#![allow(unused)]
fn main() {
use std::fmt::Debug;
use bumpalo::Bump;
use bumpalo::boxed::Box as BumpBox;
use bumpalo::collections::Vec as BumpVec;
/// Demonstrates basic bump allocation with simple types
pub fn basic_allocation() -> Vec<i32> {
    let bump = Bump::new();

    // Allocate individual values
    let x = bump.alloc(10);
    let y = bump.alloc(20);
    let z = bump.alloc(30);

    // Values are valid for the lifetime of the bump allocator
    vec![*x, *y, *z]
}
/// Shows how to allocate strings in the bump allocator
pub fn allocate_strings(bump: &Bump) -> &str {
    // Allocate a string slice
    let hello = bump.alloc_str("Hello, ");
    let world = bump.alloc_str("World!");

    // Concatenate using bump allocation

    (bump.alloc_str(&format!("{}{}", hello, world))) as _
}
/// Allocates slices efficiently in the bump allocator
pub fn allocate_slices(bump: &Bump) -> &[i32] {
    // Allocate a slice from a vector
    let data = vec![1, 2, 3, 4, 5];
    bump.alloc_slice_copy(&data)
}
/// Demonstrates using bump-allocated collections
pub fn bump_collections() -> Vec<i32> {
    let bump = Bump::new();

    // Create a bump-allocated vector
    let mut vec = BumpVec::new_in(&bump);
    vec.push(1);
    vec.push(2);
    vec.push(3);

    // Convert to standard Vec for return
    vec.iter().copied().collect()
}
/// Shows arena-style allocation for AST nodes
#[derive(Debug, Clone)]
pub enum Expr<'a> {
    Number(i64),
    Add(&'a Expr<'a>, &'a Expr<'a>),
    Multiply(&'a Expr<'a>, &'a Expr<'a>),
}
pub fn build_ast<'a>(bump: &'a Bump) -> &'a Expr<'a> {
    // Build expression: (2 + 3) * 4
    let two = bump.alloc(Expr::Number(2));
    let three = bump.alloc(Expr::Number(3));
    let four = bump.alloc(Expr::Number(4));

    let add = bump.alloc(Expr::Add(two, three));
    bump.alloc(Expr::Multiply(add, four))
}
/// Evaluates an AST expression
pub fn eval_expr(expr: &Expr) -> i64 {
    match expr {
        Expr::Number(n) => *n,
        Expr::Add(a, b) => eval_expr(a) + eval_expr(b),
        Expr::Multiply(a, b) => eval_expr(a) * eval_expr(b),
    }
}
pub enum Statement<'a> {
    Let(&'a str, &'a Expr<'a>),
    Return(&'a Expr<'a>),
}
pub fn build_function<'a>(bump: &'a Bump) -> Function<'a> {
    let mut params = BumpVec::new_in(bump);
    let x = bump.alloc_str("x");
    let y = bump.alloc_str("y");
    params.push(&*x);
    params.push(&*y);

    let mut body = BumpVec::new_in(bump);

    // let sum = x + y
    let x = bump.alloc(Expr::Number(10));
    let y = bump.alloc(Expr::Number(20));
    let sum_expr = bump.alloc(Expr::Add(x, y));
    body.push(Statement::Let("sum", sum_expr));

    // return sum * 2
    let two = bump.alloc(Expr::Number(2));
    let result = bump.alloc(Expr::Multiply(sum_expr, two));
    body.push(Statement::Return(result));

    Function {
        name: bump.alloc_str("calculate"),
        params,
        body,
    }
}
/// Shows how to reset and reuse a bump allocator
pub fn reset_and_reuse() -> (Vec<i32>, Vec<i32>) {
    let mut bump = Bump::new();

    // First allocation cycle
    let first = {
        let vec = BumpVec::new_in(&bump);
        let mut vec = vec;
        vec.extend([1, 2, 3].iter().copied());
        vec.iter().copied().collect::<Vec<_>>()
    };

    // Reset the allocator to reclaim all memory
    bump.reset();

    // Second allocation cycle reuses the same memory
    let second = {
        let vec = BumpVec::new_in(&bump);
        let mut vec = vec;
        vec.extend([4, 5, 6].iter().copied());
        vec.iter().copied().collect::<Vec<_>>()
    };

    (first, second)
}
/// Demonstrates scoped allocation for temporary computations
pub fn scoped_allocation() -> i32 {
    let bump = Bump::new();

    // Create a temporary allocation scope

    // Memory is automatically freed when bump goes out of scope
    {
        // Allocate temporary working data
        let mut temps = BumpVec::new_in(&bump);
        for i in 0..100 {
            temps.push(i);
        }

        // Process data
        temps.iter().sum::<i32>()
    }
}
/// Shows using bump allocation with closures
pub fn with_allocator<F, R>(f: F) -> R
where
    F: FnOnce(&Bump) -> R, {
    let bump = Bump::new();
    f(&bump)
}
pub fn closure_example() -> i32 {
    with_allocator(|bump| {
        let numbers = bump.alloc_slice_copy(&[1, 2, 3, 4, 5]);
        numbers.iter().sum()
    })
}
/// Custom type that uses bump allocation internally
pub struct SymbolTable<'a> {
    bump: &'a Bump,
    symbols: BumpVec<'a, &'a str>,
}
impl<'a> SymbolTable<'a> {
    pub fn new(bump: &'a Bump) -> Self {
        Self {
            bump,
            symbols: BumpVec::new_in(bump),
        }
    }

    pub fn intern(&mut self, s: &str) -> usize {
        // Check if symbol already exists
        for (i, &sym) in self.symbols.iter().enumerate() {
            if sym == s {
                return i;
            }
        }

        // Allocate new symbol
        let symbol = self.bump.alloc_str(s);
        let id = self.symbols.len();
        self.symbols.push(symbol);
        id
    }

    pub fn get(&self, id: usize) -> Option<&'a str> {
        self.symbols.get(id).copied()
    }
}
/// Demonstrates using bump allocation for graph structures
pub struct Node<'a> {
    pub value: i32,
    pub children: BumpVec<'a, &'a Node<'a>>,
}
pub fn build_tree<'a>(bump: &'a Bump) -> &'a Node<'a> {
    // Build a simple tree structure
    let leaf1 = bump.alloc(Node {
        value: 1,
        children: BumpVec::new_in(bump),
    });

    let leaf2 = bump.alloc(Node {
        value: 2,
        children: BumpVec::new_in(bump),
    });

    let mut branch_children = BumpVec::new_in(bump);
    branch_children.push(&*leaf1);
    branch_children.push(&*leaf2);

    bump.alloc(Node {
        value: 3,
        children: branch_children,
    })
}
/// Shows statistics about memory usage
pub fn allocation_stats() {
    let mut bump = Bump::new();

    // Allocate some data
    for i in 0..1000 {
        bump.alloc(i);
    }

    // Get allocation statistics
    let allocated = bump.allocated_bytes();
    println!("Allocated: {} bytes", allocated);

    // Reset and check again
    bump.reset();
    let after_reset = bump.allocated_bytes();
    println!("After reset: {} bytes", after_reset);
}
/// Demonstrates bump boxes for single-value allocation
pub fn bump_box_example() -> i32 {
    let bump = Bump::new();

    // Create a bump-allocated box
    let boxed: BumpBox<i32> = BumpBox::new_in(100, &bump);

    // Bump boxes can be dereferenced like regular boxes
    *boxed
}
/// Shows efficient string building with bump allocation
pub struct StringBuilder<'a> {
    bump: &'a Bump,
    parts: BumpVec<'a, &'a str>,
}
impl<'a> StringBuilder<'a> {
    pub fn new(bump: &'a Bump) -> Self {
        Self {
            bump,
            parts: BumpVec::new_in(bump),
        }
    }

    pub fn append(&mut self, s: &str) {
        let part = self.bump.alloc_str(s);
        self.parts.push(part);
    }

    pub fn build(&self) -> String {
        self.parts.iter().flat_map(|s| s.chars()).collect()
    }
}
#[cfg(test)]
mod tests {
    use super::*;

    #[test]
    fn test_basic_allocation() {
        let result = basic_allocation();
        assert_eq!(result, vec![10, 20, 30]);
    }

    #[test]
    fn test_string_allocation() {
        let bump = Bump::new();
        let result = allocate_strings(&bump);
        assert_eq!(result, "Hello, World!");
    }

    #[test]
    fn test_ast_evaluation() {
        let bump = Bump::new();
        let ast = build_ast(&bump);
        assert_eq!(eval_expr(ast), 20); // (2 + 3) * 4 = 20
    }

    #[test]
    fn test_reset_reuse() {
        let (first, second) = reset_and_reuse();
        assert_eq!(first, vec![1, 2, 3]);
        assert_eq!(second, vec![4, 5, 6]);
    }

    #[test]
    fn test_symbol_table() {
        let bump = Bump::new();
        let mut table = SymbolTable::new(&bump);

        let id1 = table.intern("hello");
        let id2 = table.intern("world");
        let id3 = table.intern("hello"); // Should return same ID

        assert_eq!(id1, id3);
        assert_ne!(id1, id2);
        assert_eq!(table.get(id1), Some("hello"));
        assert_eq!(table.get(id2), Some("world"));
    }

    #[test]
    fn test_tree_building() {
        let bump = Bump::new();
        let tree = build_tree(&bump);

        assert_eq!(tree.value, 3);
        assert_eq!(tree.children.len(), 2);
        assert_eq!(tree.children[0].value, 1);
        assert_eq!(tree.children[1].value, 2);
    }

    #[test]
    fn test_string_builder() {
        let bump = Bump::new();
        let mut builder = StringBuilder::new(&bump);

        builder.append("Hello");
        builder.append(", ");
        builder.append("World!");

        assert_eq!(builder.build(), "Hello, World!");
    }
}
/// Demonstrates using bump allocation for a simple compiler IR
pub struct Function<'a> {
    pub name: &'a str,
    pub params: BumpVec<'a, &'a str>,
    pub body: BumpVec<'a, Statement<'a>>,
}
}
#![allow(unused)]
fn main() {
use std::fmt::Debug;
use bumpalo::Bump;
use bumpalo::boxed::Box as BumpBox;
use bumpalo::collections::Vec as BumpVec;
/// Demonstrates basic bump allocation with simple types
pub fn basic_allocation() -> Vec<i32> {
    let bump = Bump::new();

    // Allocate individual values
    let x = bump.alloc(10);
    let y = bump.alloc(20);
    let z = bump.alloc(30);

    // Values are valid for the lifetime of the bump allocator
    vec![*x, *y, *z]
}
/// Shows how to allocate strings in the bump allocator
pub fn allocate_strings(bump: &Bump) -> &str {
    // Allocate a string slice
    let hello = bump.alloc_str("Hello, ");
    let world = bump.alloc_str("World!");

    // Concatenate using bump allocation

    (bump.alloc_str(&format!("{}{}", hello, world))) as _
}
/// Allocates slices efficiently in the bump allocator
pub fn allocate_slices(bump: &Bump) -> &[i32] {
    // Allocate a slice from a vector
    let data = vec![1, 2, 3, 4, 5];
    bump.alloc_slice_copy(&data)
}
/// Demonstrates using bump-allocated collections
pub fn bump_collections() -> Vec<i32> {
    let bump = Bump::new();

    // Create a bump-allocated vector
    let mut vec = BumpVec::new_in(&bump);
    vec.push(1);
    vec.push(2);
    vec.push(3);

    // Convert to standard Vec for return
    vec.iter().copied().collect()
}
/// Shows arena-style allocation for AST nodes
#[derive(Debug, Clone)]
pub enum Expr<'a> {
    Number(i64),
    Add(&'a Expr<'a>, &'a Expr<'a>),
    Multiply(&'a Expr<'a>, &'a Expr<'a>),
}
pub fn build_ast<'a>(bump: &'a Bump) -> &'a Expr<'a> {
    // Build expression: (2 + 3) * 4
    let two = bump.alloc(Expr::Number(2));
    let three = bump.alloc(Expr::Number(3));
    let four = bump.alloc(Expr::Number(4));

    let add = bump.alloc(Expr::Add(two, three));
    bump.alloc(Expr::Multiply(add, four))
}
/// Evaluates an AST expression
pub fn eval_expr(expr: &Expr) -> i64 {
    match expr {
        Expr::Number(n) => *n,
        Expr::Add(a, b) => eval_expr(a) + eval_expr(b),
        Expr::Multiply(a, b) => eval_expr(a) * eval_expr(b),
    }
}
/// Demonstrates using bump allocation for a simple compiler IR
pub struct Function<'a> {
    pub name: &'a str,
    pub params: BumpVec<'a, &'a str>,
    pub body: BumpVec<'a, Statement<'a>>,
}
pub fn build_function<'a>(bump: &'a Bump) -> Function<'a> {
    let mut params = BumpVec::new_in(bump);
    let x = bump.alloc_str("x");
    let y = bump.alloc_str("y");
    params.push(&*x);
    params.push(&*y);

    let mut body = BumpVec::new_in(bump);

    // let sum = x + y
    let x = bump.alloc(Expr::Number(10));
    let y = bump.alloc(Expr::Number(20));
    let sum_expr = bump.alloc(Expr::Add(x, y));
    body.push(Statement::Let("sum", sum_expr));

    // return sum * 2
    let two = bump.alloc(Expr::Number(2));
    let result = bump.alloc(Expr::Multiply(sum_expr, two));
    body.push(Statement::Return(result));

    Function {
        name: bump.alloc_str("calculate"),
        params,
        body,
    }
}
/// Shows how to reset and reuse a bump allocator
pub fn reset_and_reuse() -> (Vec<i32>, Vec<i32>) {
    let mut bump = Bump::new();

    // First allocation cycle
    let first = {
        let vec = BumpVec::new_in(&bump);
        let mut vec = vec;
        vec.extend([1, 2, 3].iter().copied());
        vec.iter().copied().collect::<Vec<_>>()
    };

    // Reset the allocator to reclaim all memory
    bump.reset();

    // Second allocation cycle reuses the same memory
    let second = {
        let vec = BumpVec::new_in(&bump);
        let mut vec = vec;
        vec.extend([4, 5, 6].iter().copied());
        vec.iter().copied().collect::<Vec<_>>()
    };

    (first, second)
}
/// Demonstrates scoped allocation for temporary computations
pub fn scoped_allocation() -> i32 {
    let bump = Bump::new();

    // Create a temporary allocation scope

    // Memory is automatically freed when bump goes out of scope
    {
        // Allocate temporary working data
        let mut temps = BumpVec::new_in(&bump);
        for i in 0..100 {
            temps.push(i);
        }

        // Process data
        temps.iter().sum::<i32>()
    }
}
/// Shows using bump allocation with closures
pub fn with_allocator<F, R>(f: F) -> R
where
    F: FnOnce(&Bump) -> R, {
    let bump = Bump::new();
    f(&bump)
}
pub fn closure_example() -> i32 {
    with_allocator(|bump| {
        let numbers = bump.alloc_slice_copy(&[1, 2, 3, 4, 5]);
        numbers.iter().sum()
    })
}
/// Custom type that uses bump allocation internally
pub struct SymbolTable<'a> {
    bump: &'a Bump,
    symbols: BumpVec<'a, &'a str>,
}
impl<'a> SymbolTable<'a> {
    pub fn new(bump: &'a Bump) -> Self {
        Self {
            bump,
            symbols: BumpVec::new_in(bump),
        }
    }

    pub fn intern(&mut self, s: &str) -> usize {
        // Check if symbol already exists
        for (i, &sym) in self.symbols.iter().enumerate() {
            if sym == s {
                return i;
            }
        }

        // Allocate new symbol
        let symbol = self.bump.alloc_str(s);
        let id = self.symbols.len();
        self.symbols.push(symbol);
        id
    }

    pub fn get(&self, id: usize) -> Option<&'a str> {
        self.symbols.get(id).copied()
    }
}
/// Demonstrates using bump allocation for graph structures
pub struct Node<'a> {
    pub value: i32,
    pub children: BumpVec<'a, &'a Node<'a>>,
}
pub fn build_tree<'a>(bump: &'a Bump) -> &'a Node<'a> {
    // Build a simple tree structure
    let leaf1 = bump.alloc(Node {
        value: 1,
        children: BumpVec::new_in(bump),
    });

    let leaf2 = bump.alloc(Node {
        value: 2,
        children: BumpVec::new_in(bump),
    });

    let mut branch_children = BumpVec::new_in(bump);
    branch_children.push(&*leaf1);
    branch_children.push(&*leaf2);

    bump.alloc(Node {
        value: 3,
        children: branch_children,
    })
}
/// Shows statistics about memory usage
pub fn allocation_stats() {
    let mut bump = Bump::new();

    // Allocate some data
    for i in 0..1000 {
        bump.alloc(i);
    }

    // Get allocation statistics
    let allocated = bump.allocated_bytes();
    println!("Allocated: {} bytes", allocated);

    // Reset and check again
    bump.reset();
    let after_reset = bump.allocated_bytes();
    println!("After reset: {} bytes", after_reset);
}
/// Demonstrates bump boxes for single-value allocation
pub fn bump_box_example() -> i32 {
    let bump = Bump::new();

    // Create a bump-allocated box
    let boxed: BumpBox<i32> = BumpBox::new_in(100, &bump);

    // Bump boxes can be dereferenced like regular boxes
    *boxed
}
/// Shows efficient string building with bump allocation
pub struct StringBuilder<'a> {
    bump: &'a Bump,
    parts: BumpVec<'a, &'a str>,
}
impl<'a> StringBuilder<'a> {
    pub fn new(bump: &'a Bump) -> Self {
        Self {
            bump,
            parts: BumpVec::new_in(bump),
        }
    }

    pub fn append(&mut self, s: &str) {
        let part = self.bump.alloc_str(s);
        self.parts.push(part);
    }

    pub fn build(&self) -> String {
        self.parts.iter().flat_map(|s| s.chars()).collect()
    }
}
#[cfg(test)]
mod tests {
    use super::*;

    #[test]
    fn test_basic_allocation() {
        let result = basic_allocation();
        assert_eq!(result, vec![10, 20, 30]);
    }

    #[test]
    fn test_string_allocation() {
        let bump = Bump::new();
        let result = allocate_strings(&bump);
        assert_eq!(result, "Hello, World!");
    }

    #[test]
    fn test_ast_evaluation() {
        let bump = Bump::new();
        let ast = build_ast(&bump);
        assert_eq!(eval_expr(ast), 20); // (2 + 3) * 4 = 20
    }

    #[test]
    fn test_reset_reuse() {
        let (first, second) = reset_and_reuse();
        assert_eq!(first, vec![1, 2, 3]);
        assert_eq!(second, vec![4, 5, 6]);
    }

    #[test]
    fn test_symbol_table() {
        let bump = Bump::new();
        let mut table = SymbolTable::new(&bump);

        let id1 = table.intern("hello");
        let id2 = table.intern("world");
        let id3 = table.intern("hello"); // Should return same ID

        assert_eq!(id1, id3);
        assert_ne!(id1, id2);
        assert_eq!(table.get(id1), Some("hello"));
        assert_eq!(table.get(id2), Some("world"));
    }

    #[test]
    fn test_tree_building() {
        let bump = Bump::new();
        let tree = build_tree(&bump);

        assert_eq!(tree.value, 3);
        assert_eq!(tree.children.len(), 2);
        assert_eq!(tree.children[0].value, 1);
        assert_eq!(tree.children[1].value, 2);
    }

    #[test]
    fn test_string_builder() {
        let bump = Bump::new();
        let mut builder = StringBuilder::new(&bump);

        builder.append("Hello");
        builder.append(", ");
        builder.append("World!");

        assert_eq!(builder.build(), "Hello, World!");
    }
}
pub enum Statement<'a> {
    Let(&'a str, &'a Expr<'a>),
    Return(&'a Expr<'a>),
}
}
#![allow(unused)]
fn main() {
use std::fmt::Debug;
use bumpalo::Bump;
use bumpalo::boxed::Box as BumpBox;
use bumpalo::collections::Vec as BumpVec;
/// Demonstrates basic bump allocation with simple types
pub fn basic_allocation() -> Vec<i32> {
    let bump = Bump::new();

    // Allocate individual values
    let x = bump.alloc(10);
    let y = bump.alloc(20);
    let z = bump.alloc(30);

    // Values are valid for the lifetime of the bump allocator
    vec![*x, *y, *z]
}
/// Shows how to allocate strings in the bump allocator
pub fn allocate_strings(bump: &Bump) -> &str {
    // Allocate a string slice
    let hello = bump.alloc_str("Hello, ");
    let world = bump.alloc_str("World!");

    // Concatenate using bump allocation

    (bump.alloc_str(&format!("{}{}", hello, world))) as _
}
/// Allocates slices efficiently in the bump allocator
pub fn allocate_slices(bump: &Bump) -> &[i32] {
    // Allocate a slice from a vector
    let data = vec![1, 2, 3, 4, 5];
    bump.alloc_slice_copy(&data)
}
/// Demonstrates using bump-allocated collections
pub fn bump_collections() -> Vec<i32> {
    let bump = Bump::new();

    // Create a bump-allocated vector
    let mut vec = BumpVec::new_in(&bump);
    vec.push(1);
    vec.push(2);
    vec.push(3);

    // Convert to standard Vec for return
    vec.iter().copied().collect()
}
/// Shows arena-style allocation for AST nodes
#[derive(Debug, Clone)]
pub enum Expr<'a> {
    Number(i64),
    Add(&'a Expr<'a>, &'a Expr<'a>),
    Multiply(&'a Expr<'a>, &'a Expr<'a>),
}
pub fn build_ast<'a>(bump: &'a Bump) -> &'a Expr<'a> {
    // Build expression: (2 + 3) * 4
    let two = bump.alloc(Expr::Number(2));
    let three = bump.alloc(Expr::Number(3));
    let four = bump.alloc(Expr::Number(4));

    let add = bump.alloc(Expr::Add(two, three));
    bump.alloc(Expr::Multiply(add, four))
}
/// Evaluates an AST expression
pub fn eval_expr(expr: &Expr) -> i64 {
    match expr {
        Expr::Number(n) => *n,
        Expr::Add(a, b) => eval_expr(a) + eval_expr(b),
        Expr::Multiply(a, b) => eval_expr(a) * eval_expr(b),
    }
}
/// Demonstrates using bump allocation for a simple compiler IR
pub struct Function<'a> {
    pub name: &'a str,
    pub params: BumpVec<'a, &'a str>,
    pub body: BumpVec<'a, Statement<'a>>,
}
pub enum Statement<'a> {
    Let(&'a str, &'a Expr<'a>),
    Return(&'a Expr<'a>),
}
/// Shows how to reset and reuse a bump allocator
pub fn reset_and_reuse() -> (Vec<i32>, Vec<i32>) {
    let mut bump = Bump::new();

    // First allocation cycle
    let first = {
        let vec = BumpVec::new_in(&bump);
        let mut vec = vec;
        vec.extend([1, 2, 3].iter().copied());
        vec.iter().copied().collect::<Vec<_>>()
    };

    // Reset the allocator to reclaim all memory
    bump.reset();

    // Second allocation cycle reuses the same memory
    let second = {
        let vec = BumpVec::new_in(&bump);
        let mut vec = vec;
        vec.extend([4, 5, 6].iter().copied());
        vec.iter().copied().collect::<Vec<_>>()
    };

    (first, second)
}
/// Demonstrates scoped allocation for temporary computations
pub fn scoped_allocation() -> i32 {
    let bump = Bump::new();

    // Create a temporary allocation scope

    // Memory is automatically freed when bump goes out of scope
    {
        // Allocate temporary working data
        let mut temps = BumpVec::new_in(&bump);
        for i in 0..100 {
            temps.push(i);
        }

        // Process data
        temps.iter().sum::<i32>()
    }
}
/// Shows using bump allocation with closures
pub fn with_allocator<F, R>(f: F) -> R
where
    F: FnOnce(&Bump) -> R, {
    let bump = Bump::new();
    f(&bump)
}
pub fn closure_example() -> i32 {
    with_allocator(|bump| {
        let numbers = bump.alloc_slice_copy(&[1, 2, 3, 4, 5]);
        numbers.iter().sum()
    })
}
/// Custom type that uses bump allocation internally
pub struct SymbolTable<'a> {
    bump: &'a Bump,
    symbols: BumpVec<'a, &'a str>,
}
impl<'a> SymbolTable<'a> {
    pub fn new(bump: &'a Bump) -> Self {
        Self {
            bump,
            symbols: BumpVec::new_in(bump),
        }
    }

    pub fn intern(&mut self, s: &str) -> usize {
        // Check if symbol already exists
        for (i, &sym) in self.symbols.iter().enumerate() {
            if sym == s {
                return i;
            }
        }

        // Allocate new symbol
        let symbol = self.bump.alloc_str(s);
        let id = self.symbols.len();
        self.symbols.push(symbol);
        id
    }

    pub fn get(&self, id: usize) -> Option<&'a str> {
        self.symbols.get(id).copied()
    }
}
/// Demonstrates using bump allocation for graph structures
pub struct Node<'a> {
    pub value: i32,
    pub children: BumpVec<'a, &'a Node<'a>>,
}
pub fn build_tree<'a>(bump: &'a Bump) -> &'a Node<'a> {
    // Build a simple tree structure
    let leaf1 = bump.alloc(Node {
        value: 1,
        children: BumpVec::new_in(bump),
    });

    let leaf2 = bump.alloc(Node {
        value: 2,
        children: BumpVec::new_in(bump),
    });

    let mut branch_children = BumpVec::new_in(bump);
    branch_children.push(&*leaf1);
    branch_children.push(&*leaf2);

    bump.alloc(Node {
        value: 3,
        children: branch_children,
    })
}
/// Shows statistics about memory usage
pub fn allocation_stats() {
    let mut bump = Bump::new();

    // Allocate some data
    for i in 0..1000 {
        bump.alloc(i);
    }

    // Get allocation statistics
    let allocated = bump.allocated_bytes();
    println!("Allocated: {} bytes", allocated);

    // Reset and check again
    bump.reset();
    let after_reset = bump.allocated_bytes();
    println!("After reset: {} bytes", after_reset);
}
/// Demonstrates bump boxes for single-value allocation
pub fn bump_box_example() -> i32 {
    let bump = Bump::new();

    // Create a bump-allocated box
    let boxed: BumpBox<i32> = BumpBox::new_in(100, &bump);

    // Bump boxes can be dereferenced like regular boxes
    *boxed
}
/// Shows efficient string building with bump allocation
pub struct StringBuilder<'a> {
    bump: &'a Bump,
    parts: BumpVec<'a, &'a str>,
}
impl<'a> StringBuilder<'a> {
    pub fn new(bump: &'a Bump) -> Self {
        Self {
            bump,
            parts: BumpVec::new_in(bump),
        }
    }

    pub fn append(&mut self, s: &str) {
        let part = self.bump.alloc_str(s);
        self.parts.push(part);
    }

    pub fn build(&self) -> String {
        self.parts.iter().flat_map(|s| s.chars()).collect()
    }
}
#[cfg(test)]
mod tests {
    use super::*;

    #[test]
    fn test_basic_allocation() {
        let result = basic_allocation();
        assert_eq!(result, vec![10, 20, 30]);
    }

    #[test]
    fn test_string_allocation() {
        let bump = Bump::new();
        let result = allocate_strings(&bump);
        assert_eq!(result, "Hello, World!");
    }

    #[test]
    fn test_ast_evaluation() {
        let bump = Bump::new();
        let ast = build_ast(&bump);
        assert_eq!(eval_expr(ast), 20); // (2 + 3) * 4 = 20
    }

    #[test]
    fn test_reset_reuse() {
        let (first, second) = reset_and_reuse();
        assert_eq!(first, vec![1, 2, 3]);
        assert_eq!(second, vec![4, 5, 6]);
    }

    #[test]
    fn test_symbol_table() {
        let bump = Bump::new();
        let mut table = SymbolTable::new(&bump);

        let id1 = table.intern("hello");
        let id2 = table.intern("world");
        let id3 = table.intern("hello"); // Should return same ID

        assert_eq!(id1, id3);
        assert_ne!(id1, id2);
        assert_eq!(table.get(id1), Some("hello"));
        assert_eq!(table.get(id2), Some("world"));
    }

    #[test]
    fn test_tree_building() {
        let bump = Bump::new();
        let tree = build_tree(&bump);

        assert_eq!(tree.value, 3);
        assert_eq!(tree.children.len(), 2);
        assert_eq!(tree.children[0].value, 1);
        assert_eq!(tree.children[1].value, 2);
    }

    #[test]
    fn test_string_builder() {
        let bump = Bump::new();
        let mut builder = StringBuilder::new(&bump);

        builder.append("Hello");
        builder.append(", ");
        builder.append("World!");

        assert_eq!(builder.build(), "Hello, World!");
    }
}
pub fn build_function<'a>(bump: &'a Bump) -> Function<'a> {
    let mut params = BumpVec::new_in(bump);
    let x = bump.alloc_str("x");
    let y = bump.alloc_str("y");
    params.push(&*x);
    params.push(&*y);

    let mut body = BumpVec::new_in(bump);

    // let sum = x + y
    let x = bump.alloc(Expr::Number(10));
    let y = bump.alloc(Expr::Number(20));
    let sum_expr = bump.alloc(Expr::Add(x, y));
    body.push(Statement::Let("sum", sum_expr));

    // return sum * 2
    let two = bump.alloc(Expr::Number(2));
    let result = bump.alloc(Expr::Multiply(sum_expr, two));
    body.push(Statement::Return(result));

    Function {
        name: bump.alloc_str("calculate"),
        params,
        body,
    }
}
}

This pattern works well for intermediate representations where you build up complex structures during one compilation phase and discard them after lowering or code generation.

Reset and Reuse

Bump allocators can be reset to reclaim all memory at once:

#![allow(unused)]
fn main() {
use std::fmt::Debug;
use bumpalo::Bump;
use bumpalo::boxed::Box as BumpBox;
use bumpalo::collections::Vec as BumpVec;
/// Demonstrates basic bump allocation with simple types
pub fn basic_allocation() -> Vec<i32> {
    let bump = Bump::new();

    // Allocate individual values
    let x = bump.alloc(10);
    let y = bump.alloc(20);
    let z = bump.alloc(30);

    // Values are valid for the lifetime of the bump allocator
    vec![*x, *y, *z]
}
/// Shows how to allocate strings in the bump allocator
pub fn allocate_strings(bump: &Bump) -> &str {
    // Allocate a string slice
    let hello = bump.alloc_str("Hello, ");
    let world = bump.alloc_str("World!");

    // Concatenate using bump allocation

    (bump.alloc_str(&format!("{}{}", hello, world))) as _
}
/// Allocates slices efficiently in the bump allocator
pub fn allocate_slices(bump: &Bump) -> &[i32] {
    // Allocate a slice from a vector
    let data = vec![1, 2, 3, 4, 5];
    bump.alloc_slice_copy(&data)
}
/// Demonstrates using bump-allocated collections
pub fn bump_collections() -> Vec<i32> {
    let bump = Bump::new();

    // Create a bump-allocated vector
    let mut vec = BumpVec::new_in(&bump);
    vec.push(1);
    vec.push(2);
    vec.push(3);

    // Convert to standard Vec for return
    vec.iter().copied().collect()
}
/// Shows arena-style allocation for AST nodes
#[derive(Debug, Clone)]
pub enum Expr<'a> {
    Number(i64),
    Add(&'a Expr<'a>, &'a Expr<'a>),
    Multiply(&'a Expr<'a>, &'a Expr<'a>),
}
pub fn build_ast<'a>(bump: &'a Bump) -> &'a Expr<'a> {
    // Build expression: (2 + 3) * 4
    let two = bump.alloc(Expr::Number(2));
    let three = bump.alloc(Expr::Number(3));
    let four = bump.alloc(Expr::Number(4));

    let add = bump.alloc(Expr::Add(two, three));
    bump.alloc(Expr::Multiply(add, four))
}
/// Evaluates an AST expression
pub fn eval_expr(expr: &Expr) -> i64 {
    match expr {
        Expr::Number(n) => *n,
        Expr::Add(a, b) => eval_expr(a) + eval_expr(b),
        Expr::Multiply(a, b) => eval_expr(a) * eval_expr(b),
    }
}
/// Demonstrates using bump allocation for a simple compiler IR
pub struct Function<'a> {
    pub name: &'a str,
    pub params: BumpVec<'a, &'a str>,
    pub body: BumpVec<'a, Statement<'a>>,
}
pub enum Statement<'a> {
    Let(&'a str, &'a Expr<'a>),
    Return(&'a Expr<'a>),
}
pub fn build_function<'a>(bump: &'a Bump) -> Function<'a> {
    let mut params = BumpVec::new_in(bump);
    let x = bump.alloc_str("x");
    let y = bump.alloc_str("y");
    params.push(&*x);
    params.push(&*y);

    let mut body = BumpVec::new_in(bump);

    // let sum = x + y
    let x = bump.alloc(Expr::Number(10));
    let y = bump.alloc(Expr::Number(20));
    let sum_expr = bump.alloc(Expr::Add(x, y));
    body.push(Statement::Let("sum", sum_expr));

    // return sum * 2
    let two = bump.alloc(Expr::Number(2));
    let result = bump.alloc(Expr::Multiply(sum_expr, two));
    body.push(Statement::Return(result));

    Function {
        name: bump.alloc_str("calculate"),
        params,
        body,
    }
}
/// Demonstrates scoped allocation for temporary computations
pub fn scoped_allocation() -> i32 {
    let bump = Bump::new();

    // Create a temporary allocation scope

    // Memory is automatically freed when bump goes out of scope
    {
        // Allocate temporary working data
        let mut temps = BumpVec::new_in(&bump);
        for i in 0..100 {
            temps.push(i);
        }

        // Process data
        temps.iter().sum::<i32>()
    }
}
/// Shows using bump allocation with closures
pub fn with_allocator<F, R>(f: F) -> R
where
    F: FnOnce(&Bump) -> R, {
    let bump = Bump::new();
    f(&bump)
}
pub fn closure_example() -> i32 {
    with_allocator(|bump| {
        let numbers = bump.alloc_slice_copy(&[1, 2, 3, 4, 5]);
        numbers.iter().sum()
    })
}
/// Custom type that uses bump allocation internally
pub struct SymbolTable<'a> {
    bump: &'a Bump,
    symbols: BumpVec<'a, &'a str>,
}
impl<'a> SymbolTable<'a> {
    pub fn new(bump: &'a Bump) -> Self {
        Self {
            bump,
            symbols: BumpVec::new_in(bump),
        }
    }

    pub fn intern(&mut self, s: &str) -> usize {
        // Check if symbol already exists
        for (i, &sym) in self.symbols.iter().enumerate() {
            if sym == s {
                return i;
            }
        }

        // Allocate new symbol
        let symbol = self.bump.alloc_str(s);
        let id = self.symbols.len();
        self.symbols.push(symbol);
        id
    }

    pub fn get(&self, id: usize) -> Option<&'a str> {
        self.symbols.get(id).copied()
    }
}
/// Demonstrates using bump allocation for graph structures
pub struct Node<'a> {
    pub value: i32,
    pub children: BumpVec<'a, &'a Node<'a>>,
}
pub fn build_tree<'a>(bump: &'a Bump) -> &'a Node<'a> {
    // Build a simple tree structure
    let leaf1 = bump.alloc(Node {
        value: 1,
        children: BumpVec::new_in(bump),
    });

    let leaf2 = bump.alloc(Node {
        value: 2,
        children: BumpVec::new_in(bump),
    });

    let mut branch_children = BumpVec::new_in(bump);
    branch_children.push(&*leaf1);
    branch_children.push(&*leaf2);

    bump.alloc(Node {
        value: 3,
        children: branch_children,
    })
}
/// Shows statistics about memory usage
pub fn allocation_stats() {
    let mut bump = Bump::new();

    // Allocate some data
    for i in 0..1000 {
        bump.alloc(i);
    }

    // Get allocation statistics
    let allocated = bump.allocated_bytes();
    println!("Allocated: {} bytes", allocated);

    // Reset and check again
    bump.reset();
    let after_reset = bump.allocated_bytes();
    println!("After reset: {} bytes", after_reset);
}
/// Demonstrates bump boxes for single-value allocation
pub fn bump_box_example() -> i32 {
    let bump = Bump::new();

    // Create a bump-allocated box
    let boxed: BumpBox<i32> = BumpBox::new_in(100, &bump);

    // Bump boxes can be dereferenced like regular boxes
    *boxed
}
/// Shows efficient string building with bump allocation
pub struct StringBuilder<'a> {
    bump: &'a Bump,
    parts: BumpVec<'a, &'a str>,
}
impl<'a> StringBuilder<'a> {
    pub fn new(bump: &'a Bump) -> Self {
        Self {
            bump,
            parts: BumpVec::new_in(bump),
        }
    }

    pub fn append(&mut self, s: &str) {
        let part = self.bump.alloc_str(s);
        self.parts.push(part);
    }

    pub fn build(&self) -> String {
        self.parts.iter().flat_map(|s| s.chars()).collect()
    }
}
#[cfg(test)]
mod tests {
    use super::*;

    #[test]
    fn test_basic_allocation() {
        let result = basic_allocation();
        assert_eq!(result, vec![10, 20, 30]);
    }

    #[test]
    fn test_string_allocation() {
        let bump = Bump::new();
        let result = allocate_strings(&bump);
        assert_eq!(result, "Hello, World!");
    }

    #[test]
    fn test_ast_evaluation() {
        let bump = Bump::new();
        let ast = build_ast(&bump);
        assert_eq!(eval_expr(ast), 20); // (2 + 3) * 4 = 20
    }

    #[test]
    fn test_reset_reuse() {
        let (first, second) = reset_and_reuse();
        assert_eq!(first, vec![1, 2, 3]);
        assert_eq!(second, vec![4, 5, 6]);
    }

    #[test]
    fn test_symbol_table() {
        let bump = Bump::new();
        let mut table = SymbolTable::new(&bump);

        let id1 = table.intern("hello");
        let id2 = table.intern("world");
        let id3 = table.intern("hello"); // Should return same ID

        assert_eq!(id1, id3);
        assert_ne!(id1, id2);
        assert_eq!(table.get(id1), Some("hello"));
        assert_eq!(table.get(id2), Some("world"));
    }

    #[test]
    fn test_tree_building() {
        let bump = Bump::new();
        let tree = build_tree(&bump);

        assert_eq!(tree.value, 3);
        assert_eq!(tree.children.len(), 2);
        assert_eq!(tree.children[0].value, 1);
        assert_eq!(tree.children[1].value, 2);
    }

    #[test]
    fn test_string_builder() {
        let bump = Bump::new();
        let mut builder = StringBuilder::new(&bump);

        builder.append("Hello");
        builder.append(", ");
        builder.append("World!");

        assert_eq!(builder.build(), "Hello, World!");
    }
}
/// Shows how to reset and reuse a bump allocator
pub fn reset_and_reuse() -> (Vec<i32>, Vec<i32>) {
    let mut bump = Bump::new();

    // First allocation cycle
    let first = {
        let vec = BumpVec::new_in(&bump);
        let mut vec = vec;
        vec.extend([1, 2, 3].iter().copied());
        vec.iter().copied().collect::<Vec<_>>()
    };

    // Reset the allocator to reclaim all memory
    bump.reset();

    // Second allocation cycle reuses the same memory
    let second = {
        let vec = BumpVec::new_in(&bump);
        let mut vec = vec;
        vec.extend([4, 5, 6].iter().copied());
        vec.iter().copied().collect::<Vec<_>>()
    };

    (first, second)
}
}

This is perfect for compilers that process multiple files or compilation units sequentially. Reset the allocator between units to reuse the same memory.

Scoped Allocation

Use bump allocation for temporary computations:

#![allow(unused)]
fn main() {
use std::fmt::Debug;
use bumpalo::Bump;
use bumpalo::boxed::Box as BumpBox;
use bumpalo::collections::Vec as BumpVec;
/// Demonstrates basic bump allocation with simple types
pub fn basic_allocation() -> Vec<i32> {
    let bump = Bump::new();

    // Allocate individual values
    let x = bump.alloc(10);
    let y = bump.alloc(20);
    let z = bump.alloc(30);

    // Values are valid for the lifetime of the bump allocator
    vec![*x, *y, *z]
}
/// Shows how to allocate strings in the bump allocator
pub fn allocate_strings(bump: &Bump) -> &str {
    // Allocate a string slice
    let hello = bump.alloc_str("Hello, ");
    let world = bump.alloc_str("World!");

    // Concatenate using bump allocation

    (bump.alloc_str(&format!("{}{}", hello, world))) as _
}
/// Allocates slices efficiently in the bump allocator
pub fn allocate_slices(bump: &Bump) -> &[i32] {
    // Allocate a slice from a vector
    let data = vec![1, 2, 3, 4, 5];
    bump.alloc_slice_copy(&data)
}
/// Demonstrates using bump-allocated collections
pub fn bump_collections() -> Vec<i32> {
    let bump = Bump::new();

    // Create a bump-allocated vector
    let mut vec = BumpVec::new_in(&bump);
    vec.push(1);
    vec.push(2);
    vec.push(3);

    // Convert to standard Vec for return
    vec.iter().copied().collect()
}
/// Shows arena-style allocation for AST nodes
#[derive(Debug, Clone)]
pub enum Expr<'a> {
    Number(i64),
    Add(&'a Expr<'a>, &'a Expr<'a>),
    Multiply(&'a Expr<'a>, &'a Expr<'a>),
}
pub fn build_ast<'a>(bump: &'a Bump) -> &'a Expr<'a> {
    // Build expression: (2 + 3) * 4
    let two = bump.alloc(Expr::Number(2));
    let three = bump.alloc(Expr::Number(3));
    let four = bump.alloc(Expr::Number(4));

    let add = bump.alloc(Expr::Add(two, three));
    bump.alloc(Expr::Multiply(add, four))
}
/// Evaluates an AST expression
pub fn eval_expr(expr: &Expr) -> i64 {
    match expr {
        Expr::Number(n) => *n,
        Expr::Add(a, b) => eval_expr(a) + eval_expr(b),
        Expr::Multiply(a, b) => eval_expr(a) * eval_expr(b),
    }
}
/// Demonstrates using bump allocation for a simple compiler IR
pub struct Function<'a> {
    pub name: &'a str,
    pub params: BumpVec<'a, &'a str>,
    pub body: BumpVec<'a, Statement<'a>>,
}
pub enum Statement<'a> {
    Let(&'a str, &'a Expr<'a>),
    Return(&'a Expr<'a>),
}
pub fn build_function<'a>(bump: &'a Bump) -> Function<'a> {
    let mut params = BumpVec::new_in(bump);
    let x = bump.alloc_str("x");
    let y = bump.alloc_str("y");
    params.push(&*x);
    params.push(&*y);

    let mut body = BumpVec::new_in(bump);

    // let sum = x + y
    let x = bump.alloc(Expr::Number(10));
    let y = bump.alloc(Expr::Number(20));
    let sum_expr = bump.alloc(Expr::Add(x, y));
    body.push(Statement::Let("sum", sum_expr));

    // return sum * 2
    let two = bump.alloc(Expr::Number(2));
    let result = bump.alloc(Expr::Multiply(sum_expr, two));
    body.push(Statement::Return(result));

    Function {
        name: bump.alloc_str("calculate"),
        params,
        body,
    }
}
/// Shows how to reset and reuse a bump allocator
pub fn reset_and_reuse() -> (Vec<i32>, Vec<i32>) {
    let mut bump = Bump::new();

    // First allocation cycle
    let first = {
        let vec = BumpVec::new_in(&bump);
        let mut vec = vec;
        vec.extend([1, 2, 3].iter().copied());
        vec.iter().copied().collect::<Vec<_>>()
    };

    // Reset the allocator to reclaim all memory
    bump.reset();

    // Second allocation cycle reuses the same memory
    let second = {
        let vec = BumpVec::new_in(&bump);
        let mut vec = vec;
        vec.extend([4, 5, 6].iter().copied());
        vec.iter().copied().collect::<Vec<_>>()
    };

    (first, second)
}
/// Shows using bump allocation with closures
pub fn with_allocator<F, R>(f: F) -> R
where
    F: FnOnce(&Bump) -> R, {
    let bump = Bump::new();
    f(&bump)
}
pub fn closure_example() -> i32 {
    with_allocator(|bump| {
        let numbers = bump.alloc_slice_copy(&[1, 2, 3, 4, 5]);
        numbers.iter().sum()
    })
}
/// Custom type that uses bump allocation internally
pub struct SymbolTable<'a> {
    bump: &'a Bump,
    symbols: BumpVec<'a, &'a str>,
}
impl<'a> SymbolTable<'a> {
    pub fn new(bump: &'a Bump) -> Self {
        Self {
            bump,
            symbols: BumpVec::new_in(bump),
        }
    }

    pub fn intern(&mut self, s: &str) -> usize {
        // Check if symbol already exists
        for (i, &sym) in self.symbols.iter().enumerate() {
            if sym == s {
                return i;
            }
        }

        // Allocate new symbol
        let symbol = self.bump.alloc_str(s);
        let id = self.symbols.len();
        self.symbols.push(symbol);
        id
    }

    pub fn get(&self, id: usize) -> Option<&'a str> {
        self.symbols.get(id).copied()
    }
}
/// Demonstrates using bump allocation for graph structures
pub struct Node<'a> {
    pub value: i32,
    pub children: BumpVec<'a, &'a Node<'a>>,
}
pub fn build_tree<'a>(bump: &'a Bump) -> &'a Node<'a> {
    // Build a simple tree structure
    let leaf1 = bump.alloc(Node {
        value: 1,
        children: BumpVec::new_in(bump),
    });

    let leaf2 = bump.alloc(Node {
        value: 2,
        children: BumpVec::new_in(bump),
    });

    let mut branch_children = BumpVec::new_in(bump);
    branch_children.push(&*leaf1);
    branch_children.push(&*leaf2);

    bump.alloc(Node {
        value: 3,
        children: branch_children,
    })
}
/// Shows statistics about memory usage
pub fn allocation_stats() {
    let mut bump = Bump::new();

    // Allocate some data
    for i in 0..1000 {
        bump.alloc(i);
    }

    // Get allocation statistics
    let allocated = bump.allocated_bytes();
    println!("Allocated: {} bytes", allocated);

    // Reset and check again
    bump.reset();
    let after_reset = bump.allocated_bytes();
    println!("After reset: {} bytes", after_reset);
}
/// Demonstrates bump boxes for single-value allocation
pub fn bump_box_example() -> i32 {
    let bump = Bump::new();

    // Create a bump-allocated box
    let boxed: BumpBox<i32> = BumpBox::new_in(100, &bump);

    // Bump boxes can be dereferenced like regular boxes
    *boxed
}
/// Shows efficient string building with bump allocation
pub struct StringBuilder<'a> {
    bump: &'a Bump,
    parts: BumpVec<'a, &'a str>,
}
impl<'a> StringBuilder<'a> {
    pub fn new(bump: &'a Bump) -> Self {
        Self {
            bump,
            parts: BumpVec::new_in(bump),
        }
    }

    pub fn append(&mut self, s: &str) {
        let part = self.bump.alloc_str(s);
        self.parts.push(part);
    }

    pub fn build(&self) -> String {
        self.parts.iter().flat_map(|s| s.chars()).collect()
    }
}
#[cfg(test)]
mod tests {
    use super::*;

    #[test]
    fn test_basic_allocation() {
        let result = basic_allocation();
        assert_eq!(result, vec![10, 20, 30]);
    }

    #[test]
    fn test_string_allocation() {
        let bump = Bump::new();
        let result = allocate_strings(&bump);
        assert_eq!(result, "Hello, World!");
    }

    #[test]
    fn test_ast_evaluation() {
        let bump = Bump::new();
        let ast = build_ast(&bump);
        assert_eq!(eval_expr(ast), 20); // (2 + 3) * 4 = 20
    }

    #[test]
    fn test_reset_reuse() {
        let (first, second) = reset_and_reuse();
        assert_eq!(first, vec![1, 2, 3]);
        assert_eq!(second, vec![4, 5, 6]);
    }

    #[test]
    fn test_symbol_table() {
        let bump = Bump::new();
        let mut table = SymbolTable::new(&bump);

        let id1 = table.intern("hello");
        let id2 = table.intern("world");
        let id3 = table.intern("hello"); // Should return same ID

        assert_eq!(id1, id3);
        assert_ne!(id1, id2);
        assert_eq!(table.get(id1), Some("hello"));
        assert_eq!(table.get(id2), Some("world"));
    }

    #[test]
    fn test_tree_building() {
        let bump = Bump::new();
        let tree = build_tree(&bump);

        assert_eq!(tree.value, 3);
        assert_eq!(tree.children.len(), 2);
        assert_eq!(tree.children[0].value, 1);
        assert_eq!(tree.children[1].value, 2);
    }

    #[test]
    fn test_string_builder() {
        let bump = Bump::new();
        let mut builder = StringBuilder::new(&bump);

        builder.append("Hello");
        builder.append(", ");
        builder.append("World!");

        assert_eq!(builder.build(), "Hello, World!");
    }
}
/// Demonstrates scoped allocation for temporary computations
pub fn scoped_allocation() -> i32 {
    let bump = Bump::new();

    // Create a temporary allocation scope

    // Memory is automatically freed when bump goes out of scope
    {
        // Allocate temporary working data
        let mut temps = BumpVec::new_in(&bump);
        for i in 0..100 {
            temps.push(i);
        }

        // Process data
        temps.iter().sum::<i32>()
    }
}
}

The arena automatically frees all memory when it goes out of scope, making it ideal for temporary working memory during optimization passes.

Higher-Order Patterns

Encapsulate arena lifetime management with closures:

#![allow(unused)]
fn main() {
use std::fmt::Debug;
use bumpalo::Bump;
use bumpalo::boxed::Box as BumpBox;
use bumpalo::collections::Vec as BumpVec;
/// Demonstrates basic bump allocation with simple types
pub fn basic_allocation() -> Vec<i32> {
    let bump = Bump::new();

    // Allocate individual values
    let x = bump.alloc(10);
    let y = bump.alloc(20);
    let z = bump.alloc(30);

    // Values are valid for the lifetime of the bump allocator
    vec![*x, *y, *z]
}
/// Shows how to allocate strings in the bump allocator
pub fn allocate_strings(bump: &Bump) -> &str {
    // Allocate a string slice
    let hello = bump.alloc_str("Hello, ");
    let world = bump.alloc_str("World!");

    // Concatenate using bump allocation

    (bump.alloc_str(&format!("{}{}", hello, world))) as _
}
/// Allocates slices efficiently in the bump allocator
pub fn allocate_slices(bump: &Bump) -> &[i32] {
    // Allocate a slice from a vector
    let data = vec![1, 2, 3, 4, 5];
    bump.alloc_slice_copy(&data)
}
/// Demonstrates using bump-allocated collections
pub fn bump_collections() -> Vec<i32> {
    let bump = Bump::new();

    // Create a bump-allocated vector
    let mut vec = BumpVec::new_in(&bump);
    vec.push(1);
    vec.push(2);
    vec.push(3);

    // Convert to standard Vec for return
    vec.iter().copied().collect()
}
/// Shows arena-style allocation for AST nodes
#[derive(Debug, Clone)]
pub enum Expr<'a> {
    Number(i64),
    Add(&'a Expr<'a>, &'a Expr<'a>),
    Multiply(&'a Expr<'a>, &'a Expr<'a>),
}
pub fn build_ast<'a>(bump: &'a Bump) -> &'a Expr<'a> {
    // Build expression: (2 + 3) * 4
    let two = bump.alloc(Expr::Number(2));
    let three = bump.alloc(Expr::Number(3));
    let four = bump.alloc(Expr::Number(4));

    let add = bump.alloc(Expr::Add(two, three));
    bump.alloc(Expr::Multiply(add, four))
}
/// Evaluates an AST expression
pub fn eval_expr(expr: &Expr) -> i64 {
    match expr {
        Expr::Number(n) => *n,
        Expr::Add(a, b) => eval_expr(a) + eval_expr(b),
        Expr::Multiply(a, b) => eval_expr(a) * eval_expr(b),
    }
}
/// Demonstrates using bump allocation for a simple compiler IR
pub struct Function<'a> {
    pub name: &'a str,
    pub params: BumpVec<'a, &'a str>,
    pub body: BumpVec<'a, Statement<'a>>,
}
pub enum Statement<'a> {
    Let(&'a str, &'a Expr<'a>),
    Return(&'a Expr<'a>),
}
pub fn build_function<'a>(bump: &'a Bump) -> Function<'a> {
    let mut params = BumpVec::new_in(bump);
    let x = bump.alloc_str("x");
    let y = bump.alloc_str("y");
    params.push(&*x);
    params.push(&*y);

    let mut body = BumpVec::new_in(bump);

    // let sum = x + y
    let x = bump.alloc(Expr::Number(10));
    let y = bump.alloc(Expr::Number(20));
    let sum_expr = bump.alloc(Expr::Add(x, y));
    body.push(Statement::Let("sum", sum_expr));

    // return sum * 2
    let two = bump.alloc(Expr::Number(2));
    let result = bump.alloc(Expr::Multiply(sum_expr, two));
    body.push(Statement::Return(result));

    Function {
        name: bump.alloc_str("calculate"),
        params,
        body,
    }
}
/// Shows how to reset and reuse a bump allocator
pub fn reset_and_reuse() -> (Vec<i32>, Vec<i32>) {
    let mut bump = Bump::new();

    // First allocation cycle
    let first = {
        let vec = BumpVec::new_in(&bump);
        let mut vec = vec;
        vec.extend([1, 2, 3].iter().copied());
        vec.iter().copied().collect::<Vec<_>>()
    };

    // Reset the allocator to reclaim all memory
    bump.reset();

    // Second allocation cycle reuses the same memory
    let second = {
        let vec = BumpVec::new_in(&bump);
        let mut vec = vec;
        vec.extend([4, 5, 6].iter().copied());
        vec.iter().copied().collect::<Vec<_>>()
    };

    (first, second)
}
/// Demonstrates scoped allocation for temporary computations
pub fn scoped_allocation() -> i32 {
    let bump = Bump::new();

    // Create a temporary allocation scope

    // Memory is automatically freed when bump goes out of scope
    {
        // Allocate temporary working data
        let mut temps = BumpVec::new_in(&bump);
        for i in 0..100 {
            temps.push(i);
        }

        // Process data
        temps.iter().sum::<i32>()
    }
}
pub fn closure_example() -> i32 {
    with_allocator(|bump| {
        let numbers = bump.alloc_slice_copy(&[1, 2, 3, 4, 5]);
        numbers.iter().sum()
    })
}
/// Custom type that uses bump allocation internally
pub struct SymbolTable<'a> {
    bump: &'a Bump,
    symbols: BumpVec<'a, &'a str>,
}
impl<'a> SymbolTable<'a> {
    pub fn new(bump: &'a Bump) -> Self {
        Self {
            bump,
            symbols: BumpVec::new_in(bump),
        }
    }

    pub fn intern(&mut self, s: &str) -> usize {
        // Check if symbol already exists
        for (i, &sym) in self.symbols.iter().enumerate() {
            if sym == s {
                return i;
            }
        }

        // Allocate new symbol
        let symbol = self.bump.alloc_str(s);
        let id = self.symbols.len();
        self.symbols.push(symbol);
        id
    }

    pub fn get(&self, id: usize) -> Option<&'a str> {
        self.symbols.get(id).copied()
    }
}
/// Demonstrates using bump allocation for graph structures
pub struct Node<'a> {
    pub value: i32,
    pub children: BumpVec<'a, &'a Node<'a>>,
}
pub fn build_tree<'a>(bump: &'a Bump) -> &'a Node<'a> {
    // Build a simple tree structure
    let leaf1 = bump.alloc(Node {
        value: 1,
        children: BumpVec::new_in(bump),
    });

    let leaf2 = bump.alloc(Node {
        value: 2,
        children: BumpVec::new_in(bump),
    });

    let mut branch_children = BumpVec::new_in(bump);
    branch_children.push(&*leaf1);
    branch_children.push(&*leaf2);

    bump.alloc(Node {
        value: 3,
        children: branch_children,
    })
}
/// Shows statistics about memory usage
pub fn allocation_stats() {
    let mut bump = Bump::new();

    // Allocate some data
    for i in 0..1000 {
        bump.alloc(i);
    }

    // Get allocation statistics
    let allocated = bump.allocated_bytes();
    println!("Allocated: {} bytes", allocated);

    // Reset and check again
    bump.reset();
    let after_reset = bump.allocated_bytes();
    println!("After reset: {} bytes", after_reset);
}
/// Demonstrates bump boxes for single-value allocation
pub fn bump_box_example() -> i32 {
    let bump = Bump::new();

    // Create a bump-allocated box
    let boxed: BumpBox<i32> = BumpBox::new_in(100, &bump);

    // Bump boxes can be dereferenced like regular boxes
    *boxed
}
/// Shows efficient string building with bump allocation
pub struct StringBuilder<'a> {
    bump: &'a Bump,
    parts: BumpVec<'a, &'a str>,
}
impl<'a> StringBuilder<'a> {
    pub fn new(bump: &'a Bump) -> Self {
        Self {
            bump,
            parts: BumpVec::new_in(bump),
        }
    }

    pub fn append(&mut self, s: &str) {
        let part = self.bump.alloc_str(s);
        self.parts.push(part);
    }

    pub fn build(&self) -> String {
        self.parts.iter().flat_map(|s| s.chars()).collect()
    }
}
#[cfg(test)]
mod tests {
    use super::*;

    #[test]
    fn test_basic_allocation() {
        let result = basic_allocation();
        assert_eq!(result, vec![10, 20, 30]);
    }

    #[test]
    fn test_string_allocation() {
        let bump = Bump::new();
        let result = allocate_strings(&bump);
        assert_eq!(result, "Hello, World!");
    }

    #[test]
    fn test_ast_evaluation() {
        let bump = Bump::new();
        let ast = build_ast(&bump);
        assert_eq!(eval_expr(ast), 20); // (2 + 3) * 4 = 20
    }

    #[test]
    fn test_reset_reuse() {
        let (first, second) = reset_and_reuse();
        assert_eq!(first, vec![1, 2, 3]);
        assert_eq!(second, vec![4, 5, 6]);
    }

    #[test]
    fn test_symbol_table() {
        let bump = Bump::new();
        let mut table = SymbolTable::new(&bump);

        let id1 = table.intern("hello");
        let id2 = table.intern("world");
        let id3 = table.intern("hello"); // Should return same ID

        assert_eq!(id1, id3);
        assert_ne!(id1, id2);
        assert_eq!(table.get(id1), Some("hello"));
        assert_eq!(table.get(id2), Some("world"));
    }

    #[test]
    fn test_tree_building() {
        let bump = Bump::new();
        let tree = build_tree(&bump);

        assert_eq!(tree.value, 3);
        assert_eq!(tree.children.len(), 2);
        assert_eq!(tree.children[0].value, 1);
        assert_eq!(tree.children[1].value, 2);
    }

    #[test]
    fn test_string_builder() {
        let bump = Bump::new();
        let mut builder = StringBuilder::new(&bump);

        builder.append("Hello");
        builder.append(", ");
        builder.append("World!");

        assert_eq!(builder.build(), "Hello, World!");
    }
}
/// Shows using bump allocation with closures
pub fn with_allocator<F, R>(f: F) -> R
where
    F: FnOnce(&Bump) -> R, {
    let bump = Bump::new();
    f(&bump)
}
}
#![allow(unused)]
fn main() {
use std::fmt::Debug;
use bumpalo::Bump;
use bumpalo::boxed::Box as BumpBox;
use bumpalo::collections::Vec as BumpVec;
/// Demonstrates basic bump allocation with simple types
pub fn basic_allocation() -> Vec<i32> {
    let bump = Bump::new();

    // Allocate individual values
    let x = bump.alloc(10);
    let y = bump.alloc(20);
    let z = bump.alloc(30);

    // Values are valid for the lifetime of the bump allocator
    vec![*x, *y, *z]
}
/// Shows how to allocate strings in the bump allocator
pub fn allocate_strings(bump: &Bump) -> &str {
    // Allocate a string slice
    let hello = bump.alloc_str("Hello, ");
    let world = bump.alloc_str("World!");

    // Concatenate using bump allocation

    (bump.alloc_str(&format!("{}{}", hello, world))) as _
}
/// Allocates slices efficiently in the bump allocator
pub fn allocate_slices(bump: &Bump) -> &[i32] {
    // Allocate a slice from a vector
    let data = vec![1, 2, 3, 4, 5];
    bump.alloc_slice_copy(&data)
}
/// Demonstrates using bump-allocated collections
pub fn bump_collections() -> Vec<i32> {
    let bump = Bump::new();

    // Create a bump-allocated vector
    let mut vec = BumpVec::new_in(&bump);
    vec.push(1);
    vec.push(2);
    vec.push(3);

    // Convert to standard Vec for return
    vec.iter().copied().collect()
}
/// Shows arena-style allocation for AST nodes
#[derive(Debug, Clone)]
pub enum Expr<'a> {
    Number(i64),
    Add(&'a Expr<'a>, &'a Expr<'a>),
    Multiply(&'a Expr<'a>, &'a Expr<'a>),
}
pub fn build_ast<'a>(bump: &'a Bump) -> &'a Expr<'a> {
    // Build expression: (2 + 3) * 4
    let two = bump.alloc(Expr::Number(2));
    let three = bump.alloc(Expr::Number(3));
    let four = bump.alloc(Expr::Number(4));

    let add = bump.alloc(Expr::Add(two, three));
    bump.alloc(Expr::Multiply(add, four))
}
/// Evaluates an AST expression
pub fn eval_expr(expr: &Expr) -> i64 {
    match expr {
        Expr::Number(n) => *n,
        Expr::Add(a, b) => eval_expr(a) + eval_expr(b),
        Expr::Multiply(a, b) => eval_expr(a) * eval_expr(b),
    }
}
/// Demonstrates using bump allocation for a simple compiler IR
pub struct Function<'a> {
    pub name: &'a str,
    pub params: BumpVec<'a, &'a str>,
    pub body: BumpVec<'a, Statement<'a>>,
}
pub enum Statement<'a> {
    Let(&'a str, &'a Expr<'a>),
    Return(&'a Expr<'a>),
}
pub fn build_function<'a>(bump: &'a Bump) -> Function<'a> {
    let mut params = BumpVec::new_in(bump);
    let x = bump.alloc_str("x");
    let y = bump.alloc_str("y");
    params.push(&*x);
    params.push(&*y);

    let mut body = BumpVec::new_in(bump);

    // let sum = x + y
    let x = bump.alloc(Expr::Number(10));
    let y = bump.alloc(Expr::Number(20));
    let sum_expr = bump.alloc(Expr::Add(x, y));
    body.push(Statement::Let("sum", sum_expr));

    // return sum * 2
    let two = bump.alloc(Expr::Number(2));
    let result = bump.alloc(Expr::Multiply(sum_expr, two));
    body.push(Statement::Return(result));

    Function {
        name: bump.alloc_str("calculate"),
        params,
        body,
    }
}
/// Shows how to reset and reuse a bump allocator
pub fn reset_and_reuse() -> (Vec<i32>, Vec<i32>) {
    let mut bump = Bump::new();

    // First allocation cycle
    let first = {
        let vec = BumpVec::new_in(&bump);
        let mut vec = vec;
        vec.extend([1, 2, 3].iter().copied());
        vec.iter().copied().collect::<Vec<_>>()
    };

    // Reset the allocator to reclaim all memory
    bump.reset();

    // Second allocation cycle reuses the same memory
    let second = {
        let vec = BumpVec::new_in(&bump);
        let mut vec = vec;
        vec.extend([4, 5, 6].iter().copied());
        vec.iter().copied().collect::<Vec<_>>()
    };

    (first, second)
}
/// Demonstrates scoped allocation for temporary computations
pub fn scoped_allocation() -> i32 {
    let bump = Bump::new();

    // Create a temporary allocation scope

    // Memory is automatically freed when bump goes out of scope
    {
        // Allocate temporary working data
        let mut temps = BumpVec::new_in(&bump);
        for i in 0..100 {
            temps.push(i);
        }

        // Process data
        temps.iter().sum::<i32>()
    }
}
/// Shows using bump allocation with closures
pub fn with_allocator<F, R>(f: F) -> R
where
    F: FnOnce(&Bump) -> R, {
    let bump = Bump::new();
    f(&bump)
}
/// Custom type that uses bump allocation internally
pub struct SymbolTable<'a> {
    bump: &'a Bump,
    symbols: BumpVec<'a, &'a str>,
}
impl<'a> SymbolTable<'a> {
    pub fn new(bump: &'a Bump) -> Self {
        Self {
            bump,
            symbols: BumpVec::new_in(bump),
        }
    }

    pub fn intern(&mut self, s: &str) -> usize {
        // Check if symbol already exists
        for (i, &sym) in self.symbols.iter().enumerate() {
            if sym == s {
                return i;
            }
        }

        // Allocate new symbol
        let symbol = self.bump.alloc_str(s);
        let id = self.symbols.len();
        self.symbols.push(symbol);
        id
    }

    pub fn get(&self, id: usize) -> Option<&'a str> {
        self.symbols.get(id).copied()
    }
}
/// Demonstrates using bump allocation for graph structures
pub struct Node<'a> {
    pub value: i32,
    pub children: BumpVec<'a, &'a Node<'a>>,
}
pub fn build_tree<'a>(bump: &'a Bump) -> &'a Node<'a> {
    // Build a simple tree structure
    let leaf1 = bump.alloc(Node {
        value: 1,
        children: BumpVec::new_in(bump),
    });

    let leaf2 = bump.alloc(Node {
        value: 2,
        children: BumpVec::new_in(bump),
    });

    let mut branch_children = BumpVec::new_in(bump);
    branch_children.push(&*leaf1);
    branch_children.push(&*leaf2);

    bump.alloc(Node {
        value: 3,
        children: branch_children,
    })
}
/// Shows statistics about memory usage
pub fn allocation_stats() {
    let mut bump = Bump::new();

    // Allocate some data
    for i in 0..1000 {
        bump.alloc(i);
    }

    // Get allocation statistics
    let allocated = bump.allocated_bytes();
    println!("Allocated: {} bytes", allocated);

    // Reset and check again
    bump.reset();
    let after_reset = bump.allocated_bytes();
    println!("After reset: {} bytes", after_reset);
}
/// Demonstrates bump boxes for single-value allocation
pub fn bump_box_example() -> i32 {
    let bump = Bump::new();

    // Create a bump-allocated box
    let boxed: BumpBox<i32> = BumpBox::new_in(100, &bump);

    // Bump boxes can be dereferenced like regular boxes
    *boxed
}
/// Shows efficient string building with bump allocation
pub struct StringBuilder<'a> {
    bump: &'a Bump,
    parts: BumpVec<'a, &'a str>,
}
impl<'a> StringBuilder<'a> {
    pub fn new(bump: &'a Bump) -> Self {
        Self {
            bump,
            parts: BumpVec::new_in(bump),
        }
    }

    pub fn append(&mut self, s: &str) {
        let part = self.bump.alloc_str(s);
        self.parts.push(part);
    }

    pub fn build(&self) -> String {
        self.parts.iter().flat_map(|s| s.chars()).collect()
    }
}
#[cfg(test)]
mod tests {
    use super::*;

    #[test]
    fn test_basic_allocation() {
        let result = basic_allocation();
        assert_eq!(result, vec![10, 20, 30]);
    }

    #[test]
    fn test_string_allocation() {
        let bump = Bump::new();
        let result = allocate_strings(&bump);
        assert_eq!(result, "Hello, World!");
    }

    #[test]
    fn test_ast_evaluation() {
        let bump = Bump::new();
        let ast = build_ast(&bump);
        assert_eq!(eval_expr(ast), 20); // (2 + 3) * 4 = 20
    }

    #[test]
    fn test_reset_reuse() {
        let (first, second) = reset_and_reuse();
        assert_eq!(first, vec![1, 2, 3]);
        assert_eq!(second, vec![4, 5, 6]);
    }

    #[test]
    fn test_symbol_table() {
        let bump = Bump::new();
        let mut table = SymbolTable::new(&bump);

        let id1 = table.intern("hello");
        let id2 = table.intern("world");
        let id3 = table.intern("hello"); // Should return same ID

        assert_eq!(id1, id3);
        assert_ne!(id1, id2);
        assert_eq!(table.get(id1), Some("hello"));
        assert_eq!(table.get(id2), Some("world"));
    }

    #[test]
    fn test_tree_building() {
        let bump = Bump::new();
        let tree = build_tree(&bump);

        assert_eq!(tree.value, 3);
        assert_eq!(tree.children.len(), 2);
        assert_eq!(tree.children[0].value, 1);
        assert_eq!(tree.children[1].value, 2);
    }

    #[test]
    fn test_string_builder() {
        let bump = Bump::new();
        let mut builder = StringBuilder::new(&bump);

        builder.append("Hello");
        builder.append(", ");
        builder.append("World!");

        assert_eq!(builder.build(), "Hello, World!");
    }
}
pub fn closure_example() -> i32 {
    with_allocator(|bump| {
        let numbers = bump.alloc_slice_copy(&[1, 2, 3, 4, 5]);
        numbers.iter().sum()
    })
}
}

This pattern ensures the arena is properly scoped and makes it easy to add arena allocation to existing code.

Symbol Tables

Arena allocation works well for symbol interning:

#![allow(unused)]
fn main() {
use std::fmt::Debug;
use bumpalo::Bump;
use bumpalo::boxed::Box as BumpBox;
use bumpalo::collections::Vec as BumpVec;
/// Demonstrates basic bump allocation with simple types
pub fn basic_allocation() -> Vec<i32> {
    let bump = Bump::new();

    // Allocate individual values
    let x = bump.alloc(10);
    let y = bump.alloc(20);
    let z = bump.alloc(30);

    // Values are valid for the lifetime of the bump allocator
    vec![*x, *y, *z]
}
/// Shows how to allocate strings in the bump allocator
pub fn allocate_strings(bump: &Bump) -> &str {
    // Allocate a string slice
    let hello = bump.alloc_str("Hello, ");
    let world = bump.alloc_str("World!");

    // Concatenate using bump allocation

    (bump.alloc_str(&format!("{}{}", hello, world))) as _
}
/// Allocates slices efficiently in the bump allocator
pub fn allocate_slices(bump: &Bump) -> &[i32] {
    // Allocate a slice from a vector
    let data = vec![1, 2, 3, 4, 5];
    bump.alloc_slice_copy(&data)
}
/// Demonstrates using bump-allocated collections
pub fn bump_collections() -> Vec<i32> {
    let bump = Bump::new();

    // Create a bump-allocated vector
    let mut vec = BumpVec::new_in(&bump);
    vec.push(1);
    vec.push(2);
    vec.push(3);

    // Convert to standard Vec for return
    vec.iter().copied().collect()
}
/// Shows arena-style allocation for AST nodes
#[derive(Debug, Clone)]
pub enum Expr<'a> {
    Number(i64),
    Add(&'a Expr<'a>, &'a Expr<'a>),
    Multiply(&'a Expr<'a>, &'a Expr<'a>),
}
pub fn build_ast<'a>(bump: &'a Bump) -> &'a Expr<'a> {
    // Build expression: (2 + 3) * 4
    let two = bump.alloc(Expr::Number(2));
    let three = bump.alloc(Expr::Number(3));
    let four = bump.alloc(Expr::Number(4));

    let add = bump.alloc(Expr::Add(two, three));
    bump.alloc(Expr::Multiply(add, four))
}
/// Evaluates an AST expression
pub fn eval_expr(expr: &Expr) -> i64 {
    match expr {
        Expr::Number(n) => *n,
        Expr::Add(a, b) => eval_expr(a) + eval_expr(b),
        Expr::Multiply(a, b) => eval_expr(a) * eval_expr(b),
    }
}
/// Demonstrates using bump allocation for a simple compiler IR
pub struct Function<'a> {
    pub name: &'a str,
    pub params: BumpVec<'a, &'a str>,
    pub body: BumpVec<'a, Statement<'a>>,
}
pub enum Statement<'a> {
    Let(&'a str, &'a Expr<'a>),
    Return(&'a Expr<'a>),
}
pub fn build_function<'a>(bump: &'a Bump) -> Function<'a> {
    let mut params = BumpVec::new_in(bump);
    let x = bump.alloc_str("x");
    let y = bump.alloc_str("y");
    params.push(&*x);
    params.push(&*y);

    let mut body = BumpVec::new_in(bump);

    // let sum = x + y
    let x = bump.alloc(Expr::Number(10));
    let y = bump.alloc(Expr::Number(20));
    let sum_expr = bump.alloc(Expr::Add(x, y));
    body.push(Statement::Let("sum", sum_expr));

    // return sum * 2
    let two = bump.alloc(Expr::Number(2));
    let result = bump.alloc(Expr::Multiply(sum_expr, two));
    body.push(Statement::Return(result));

    Function {
        name: bump.alloc_str("calculate"),
        params,
        body,
    }
}
/// Shows how to reset and reuse a bump allocator
pub fn reset_and_reuse() -> (Vec<i32>, Vec<i32>) {
    let mut bump = Bump::new();

    // First allocation cycle
    let first = {
        let vec = BumpVec::new_in(&bump);
        let mut vec = vec;
        vec.extend([1, 2, 3].iter().copied());
        vec.iter().copied().collect::<Vec<_>>()
    };

    // Reset the allocator to reclaim all memory
    bump.reset();

    // Second allocation cycle reuses the same memory
    let second = {
        let vec = BumpVec::new_in(&bump);
        let mut vec = vec;
        vec.extend([4, 5, 6].iter().copied());
        vec.iter().copied().collect::<Vec<_>>()
    };

    (first, second)
}
/// Demonstrates scoped allocation for temporary computations
pub fn scoped_allocation() -> i32 {
    let bump = Bump::new();

    // Create a temporary allocation scope

    // Memory is automatically freed when bump goes out of scope
    {
        // Allocate temporary working data
        let mut temps = BumpVec::new_in(&bump);
        for i in 0..100 {
            temps.push(i);
        }

        // Process data
        temps.iter().sum::<i32>()
    }
}
/// Shows using bump allocation with closures
pub fn with_allocator<F, R>(f: F) -> R
where
    F: FnOnce(&Bump) -> R, {
    let bump = Bump::new();
    f(&bump)
}
pub fn closure_example() -> i32 {
    with_allocator(|bump| {
        let numbers = bump.alloc_slice_copy(&[1, 2, 3, 4, 5]);
        numbers.iter().sum()
    })
}
impl<'a> SymbolTable<'a> {
    pub fn new(bump: &'a Bump) -> Self {
        Self {
            bump,
            symbols: BumpVec::new_in(bump),
        }
    }

    pub fn intern(&mut self, s: &str) -> usize {
        // Check if symbol already exists
        for (i, &sym) in self.symbols.iter().enumerate() {
            if sym == s {
                return i;
            }
        }

        // Allocate new symbol
        let symbol = self.bump.alloc_str(s);
        let id = self.symbols.len();
        self.symbols.push(symbol);
        id
    }

    pub fn get(&self, id: usize) -> Option<&'a str> {
        self.symbols.get(id).copied()
    }
}
/// Demonstrates using bump allocation for graph structures
pub struct Node<'a> {
    pub value: i32,
    pub children: BumpVec<'a, &'a Node<'a>>,
}
pub fn build_tree<'a>(bump: &'a Bump) -> &'a Node<'a> {
    // Build a simple tree structure
    let leaf1 = bump.alloc(Node {
        value: 1,
        children: BumpVec::new_in(bump),
    });

    let leaf2 = bump.alloc(Node {
        value: 2,
        children: BumpVec::new_in(bump),
    });

    let mut branch_children = BumpVec::new_in(bump);
    branch_children.push(&*leaf1);
    branch_children.push(&*leaf2);

    bump.alloc(Node {
        value: 3,
        children: branch_children,
    })
}
/// Shows statistics about memory usage
pub fn allocation_stats() {
    let mut bump = Bump::new();

    // Allocate some data
    for i in 0..1000 {
        bump.alloc(i);
    }

    // Get allocation statistics
    let allocated = bump.allocated_bytes();
    println!("Allocated: {} bytes", allocated);

    // Reset and check again
    bump.reset();
    let after_reset = bump.allocated_bytes();
    println!("After reset: {} bytes", after_reset);
}
/// Demonstrates bump boxes for single-value allocation
pub fn bump_box_example() -> i32 {
    let bump = Bump::new();

    // Create a bump-allocated box
    let boxed: BumpBox<i32> = BumpBox::new_in(100, &bump);

    // Bump boxes can be dereferenced like regular boxes
    *boxed
}
/// Shows efficient string building with bump allocation
pub struct StringBuilder<'a> {
    bump: &'a Bump,
    parts: BumpVec<'a, &'a str>,
}
impl<'a> StringBuilder<'a> {
    pub fn new(bump: &'a Bump) -> Self {
        Self {
            bump,
            parts: BumpVec::new_in(bump),
        }
    }

    pub fn append(&mut self, s: &str) {
        let part = self.bump.alloc_str(s);
        self.parts.push(part);
    }

    pub fn build(&self) -> String {
        self.parts.iter().flat_map(|s| s.chars()).collect()
    }
}
#[cfg(test)]
mod tests {
    use super::*;

    #[test]
    fn test_basic_allocation() {
        let result = basic_allocation();
        assert_eq!(result, vec![10, 20, 30]);
    }

    #[test]
    fn test_string_allocation() {
        let bump = Bump::new();
        let result = allocate_strings(&bump);
        assert_eq!(result, "Hello, World!");
    }

    #[test]
    fn test_ast_evaluation() {
        let bump = Bump::new();
        let ast = build_ast(&bump);
        assert_eq!(eval_expr(ast), 20); // (2 + 3) * 4 = 20
    }

    #[test]
    fn test_reset_reuse() {
        let (first, second) = reset_and_reuse();
        assert_eq!(first, vec![1, 2, 3]);
        assert_eq!(second, vec![4, 5, 6]);
    }

    #[test]
    fn test_symbol_table() {
        let bump = Bump::new();
        let mut table = SymbolTable::new(&bump);

        let id1 = table.intern("hello");
        let id2 = table.intern("world");
        let id3 = table.intern("hello"); // Should return same ID

        assert_eq!(id1, id3);
        assert_ne!(id1, id2);
        assert_eq!(table.get(id1), Some("hello"));
        assert_eq!(table.get(id2), Some("world"));
    }

    #[test]
    fn test_tree_building() {
        let bump = Bump::new();
        let tree = build_tree(&bump);

        assert_eq!(tree.value, 3);
        assert_eq!(tree.children.len(), 2);
        assert_eq!(tree.children[0].value, 1);
        assert_eq!(tree.children[1].value, 2);
    }

    #[test]
    fn test_string_builder() {
        let bump = Bump::new();
        let mut builder = StringBuilder::new(&bump);

        builder.append("Hello");
        builder.append(", ");
        builder.append("World!");

        assert_eq!(builder.build(), "Hello, World!");
    }
}
/// Custom type that uses bump allocation internally
pub struct SymbolTable<'a> {
    bump: &'a Bump,
    symbols: BumpVec<'a, &'a str>,
}
}
#![allow(unused)]
fn main() {
use std::fmt::Debug;
use bumpalo::Bump;
use bumpalo::boxed::Box as BumpBox;
use bumpalo::collections::Vec as BumpVec;
/// Demonstrates basic bump allocation with simple types
pub fn basic_allocation() -> Vec<i32> {
    let bump = Bump::new();

    // Allocate individual values
    let x = bump.alloc(10);
    let y = bump.alloc(20);
    let z = bump.alloc(30);

    // Values are valid for the lifetime of the bump allocator
    vec![*x, *y, *z]
}
/// Shows how to allocate strings in the bump allocator
pub fn allocate_strings(bump: &Bump) -> &str {
    // Allocate a string slice
    let hello = bump.alloc_str("Hello, ");
    let world = bump.alloc_str("World!");

    // Concatenate using bump allocation

    (bump.alloc_str(&format!("{}{}", hello, world))) as _
}
/// Allocates slices efficiently in the bump allocator
pub fn allocate_slices(bump: &Bump) -> &[i32] {
    // Allocate a slice from a vector
    let data = vec![1, 2, 3, 4, 5];
    bump.alloc_slice_copy(&data)
}
/// Demonstrates using bump-allocated collections
pub fn bump_collections() -> Vec<i32> {
    let bump = Bump::new();

    // Create a bump-allocated vector
    let mut vec = BumpVec::new_in(&bump);
    vec.push(1);
    vec.push(2);
    vec.push(3);

    // Convert to standard Vec for return
    vec.iter().copied().collect()
}
/// Shows arena-style allocation for AST nodes
#[derive(Debug, Clone)]
pub enum Expr<'a> {
    Number(i64),
    Add(&'a Expr<'a>, &'a Expr<'a>),
    Multiply(&'a Expr<'a>, &'a Expr<'a>),
}
pub fn build_ast<'a>(bump: &'a Bump) -> &'a Expr<'a> {
    // Build expression: (2 + 3) * 4
    let two = bump.alloc(Expr::Number(2));
    let three = bump.alloc(Expr::Number(3));
    let four = bump.alloc(Expr::Number(4));

    let add = bump.alloc(Expr::Add(two, three));
    bump.alloc(Expr::Multiply(add, four))
}
/// Evaluates an AST expression
pub fn eval_expr(expr: &Expr) -> i64 {
    match expr {
        Expr::Number(n) => *n,
        Expr::Add(a, b) => eval_expr(a) + eval_expr(b),
        Expr::Multiply(a, b) => eval_expr(a) * eval_expr(b),
    }
}
/// Demonstrates using bump allocation for a simple compiler IR
pub struct Function<'a> {
    pub name: &'a str,
    pub params: BumpVec<'a, &'a str>,
    pub body: BumpVec<'a, Statement<'a>>,
}
pub enum Statement<'a> {
    Let(&'a str, &'a Expr<'a>),
    Return(&'a Expr<'a>),
}
pub fn build_function<'a>(bump: &'a Bump) -> Function<'a> {
    let mut params = BumpVec::new_in(bump);
    let x = bump.alloc_str("x");
    let y = bump.alloc_str("y");
    params.push(&*x);
    params.push(&*y);

    let mut body = BumpVec::new_in(bump);

    // let sum = x + y
    let x = bump.alloc(Expr::Number(10));
    let y = bump.alloc(Expr::Number(20));
    let sum_expr = bump.alloc(Expr::Add(x, y));
    body.push(Statement::Let("sum", sum_expr));

    // return sum * 2
    let two = bump.alloc(Expr::Number(2));
    let result = bump.alloc(Expr::Multiply(sum_expr, two));
    body.push(Statement::Return(result));

    Function {
        name: bump.alloc_str("calculate"),
        params,
        body,
    }
}
/// Shows how to reset and reuse a bump allocator
pub fn reset_and_reuse() -> (Vec<i32>, Vec<i32>) {
    let mut bump = Bump::new();

    // First allocation cycle
    let first = {
        let vec = BumpVec::new_in(&bump);
        let mut vec = vec;
        vec.extend([1, 2, 3].iter().copied());
        vec.iter().copied().collect::<Vec<_>>()
    };

    // Reset the allocator to reclaim all memory
    bump.reset();

    // Second allocation cycle reuses the same memory
    let second = {
        let vec = BumpVec::new_in(&bump);
        let mut vec = vec;
        vec.extend([4, 5, 6].iter().copied());
        vec.iter().copied().collect::<Vec<_>>()
    };

    (first, second)
}
/// Demonstrates scoped allocation for temporary computations
pub fn scoped_allocation() -> i32 {
    let bump = Bump::new();

    // Create a temporary allocation scope

    // Memory is automatically freed when bump goes out of scope
    {
        // Allocate temporary working data
        let mut temps = BumpVec::new_in(&bump);
        for i in 0..100 {
            temps.push(i);
        }

        // Process data
        temps.iter().sum::<i32>()
    }
}
/// Shows using bump allocation with closures
pub fn with_allocator<F, R>(f: F) -> R
where
    F: FnOnce(&Bump) -> R, {
    let bump = Bump::new();
    f(&bump)
}
pub fn closure_example() -> i32 {
    with_allocator(|bump| {
        let numbers = bump.alloc_slice_copy(&[1, 2, 3, 4, 5]);
        numbers.iter().sum()
    })
}
/// Custom type that uses bump allocation internally
pub struct SymbolTable<'a> {
    bump: &'a Bump,
    symbols: BumpVec<'a, &'a str>,
}
/// Demonstrates using bump allocation for graph structures
pub struct Node<'a> {
    pub value: i32,
    pub children: BumpVec<'a, &'a Node<'a>>,
}
pub fn build_tree<'a>(bump: &'a Bump) -> &'a Node<'a> {
    // Build a simple tree structure
    let leaf1 = bump.alloc(Node {
        value: 1,
        children: BumpVec::new_in(bump),
    });

    let leaf2 = bump.alloc(Node {
        value: 2,
        children: BumpVec::new_in(bump),
    });

    let mut branch_children = BumpVec::new_in(bump);
    branch_children.push(&*leaf1);
    branch_children.push(&*leaf2);

    bump.alloc(Node {
        value: 3,
        children: branch_children,
    })
}
/// Shows statistics about memory usage
pub fn allocation_stats() {
    let mut bump = Bump::new();

    // Allocate some data
    for i in 0..1000 {
        bump.alloc(i);
    }

    // Get allocation statistics
    let allocated = bump.allocated_bytes();
    println!("Allocated: {} bytes", allocated);

    // Reset and check again
    bump.reset();
    let after_reset = bump.allocated_bytes();
    println!("After reset: {} bytes", after_reset);
}
/// Demonstrates bump boxes for single-value allocation
pub fn bump_box_example() -> i32 {
    let bump = Bump::new();

    // Create a bump-allocated box
    let boxed: BumpBox<i32> = BumpBox::new_in(100, &bump);

    // Bump boxes can be dereferenced like regular boxes
    *boxed
}
/// Shows efficient string building with bump allocation
pub struct StringBuilder<'a> {
    bump: &'a Bump,
    parts: BumpVec<'a, &'a str>,
}
impl<'a> StringBuilder<'a> {
    pub fn new(bump: &'a Bump) -> Self {
        Self {
            bump,
            parts: BumpVec::new_in(bump),
        }
    }

    pub fn append(&mut self, s: &str) {
        let part = self.bump.alloc_str(s);
        self.parts.push(part);
    }

    pub fn build(&self) -> String {
        self.parts.iter().flat_map(|s| s.chars()).collect()
    }
}
#[cfg(test)]
mod tests {
    use super::*;

    #[test]
    fn test_basic_allocation() {
        let result = basic_allocation();
        assert_eq!(result, vec![10, 20, 30]);
    }

    #[test]
    fn test_string_allocation() {
        let bump = Bump::new();
        let result = allocate_strings(&bump);
        assert_eq!(result, "Hello, World!");
    }

    #[test]
    fn test_ast_evaluation() {
        let bump = Bump::new();
        let ast = build_ast(&bump);
        assert_eq!(eval_expr(ast), 20); // (2 + 3) * 4 = 20
    }

    #[test]
    fn test_reset_reuse() {
        let (first, second) = reset_and_reuse();
        assert_eq!(first, vec![1, 2, 3]);
        assert_eq!(second, vec![4, 5, 6]);
    }

    #[test]
    fn test_symbol_table() {
        let bump = Bump::new();
        let mut table = SymbolTable::new(&bump);

        let id1 = table.intern("hello");
        let id2 = table.intern("world");
        let id3 = table.intern("hello"); // Should return same ID

        assert_eq!(id1, id3);
        assert_ne!(id1, id2);
        assert_eq!(table.get(id1), Some("hello"));
        assert_eq!(table.get(id2), Some("world"));
    }

    #[test]
    fn test_tree_building() {
        let bump = Bump::new();
        let tree = build_tree(&bump);

        assert_eq!(tree.value, 3);
        assert_eq!(tree.children.len(), 2);
        assert_eq!(tree.children[0].value, 1);
        assert_eq!(tree.children[1].value, 2);
    }

    #[test]
    fn test_string_builder() {
        let bump = Bump::new();
        let mut builder = StringBuilder::new(&bump);

        builder.append("Hello");
        builder.append(", ");
        builder.append("World!");

        assert_eq!(builder.build(), "Hello, World!");
    }
}
impl<'a> SymbolTable<'a> {
    pub fn new(bump: &'a Bump) -> Self {
        Self {
            bump,
            symbols: BumpVec::new_in(bump),
        }
    }

    pub fn intern(&mut self, s: &str) -> usize {
        // Check if symbol already exists
        for (i, &sym) in self.symbols.iter().enumerate() {
            if sym == s {
                return i;
            }
        }

        // Allocate new symbol
        let symbol = self.bump.alloc_str(s);
        let id = self.symbols.len();
        self.symbols.push(symbol);
        id
    }

    pub fn get(&self, id: usize) -> Option<&'a str> {
        self.symbols.get(id).copied()
    }
}
}

Interned strings live as long as the compilation unit needs them, with minimal allocation overhead and excellent cache performance.

Graph Structures

Build complex graph structures like control flow graphs:

#![allow(unused)]
fn main() {
use std::fmt::Debug;
use bumpalo::Bump;
use bumpalo::boxed::Box as BumpBox;
use bumpalo::collections::Vec as BumpVec;
/// Demonstrates basic bump allocation with simple types
pub fn basic_allocation() -> Vec<i32> {
    let bump = Bump::new();

    // Allocate individual values
    let x = bump.alloc(10);
    let y = bump.alloc(20);
    let z = bump.alloc(30);

    // Values are valid for the lifetime of the bump allocator
    vec![*x, *y, *z]
}
/// Shows how to allocate strings in the bump allocator
pub fn allocate_strings(bump: &Bump) -> &str {
    // Allocate a string slice
    let hello = bump.alloc_str("Hello, ");
    let world = bump.alloc_str("World!");

    // Concatenate using bump allocation

    (bump.alloc_str(&format!("{}{}", hello, world))) as _
}
/// Allocates slices efficiently in the bump allocator
pub fn allocate_slices(bump: &Bump) -> &[i32] {
    // Allocate a slice from a vector
    let data = vec![1, 2, 3, 4, 5];
    bump.alloc_slice_copy(&data)
}
/// Demonstrates using bump-allocated collections
pub fn bump_collections() -> Vec<i32> {
    let bump = Bump::new();

    // Create a bump-allocated vector
    let mut vec = BumpVec::new_in(&bump);
    vec.push(1);
    vec.push(2);
    vec.push(3);

    // Convert to standard Vec for return
    vec.iter().copied().collect()
}
/// Shows arena-style allocation for AST nodes
#[derive(Debug, Clone)]
pub enum Expr<'a> {
    Number(i64),
    Add(&'a Expr<'a>, &'a Expr<'a>),
    Multiply(&'a Expr<'a>, &'a Expr<'a>),
}
pub fn build_ast<'a>(bump: &'a Bump) -> &'a Expr<'a> {
    // Build expression: (2 + 3) * 4
    let two = bump.alloc(Expr::Number(2));
    let three = bump.alloc(Expr::Number(3));
    let four = bump.alloc(Expr::Number(4));

    let add = bump.alloc(Expr::Add(two, three));
    bump.alloc(Expr::Multiply(add, four))
}
/// Evaluates an AST expression
pub fn eval_expr(expr: &Expr) -> i64 {
    match expr {
        Expr::Number(n) => *n,
        Expr::Add(a, b) => eval_expr(a) + eval_expr(b),
        Expr::Multiply(a, b) => eval_expr(a) * eval_expr(b),
    }
}
/// Demonstrates using bump allocation for a simple compiler IR
pub struct Function<'a> {
    pub name: &'a str,
    pub params: BumpVec<'a, &'a str>,
    pub body: BumpVec<'a, Statement<'a>>,
}
pub enum Statement<'a> {
    Let(&'a str, &'a Expr<'a>),
    Return(&'a Expr<'a>),
}
pub fn build_function<'a>(bump: &'a Bump) -> Function<'a> {
    let mut params = BumpVec::new_in(bump);
    let x = bump.alloc_str("x");
    let y = bump.alloc_str("y");
    params.push(&*x);
    params.push(&*y);

    let mut body = BumpVec::new_in(bump);

    // let sum = x + y
    let x = bump.alloc(Expr::Number(10));
    let y = bump.alloc(Expr::Number(20));
    let sum_expr = bump.alloc(Expr::Add(x, y));
    body.push(Statement::Let("sum", sum_expr));

    // return sum * 2
    let two = bump.alloc(Expr::Number(2));
    let result = bump.alloc(Expr::Multiply(sum_expr, two));
    body.push(Statement::Return(result));

    Function {
        name: bump.alloc_str("calculate"),
        params,
        body,
    }
}
/// Shows how to reset and reuse a bump allocator
pub fn reset_and_reuse() -> (Vec<i32>, Vec<i32>) {
    let mut bump = Bump::new();

    // First allocation cycle
    let first = {
        let vec = BumpVec::new_in(&bump);
        let mut vec = vec;
        vec.extend([1, 2, 3].iter().copied());
        vec.iter().copied().collect::<Vec<_>>()
    };

    // Reset the allocator to reclaim all memory
    bump.reset();

    // Second allocation cycle reuses the same memory
    let second = {
        let vec = BumpVec::new_in(&bump);
        let mut vec = vec;
        vec.extend([4, 5, 6].iter().copied());
        vec.iter().copied().collect::<Vec<_>>()
    };

    (first, second)
}
/// Demonstrates scoped allocation for temporary computations
pub fn scoped_allocation() -> i32 {
    let bump = Bump::new();

    // Create a temporary allocation scope

    // Memory is automatically freed when bump goes out of scope
    {
        // Allocate temporary working data
        let mut temps = BumpVec::new_in(&bump);
        for i in 0..100 {
            temps.push(i);
        }

        // Process data
        temps.iter().sum::<i32>()
    }
}
/// Shows using bump allocation with closures
pub fn with_allocator<F, R>(f: F) -> R
where
    F: FnOnce(&Bump) -> R, {
    let bump = Bump::new();
    f(&bump)
}
pub fn closure_example() -> i32 {
    with_allocator(|bump| {
        let numbers = bump.alloc_slice_copy(&[1, 2, 3, 4, 5]);
        numbers.iter().sum()
    })
}
/// Custom type that uses bump allocation internally
pub struct SymbolTable<'a> {
    bump: &'a Bump,
    symbols: BumpVec<'a, &'a str>,
}
impl<'a> SymbolTable<'a> {
    pub fn new(bump: &'a Bump) -> Self {
        Self {
            bump,
            symbols: BumpVec::new_in(bump),
        }
    }

    pub fn intern(&mut self, s: &str) -> usize {
        // Check if symbol already exists
        for (i, &sym) in self.symbols.iter().enumerate() {
            if sym == s {
                return i;
            }
        }

        // Allocate new symbol
        let symbol = self.bump.alloc_str(s);
        let id = self.symbols.len();
        self.symbols.push(symbol);
        id
    }

    pub fn get(&self, id: usize) -> Option<&'a str> {
        self.symbols.get(id).copied()
    }
}
pub fn build_tree<'a>(bump: &'a Bump) -> &'a Node<'a> {
    // Build a simple tree structure
    let leaf1 = bump.alloc(Node {
        value: 1,
        children: BumpVec::new_in(bump),
    });

    let leaf2 = bump.alloc(Node {
        value: 2,
        children: BumpVec::new_in(bump),
    });

    let mut branch_children = BumpVec::new_in(bump);
    branch_children.push(&*leaf1);
    branch_children.push(&*leaf2);

    bump.alloc(Node {
        value: 3,
        children: branch_children,
    })
}
/// Shows statistics about memory usage
pub fn allocation_stats() {
    let mut bump = Bump::new();

    // Allocate some data
    for i in 0..1000 {
        bump.alloc(i);
    }

    // Get allocation statistics
    let allocated = bump.allocated_bytes();
    println!("Allocated: {} bytes", allocated);

    // Reset and check again
    bump.reset();
    let after_reset = bump.allocated_bytes();
    println!("After reset: {} bytes", after_reset);
}
/// Demonstrates bump boxes for single-value allocation
pub fn bump_box_example() -> i32 {
    let bump = Bump::new();

    // Create a bump-allocated box
    let boxed: BumpBox<i32> = BumpBox::new_in(100, &bump);

    // Bump boxes can be dereferenced like regular boxes
    *boxed
}
/// Shows efficient string building with bump allocation
pub struct StringBuilder<'a> {
    bump: &'a Bump,
    parts: BumpVec<'a, &'a str>,
}
impl<'a> StringBuilder<'a> {
    pub fn new(bump: &'a Bump) -> Self {
        Self {
            bump,
            parts: BumpVec::new_in(bump),
        }
    }

    pub fn append(&mut self, s: &str) {
        let part = self.bump.alloc_str(s);
        self.parts.push(part);
    }

    pub fn build(&self) -> String {
        self.parts.iter().flat_map(|s| s.chars()).collect()
    }
}
#[cfg(test)]
mod tests {
    use super::*;

    #[test]
    fn test_basic_allocation() {
        let result = basic_allocation();
        assert_eq!(result, vec![10, 20, 30]);
    }

    #[test]
    fn test_string_allocation() {
        let bump = Bump::new();
        let result = allocate_strings(&bump);
        assert_eq!(result, "Hello, World!");
    }

    #[test]
    fn test_ast_evaluation() {
        let bump = Bump::new();
        let ast = build_ast(&bump);
        assert_eq!(eval_expr(ast), 20); // (2 + 3) * 4 = 20
    }

    #[test]
    fn test_reset_reuse() {
        let (first, second) = reset_and_reuse();
        assert_eq!(first, vec![1, 2, 3]);
        assert_eq!(second, vec![4, 5, 6]);
    }

    #[test]
    fn test_symbol_table() {
        let bump = Bump::new();
        let mut table = SymbolTable::new(&bump);

        let id1 = table.intern("hello");
        let id2 = table.intern("world");
        let id3 = table.intern("hello"); // Should return same ID

        assert_eq!(id1, id3);
        assert_ne!(id1, id2);
        assert_eq!(table.get(id1), Some("hello"));
        assert_eq!(table.get(id2), Some("world"));
    }

    #[test]
    fn test_tree_building() {
        let bump = Bump::new();
        let tree = build_tree(&bump);

        assert_eq!(tree.value, 3);
        assert_eq!(tree.children.len(), 2);
        assert_eq!(tree.children[0].value, 1);
        assert_eq!(tree.children[1].value, 2);
    }

    #[test]
    fn test_string_builder() {
        let bump = Bump::new();
        let mut builder = StringBuilder::new(&bump);

        builder.append("Hello");
        builder.append(", ");
        builder.append("World!");

        assert_eq!(builder.build(), "Hello, World!");
    }
}
/// Demonstrates using bump allocation for graph structures
pub struct Node<'a> {
    pub value: i32,
    pub children: BumpVec<'a, &'a Node<'a>>,
}
}
#![allow(unused)]
fn main() {
use std::fmt::Debug;
use bumpalo::Bump;
use bumpalo::boxed::Box as BumpBox;
use bumpalo::collections::Vec as BumpVec;
/// Demonstrates basic bump allocation with simple types
pub fn basic_allocation() -> Vec<i32> {
    let bump = Bump::new();

    // Allocate individual values
    let x = bump.alloc(10);
    let y = bump.alloc(20);
    let z = bump.alloc(30);

    // Values are valid for the lifetime of the bump allocator
    vec![*x, *y, *z]
}
/// Shows how to allocate strings in the bump allocator
pub fn allocate_strings(bump: &Bump) -> &str {
    // Allocate a string slice
    let hello = bump.alloc_str("Hello, ");
    let world = bump.alloc_str("World!");

    // Concatenate using bump allocation

    (bump.alloc_str(&format!("{}{}", hello, world))) as _
}
/// Allocates slices efficiently in the bump allocator
pub fn allocate_slices(bump: &Bump) -> &[i32] {
    // Allocate a slice from a vector
    let data = vec![1, 2, 3, 4, 5];
    bump.alloc_slice_copy(&data)
}
/// Demonstrates using bump-allocated collections
pub fn bump_collections() -> Vec<i32> {
    let bump = Bump::new();

    // Create a bump-allocated vector
    let mut vec = BumpVec::new_in(&bump);
    vec.push(1);
    vec.push(2);
    vec.push(3);

    // Convert to standard Vec for return
    vec.iter().copied().collect()
}
/// Shows arena-style allocation for AST nodes
#[derive(Debug, Clone)]
pub enum Expr<'a> {
    Number(i64),
    Add(&'a Expr<'a>, &'a Expr<'a>),
    Multiply(&'a Expr<'a>, &'a Expr<'a>),
}
pub fn build_ast<'a>(bump: &'a Bump) -> &'a Expr<'a> {
    // Build expression: (2 + 3) * 4
    let two = bump.alloc(Expr::Number(2));
    let three = bump.alloc(Expr::Number(3));
    let four = bump.alloc(Expr::Number(4));

    let add = bump.alloc(Expr::Add(two, three));
    bump.alloc(Expr::Multiply(add, four))
}
/// Evaluates an AST expression
pub fn eval_expr(expr: &Expr) -> i64 {
    match expr {
        Expr::Number(n) => *n,
        Expr::Add(a, b) => eval_expr(a) + eval_expr(b),
        Expr::Multiply(a, b) => eval_expr(a) * eval_expr(b),
    }
}
/// Demonstrates using bump allocation for a simple compiler IR
pub struct Function<'a> {
    pub name: &'a str,
    pub params: BumpVec<'a, &'a str>,
    pub body: BumpVec<'a, Statement<'a>>,
}
pub enum Statement<'a> {
    Let(&'a str, &'a Expr<'a>),
    Return(&'a Expr<'a>),
}
pub fn build_function<'a>(bump: &'a Bump) -> Function<'a> {
    let mut params = BumpVec::new_in(bump);
    let x = bump.alloc_str("x");
    let y = bump.alloc_str("y");
    params.push(&*x);
    params.push(&*y);

    let mut body = BumpVec::new_in(bump);

    // let sum = x + y
    let x = bump.alloc(Expr::Number(10));
    let y = bump.alloc(Expr::Number(20));
    let sum_expr = bump.alloc(Expr::Add(x, y));
    body.push(Statement::Let("sum", sum_expr));

    // return sum * 2
    let two = bump.alloc(Expr::Number(2));
    let result = bump.alloc(Expr::Multiply(sum_expr, two));
    body.push(Statement::Return(result));

    Function {
        name: bump.alloc_str("calculate"),
        params,
        body,
    }
}
/// Shows how to reset and reuse a bump allocator
pub fn reset_and_reuse() -> (Vec<i32>, Vec<i32>) {
    let mut bump = Bump::new();

    // First allocation cycle
    let first = {
        let vec = BumpVec::new_in(&bump);
        let mut vec = vec;
        vec.extend([1, 2, 3].iter().copied());
        vec.iter().copied().collect::<Vec<_>>()
    };

    // Reset the allocator to reclaim all memory
    bump.reset();

    // Second allocation cycle reuses the same memory
    let second = {
        let vec = BumpVec::new_in(&bump);
        let mut vec = vec;
        vec.extend([4, 5, 6].iter().copied());
        vec.iter().copied().collect::<Vec<_>>()
    };

    (first, second)
}
/// Demonstrates scoped allocation for temporary computations
pub fn scoped_allocation() -> i32 {
    let bump = Bump::new();

    // Create a temporary allocation scope

    // Memory is automatically freed when bump goes out of scope
    {
        // Allocate temporary working data
        let mut temps = BumpVec::new_in(&bump);
        for i in 0..100 {
            temps.push(i);
        }

        // Process data
        temps.iter().sum::<i32>()
    }
}
/// Shows using bump allocation with closures
pub fn with_allocator<F, R>(f: F) -> R
where
    F: FnOnce(&Bump) -> R, {
    let bump = Bump::new();
    f(&bump)
}
pub fn closure_example() -> i32 {
    with_allocator(|bump| {
        let numbers = bump.alloc_slice_copy(&[1, 2, 3, 4, 5]);
        numbers.iter().sum()
    })
}
/// Custom type that uses bump allocation internally
pub struct SymbolTable<'a> {
    bump: &'a Bump,
    symbols: BumpVec<'a, &'a str>,
}
impl<'a> SymbolTable<'a> {
    pub fn new(bump: &'a Bump) -> Self {
        Self {
            bump,
            symbols: BumpVec::new_in(bump),
        }
    }

    pub fn intern(&mut self, s: &str) -> usize {
        // Check if symbol already exists
        for (i, &sym) in self.symbols.iter().enumerate() {
            if sym == s {
                return i;
            }
        }

        // Allocate new symbol
        let symbol = self.bump.alloc_str(s);
        let id = self.symbols.len();
        self.symbols.push(symbol);
        id
    }

    pub fn get(&self, id: usize) -> Option<&'a str> {
        self.symbols.get(id).copied()
    }
}
/// Demonstrates using bump allocation for graph structures
pub struct Node<'a> {
    pub value: i32,
    pub children: BumpVec<'a, &'a Node<'a>>,
}
/// Shows statistics about memory usage
pub fn allocation_stats() {
    let mut bump = Bump::new();

    // Allocate some data
    for i in 0..1000 {
        bump.alloc(i);
    }

    // Get allocation statistics
    let allocated = bump.allocated_bytes();
    println!("Allocated: {} bytes", allocated);

    // Reset and check again
    bump.reset();
    let after_reset = bump.allocated_bytes();
    println!("After reset: {} bytes", after_reset);
}
/// Demonstrates bump boxes for single-value allocation
pub fn bump_box_example() -> i32 {
    let bump = Bump::new();

    // Create a bump-allocated box
    let boxed: BumpBox<i32> = BumpBox::new_in(100, &bump);

    // Bump boxes can be dereferenced like regular boxes
    *boxed
}
/// Shows efficient string building with bump allocation
pub struct StringBuilder<'a> {
    bump: &'a Bump,
    parts: BumpVec<'a, &'a str>,
}
impl<'a> StringBuilder<'a> {
    pub fn new(bump: &'a Bump) -> Self {
        Self {
            bump,
            parts: BumpVec::new_in(bump),
        }
    }

    pub fn append(&mut self, s: &str) {
        let part = self.bump.alloc_str(s);
        self.parts.push(part);
    }

    pub fn build(&self) -> String {
        self.parts.iter().flat_map(|s| s.chars()).collect()
    }
}
#[cfg(test)]
mod tests {
    use super::*;

    #[test]
    fn test_basic_allocation() {
        let result = basic_allocation();
        assert_eq!(result, vec![10, 20, 30]);
    }

    #[test]
    fn test_string_allocation() {
        let bump = Bump::new();
        let result = allocate_strings(&bump);
        assert_eq!(result, "Hello, World!");
    }

    #[test]
    fn test_ast_evaluation() {
        let bump = Bump::new();
        let ast = build_ast(&bump);
        assert_eq!(eval_expr(ast), 20); // (2 + 3) * 4 = 20
    }

    #[test]
    fn test_reset_reuse() {
        let (first, second) = reset_and_reuse();
        assert_eq!(first, vec![1, 2, 3]);
        assert_eq!(second, vec![4, 5, 6]);
    }

    #[test]
    fn test_symbol_table() {
        let bump = Bump::new();
        let mut table = SymbolTable::new(&bump);

        let id1 = table.intern("hello");
        let id2 = table.intern("world");
        let id3 = table.intern("hello"); // Should return same ID

        assert_eq!(id1, id3);
        assert_ne!(id1, id2);
        assert_eq!(table.get(id1), Some("hello"));
        assert_eq!(table.get(id2), Some("world"));
    }

    #[test]
    fn test_tree_building() {
        let bump = Bump::new();
        let tree = build_tree(&bump);

        assert_eq!(tree.value, 3);
        assert_eq!(tree.children.len(), 2);
        assert_eq!(tree.children[0].value, 1);
        assert_eq!(tree.children[1].value, 2);
    }

    #[test]
    fn test_string_builder() {
        let bump = Bump::new();
        let mut builder = StringBuilder::new(&bump);

        builder.append("Hello");
        builder.append(", ");
        builder.append("World!");

        assert_eq!(builder.build(), "Hello, World!");
    }
}
pub fn build_tree<'a>(bump: &'a Bump) -> &'a Node<'a> {
    // Build a simple tree structure
    let leaf1 = bump.alloc(Node {
        value: 1,
        children: BumpVec::new_in(bump),
    });

    let leaf2 = bump.alloc(Node {
        value: 2,
        children: BumpVec::new_in(bump),
    });

    let mut branch_children = BumpVec::new_in(bump);
    branch_children.push(&*leaf1);
    branch_children.push(&*leaf2);

    bump.alloc(Node {
        value: 3,
        children: branch_children,
    })
}
}

Nodes can freely reference each other without complex lifetime management or reference counting overhead.

Bump Boxes

For single-value allocations with ownership semantics:

#![allow(unused)]
fn main() {
use std::fmt::Debug;
use bumpalo::Bump;
use bumpalo::boxed::Box as BumpBox;
use bumpalo::collections::Vec as BumpVec;
/// Demonstrates basic bump allocation with simple types
pub fn basic_allocation() -> Vec<i32> {
    let bump = Bump::new();

    // Allocate individual values
    let x = bump.alloc(10);
    let y = bump.alloc(20);
    let z = bump.alloc(30);

    // Values are valid for the lifetime of the bump allocator
    vec![*x, *y, *z]
}
/// Shows how to allocate strings in the bump allocator
pub fn allocate_strings(bump: &Bump) -> &str {
    // Allocate a string slice
    let hello = bump.alloc_str("Hello, ");
    let world = bump.alloc_str("World!");

    // Concatenate using bump allocation

    (bump.alloc_str(&format!("{}{}", hello, world))) as _
}
/// Allocates slices efficiently in the bump allocator
pub fn allocate_slices(bump: &Bump) -> &[i32] {
    // Allocate a slice from a vector
    let data = vec![1, 2, 3, 4, 5];
    bump.alloc_slice_copy(&data)
}
/// Demonstrates using bump-allocated collections
pub fn bump_collections() -> Vec<i32> {
    let bump = Bump::new();

    // Create a bump-allocated vector
    let mut vec = BumpVec::new_in(&bump);
    vec.push(1);
    vec.push(2);
    vec.push(3);

    // Convert to standard Vec for return
    vec.iter().copied().collect()
}
/// Shows arena-style allocation for AST nodes
#[derive(Debug, Clone)]
pub enum Expr<'a> {
    Number(i64),
    Add(&'a Expr<'a>, &'a Expr<'a>),
    Multiply(&'a Expr<'a>, &'a Expr<'a>),
}
pub fn build_ast<'a>(bump: &'a Bump) -> &'a Expr<'a> {
    // Build expression: (2 + 3) * 4
    let two = bump.alloc(Expr::Number(2));
    let three = bump.alloc(Expr::Number(3));
    let four = bump.alloc(Expr::Number(4));

    let add = bump.alloc(Expr::Add(two, three));
    bump.alloc(Expr::Multiply(add, four))
}
/// Evaluates an AST expression
pub fn eval_expr(expr: &Expr) -> i64 {
    match expr {
        Expr::Number(n) => *n,
        Expr::Add(a, b) => eval_expr(a) + eval_expr(b),
        Expr::Multiply(a, b) => eval_expr(a) * eval_expr(b),
    }
}
/// Demonstrates using bump allocation for a simple compiler IR
pub struct Function<'a> {
    pub name: &'a str,
    pub params: BumpVec<'a, &'a str>,
    pub body: BumpVec<'a, Statement<'a>>,
}
pub enum Statement<'a> {
    Let(&'a str, &'a Expr<'a>),
    Return(&'a Expr<'a>),
}
pub fn build_function<'a>(bump: &'a Bump) -> Function<'a> {
    let mut params = BumpVec::new_in(bump);
    let x = bump.alloc_str("x");
    let y = bump.alloc_str("y");
    params.push(&*x);
    params.push(&*y);

    let mut body = BumpVec::new_in(bump);

    // let sum = x + y
    let x = bump.alloc(Expr::Number(10));
    let y = bump.alloc(Expr::Number(20));
    let sum_expr = bump.alloc(Expr::Add(x, y));
    body.push(Statement::Let("sum", sum_expr));

    // return sum * 2
    let two = bump.alloc(Expr::Number(2));
    let result = bump.alloc(Expr::Multiply(sum_expr, two));
    body.push(Statement::Return(result));

    Function {
        name: bump.alloc_str("calculate"),
        params,
        body,
    }
}
/// Shows how to reset and reuse a bump allocator
pub fn reset_and_reuse() -> (Vec<i32>, Vec<i32>) {
    let mut bump = Bump::new();

    // First allocation cycle
    let first = {
        let vec = BumpVec::new_in(&bump);
        let mut vec = vec;
        vec.extend([1, 2, 3].iter().copied());
        vec.iter().copied().collect::<Vec<_>>()
    };

    // Reset the allocator to reclaim all memory
    bump.reset();

    // Second allocation cycle reuses the same memory
    let second = {
        let vec = BumpVec::new_in(&bump);
        let mut vec = vec;
        vec.extend([4, 5, 6].iter().copied());
        vec.iter().copied().collect::<Vec<_>>()
    };

    (first, second)
}
/// Demonstrates scoped allocation for temporary computations
pub fn scoped_allocation() -> i32 {
    let bump = Bump::new();

    // Create a temporary allocation scope

    // Memory is automatically freed when bump goes out of scope
    {
        // Allocate temporary working data
        let mut temps = BumpVec::new_in(&bump);
        for i in 0..100 {
            temps.push(i);
        }

        // Process data
        temps.iter().sum::<i32>()
    }
}
/// Shows using bump allocation with closures
pub fn with_allocator<F, R>(f: F) -> R
where
    F: FnOnce(&Bump) -> R, {
    let bump = Bump::new();
    f(&bump)
}
pub fn closure_example() -> i32 {
    with_allocator(|bump| {
        let numbers = bump.alloc_slice_copy(&[1, 2, 3, 4, 5]);
        numbers.iter().sum()
    })
}
/// Custom type that uses bump allocation internally
pub struct SymbolTable<'a> {
    bump: &'a Bump,
    symbols: BumpVec<'a, &'a str>,
}
impl<'a> SymbolTable<'a> {
    pub fn new(bump: &'a Bump) -> Self {
        Self {
            bump,
            symbols: BumpVec::new_in(bump),
        }
    }

    pub fn intern(&mut self, s: &str) -> usize {
        // Check if symbol already exists
        for (i, &sym) in self.symbols.iter().enumerate() {
            if sym == s {
                return i;
            }
        }

        // Allocate new symbol
        let symbol = self.bump.alloc_str(s);
        let id = self.symbols.len();
        self.symbols.push(symbol);
        id
    }

    pub fn get(&self, id: usize) -> Option<&'a str> {
        self.symbols.get(id).copied()
    }
}
/// Demonstrates using bump allocation for graph structures
pub struct Node<'a> {
    pub value: i32,
    pub children: BumpVec<'a, &'a Node<'a>>,
}
pub fn build_tree<'a>(bump: &'a Bump) -> &'a Node<'a> {
    // Build a simple tree structure
    let leaf1 = bump.alloc(Node {
        value: 1,
        children: BumpVec::new_in(bump),
    });

    let leaf2 = bump.alloc(Node {
        value: 2,
        children: BumpVec::new_in(bump),
    });

    let mut branch_children = BumpVec::new_in(bump);
    branch_children.push(&*leaf1);
    branch_children.push(&*leaf2);

    bump.alloc(Node {
        value: 3,
        children: branch_children,
    })
}
/// Shows statistics about memory usage
pub fn allocation_stats() {
    let mut bump = Bump::new();

    // Allocate some data
    for i in 0..1000 {
        bump.alloc(i);
    }

    // Get allocation statistics
    let allocated = bump.allocated_bytes();
    println!("Allocated: {} bytes", allocated);

    // Reset and check again
    bump.reset();
    let after_reset = bump.allocated_bytes();
    println!("After reset: {} bytes", after_reset);
}
/// Shows efficient string building with bump allocation
pub struct StringBuilder<'a> {
    bump: &'a Bump,
    parts: BumpVec<'a, &'a str>,
}
impl<'a> StringBuilder<'a> {
    pub fn new(bump: &'a Bump) -> Self {
        Self {
            bump,
            parts: BumpVec::new_in(bump),
        }
    }

    pub fn append(&mut self, s: &str) {
        let part = self.bump.alloc_str(s);
        self.parts.push(part);
    }

    pub fn build(&self) -> String {
        self.parts.iter().flat_map(|s| s.chars()).collect()
    }
}
#[cfg(test)]
mod tests {
    use super::*;

    #[test]
    fn test_basic_allocation() {
        let result = basic_allocation();
        assert_eq!(result, vec![10, 20, 30]);
    }

    #[test]
    fn test_string_allocation() {
        let bump = Bump::new();
        let result = allocate_strings(&bump);
        assert_eq!(result, "Hello, World!");
    }

    #[test]
    fn test_ast_evaluation() {
        let bump = Bump::new();
        let ast = build_ast(&bump);
        assert_eq!(eval_expr(ast), 20); // (2 + 3) * 4 = 20
    }

    #[test]
    fn test_reset_reuse() {
        let (first, second) = reset_and_reuse();
        assert_eq!(first, vec![1, 2, 3]);
        assert_eq!(second, vec![4, 5, 6]);
    }

    #[test]
    fn test_symbol_table() {
        let bump = Bump::new();
        let mut table = SymbolTable::new(&bump);

        let id1 = table.intern("hello");
        let id2 = table.intern("world");
        let id3 = table.intern("hello"); // Should return same ID

        assert_eq!(id1, id3);
        assert_ne!(id1, id2);
        assert_eq!(table.get(id1), Some("hello"));
        assert_eq!(table.get(id2), Some("world"));
    }

    #[test]
    fn test_tree_building() {
        let bump = Bump::new();
        let tree = build_tree(&bump);

        assert_eq!(tree.value, 3);
        assert_eq!(tree.children.len(), 2);
        assert_eq!(tree.children[0].value, 1);
        assert_eq!(tree.children[1].value, 2);
    }

    #[test]
    fn test_string_builder() {
        let bump = Bump::new();
        let mut builder = StringBuilder::new(&bump);

        builder.append("Hello");
        builder.append(", ");
        builder.append("World!");

        assert_eq!(builder.build(), "Hello, World!");
    }
}
/// Demonstrates bump boxes for single-value allocation
pub fn bump_box_example() -> i32 {
    let bump = Bump::new();

    // Create a bump-allocated box
    let boxed: BumpBox<i32> = BumpBox::new_in(100, &bump);

    // Bump boxes can be dereferenced like regular boxes
    *boxed
}
}

Bump boxes provide a Box-like interface while using arena allocation under the hood.

String Building

Efficient string construction without repeated allocations:

#![allow(unused)]
fn main() {
use std::fmt::Debug;
use bumpalo::Bump;
use bumpalo::boxed::Box as BumpBox;
use bumpalo::collections::Vec as BumpVec;
/// Demonstrates basic bump allocation with simple types
pub fn basic_allocation() -> Vec<i32> {
    let bump = Bump::new();

    // Allocate individual values
    let x = bump.alloc(10);
    let y = bump.alloc(20);
    let z = bump.alloc(30);

    // Values are valid for the lifetime of the bump allocator
    vec![*x, *y, *z]
}
/// Shows how to allocate strings in the bump allocator
pub fn allocate_strings(bump: &Bump) -> &str {
    // Allocate a string slice
    let hello = bump.alloc_str("Hello, ");
    let world = bump.alloc_str("World!");

    // Concatenate using bump allocation

    (bump.alloc_str(&format!("{}{}", hello, world))) as _
}
/// Allocates slices efficiently in the bump allocator
pub fn allocate_slices(bump: &Bump) -> &[i32] {
    // Allocate a slice from a vector
    let data = vec![1, 2, 3, 4, 5];
    bump.alloc_slice_copy(&data)
}
/// Demonstrates using bump-allocated collections
pub fn bump_collections() -> Vec<i32> {
    let bump = Bump::new();

    // Create a bump-allocated vector
    let mut vec = BumpVec::new_in(&bump);
    vec.push(1);
    vec.push(2);
    vec.push(3);

    // Convert to standard Vec for return
    vec.iter().copied().collect()
}
/// Shows arena-style allocation for AST nodes
#[derive(Debug, Clone)]
pub enum Expr<'a> {
    Number(i64),
    Add(&'a Expr<'a>, &'a Expr<'a>),
    Multiply(&'a Expr<'a>, &'a Expr<'a>),
}
pub fn build_ast<'a>(bump: &'a Bump) -> &'a Expr<'a> {
    // Build expression: (2 + 3) * 4
    let two = bump.alloc(Expr::Number(2));
    let three = bump.alloc(Expr::Number(3));
    let four = bump.alloc(Expr::Number(4));

    let add = bump.alloc(Expr::Add(two, three));
    bump.alloc(Expr::Multiply(add, four))
}
/// Evaluates an AST expression
pub fn eval_expr(expr: &Expr) -> i64 {
    match expr {
        Expr::Number(n) => *n,
        Expr::Add(a, b) => eval_expr(a) + eval_expr(b),
        Expr::Multiply(a, b) => eval_expr(a) * eval_expr(b),
    }
}
/// Demonstrates using bump allocation for a simple compiler IR
pub struct Function<'a> {
    pub name: &'a str,
    pub params: BumpVec<'a, &'a str>,
    pub body: BumpVec<'a, Statement<'a>>,
}
pub enum Statement<'a> {
    Let(&'a str, &'a Expr<'a>),
    Return(&'a Expr<'a>),
}
pub fn build_function<'a>(bump: &'a Bump) -> Function<'a> {
    let mut params = BumpVec::new_in(bump);
    let x = bump.alloc_str("x");
    let y = bump.alloc_str("y");
    params.push(&*x);
    params.push(&*y);

    let mut body = BumpVec::new_in(bump);

    // let sum = x + y
    let x = bump.alloc(Expr::Number(10));
    let y = bump.alloc(Expr::Number(20));
    let sum_expr = bump.alloc(Expr::Add(x, y));
    body.push(Statement::Let("sum", sum_expr));

    // return sum * 2
    let two = bump.alloc(Expr::Number(2));
    let result = bump.alloc(Expr::Multiply(sum_expr, two));
    body.push(Statement::Return(result));

    Function {
        name: bump.alloc_str("calculate"),
        params,
        body,
    }
}
/// Shows how to reset and reuse a bump allocator
pub fn reset_and_reuse() -> (Vec<i32>, Vec<i32>) {
    let mut bump = Bump::new();

    // First allocation cycle
    let first = {
        let vec = BumpVec::new_in(&bump);
        let mut vec = vec;
        vec.extend([1, 2, 3].iter().copied());
        vec.iter().copied().collect::<Vec<_>>()
    };

    // Reset the allocator to reclaim all memory
    bump.reset();

    // Second allocation cycle reuses the same memory
    let second = {
        let vec = BumpVec::new_in(&bump);
        let mut vec = vec;
        vec.extend([4, 5, 6].iter().copied());
        vec.iter().copied().collect::<Vec<_>>()
    };

    (first, second)
}
/// Demonstrates scoped allocation for temporary computations
pub fn scoped_allocation() -> i32 {
    let bump = Bump::new();

    // Create a temporary allocation scope

    // Memory is automatically freed when bump goes out of scope
    {
        // Allocate temporary working data
        let mut temps = BumpVec::new_in(&bump);
        for i in 0..100 {
            temps.push(i);
        }

        // Process data
        temps.iter().sum::<i32>()
    }
}
/// Shows using bump allocation with closures
pub fn with_allocator<F, R>(f: F) -> R
where
    F: FnOnce(&Bump) -> R, {
    let bump = Bump::new();
    f(&bump)
}
pub fn closure_example() -> i32 {
    with_allocator(|bump| {
        let numbers = bump.alloc_slice_copy(&[1, 2, 3, 4, 5]);
        numbers.iter().sum()
    })
}
/// Custom type that uses bump allocation internally
pub struct SymbolTable<'a> {
    bump: &'a Bump,
    symbols: BumpVec<'a, &'a str>,
}
impl<'a> SymbolTable<'a> {
    pub fn new(bump: &'a Bump) -> Self {
        Self {
            bump,
            symbols: BumpVec::new_in(bump),
        }
    }

    pub fn intern(&mut self, s: &str) -> usize {
        // Check if symbol already exists
        for (i, &sym) in self.symbols.iter().enumerate() {
            if sym == s {
                return i;
            }
        }

        // Allocate new symbol
        let symbol = self.bump.alloc_str(s);
        let id = self.symbols.len();
        self.symbols.push(symbol);
        id
    }

    pub fn get(&self, id: usize) -> Option<&'a str> {
        self.symbols.get(id).copied()
    }
}
/// Demonstrates using bump allocation for graph structures
pub struct Node<'a> {
    pub value: i32,
    pub children: BumpVec<'a, &'a Node<'a>>,
}
pub fn build_tree<'a>(bump: &'a Bump) -> &'a Node<'a> {
    // Build a simple tree structure
    let leaf1 = bump.alloc(Node {
        value: 1,
        children: BumpVec::new_in(bump),
    });

    let leaf2 = bump.alloc(Node {
        value: 2,
        children: BumpVec::new_in(bump),
    });

    let mut branch_children = BumpVec::new_in(bump);
    branch_children.push(&*leaf1);
    branch_children.push(&*leaf2);

    bump.alloc(Node {
        value: 3,
        children: branch_children,
    })
}
/// Shows statistics about memory usage
pub fn allocation_stats() {
    let mut bump = Bump::new();

    // Allocate some data
    for i in 0..1000 {
        bump.alloc(i);
    }

    // Get allocation statistics
    let allocated = bump.allocated_bytes();
    println!("Allocated: {} bytes", allocated);

    // Reset and check again
    bump.reset();
    let after_reset = bump.allocated_bytes();
    println!("After reset: {} bytes", after_reset);
}
/// Demonstrates bump boxes for single-value allocation
pub fn bump_box_example() -> i32 {
    let bump = Bump::new();

    // Create a bump-allocated box
    let boxed: BumpBox<i32> = BumpBox::new_in(100, &bump);

    // Bump boxes can be dereferenced like regular boxes
    *boxed
}
impl<'a> StringBuilder<'a> {
    pub fn new(bump: &'a Bump) -> Self {
        Self {
            bump,
            parts: BumpVec::new_in(bump),
        }
    }

    pub fn append(&mut self, s: &str) {
        let part = self.bump.alloc_str(s);
        self.parts.push(part);
    }

    pub fn build(&self) -> String {
        self.parts.iter().flat_map(|s| s.chars()).collect()
    }
}
#[cfg(test)]
mod tests {
    use super::*;

    #[test]
    fn test_basic_allocation() {
        let result = basic_allocation();
        assert_eq!(result, vec![10, 20, 30]);
    }

    #[test]
    fn test_string_allocation() {
        let bump = Bump::new();
        let result = allocate_strings(&bump);
        assert_eq!(result, "Hello, World!");
    }

    #[test]
    fn test_ast_evaluation() {
        let bump = Bump::new();
        let ast = build_ast(&bump);
        assert_eq!(eval_expr(ast), 20); // (2 + 3) * 4 = 20
    }

    #[test]
    fn test_reset_reuse() {
        let (first, second) = reset_and_reuse();
        assert_eq!(first, vec![1, 2, 3]);
        assert_eq!(second, vec![4, 5, 6]);
    }

    #[test]
    fn test_symbol_table() {
        let bump = Bump::new();
        let mut table = SymbolTable::new(&bump);

        let id1 = table.intern("hello");
        let id2 = table.intern("world");
        let id3 = table.intern("hello"); // Should return same ID

        assert_eq!(id1, id3);
        assert_ne!(id1, id2);
        assert_eq!(table.get(id1), Some("hello"));
        assert_eq!(table.get(id2), Some("world"));
    }

    #[test]
    fn test_tree_building() {
        let bump = Bump::new();
        let tree = build_tree(&bump);

        assert_eq!(tree.value, 3);
        assert_eq!(tree.children.len(), 2);
        assert_eq!(tree.children[0].value, 1);
        assert_eq!(tree.children[1].value, 2);
    }

    #[test]
    fn test_string_builder() {
        let bump = Bump::new();
        let mut builder = StringBuilder::new(&bump);

        builder.append("Hello");
        builder.append(", ");
        builder.append("World!");

        assert_eq!(builder.build(), "Hello, World!");
    }
}
/// Shows efficient string building with bump allocation
pub struct StringBuilder<'a> {
    bump: &'a Bump,
    parts: BumpVec<'a, &'a str>,
}
}
#![allow(unused)]
fn main() {
use std::fmt::Debug;
use bumpalo::Bump;
use bumpalo::boxed::Box as BumpBox;
use bumpalo::collections::Vec as BumpVec;
/// Demonstrates basic bump allocation with simple types
pub fn basic_allocation() -> Vec<i32> {
    let bump = Bump::new();

    // Allocate individual values
    let x = bump.alloc(10);
    let y = bump.alloc(20);
    let z = bump.alloc(30);

    // Values are valid for the lifetime of the bump allocator
    vec![*x, *y, *z]
}
/// Shows how to allocate strings in the bump allocator
pub fn allocate_strings(bump: &Bump) -> &str {
    // Allocate a string slice
    let hello = bump.alloc_str("Hello, ");
    let world = bump.alloc_str("World!");

    // Concatenate using bump allocation

    (bump.alloc_str(&format!("{}{}", hello, world))) as _
}
/// Allocates slices efficiently in the bump allocator
pub fn allocate_slices(bump: &Bump) -> &[i32] {
    // Allocate a slice from a vector
    let data = vec![1, 2, 3, 4, 5];
    bump.alloc_slice_copy(&data)
}
/// Demonstrates using bump-allocated collections
pub fn bump_collections() -> Vec<i32> {
    let bump = Bump::new();

    // Create a bump-allocated vector
    let mut vec = BumpVec::new_in(&bump);
    vec.push(1);
    vec.push(2);
    vec.push(3);

    // Convert to standard Vec for return
    vec.iter().copied().collect()
}
/// Shows arena-style allocation for AST nodes
#[derive(Debug, Clone)]
pub enum Expr<'a> {
    Number(i64),
    Add(&'a Expr<'a>, &'a Expr<'a>),
    Multiply(&'a Expr<'a>, &'a Expr<'a>),
}
pub fn build_ast<'a>(bump: &'a Bump) -> &'a Expr<'a> {
    // Build expression: (2 + 3) * 4
    let two = bump.alloc(Expr::Number(2));
    let three = bump.alloc(Expr::Number(3));
    let four = bump.alloc(Expr::Number(4));

    let add = bump.alloc(Expr::Add(two, three));
    bump.alloc(Expr::Multiply(add, four))
}
/// Evaluates an AST expression
pub fn eval_expr(expr: &Expr) -> i64 {
    match expr {
        Expr::Number(n) => *n,
        Expr::Add(a, b) => eval_expr(a) + eval_expr(b),
        Expr::Multiply(a, b) => eval_expr(a) * eval_expr(b),
    }
}
/// Demonstrates using bump allocation for a simple compiler IR
pub struct Function<'a> {
    pub name: &'a str,
    pub params: BumpVec<'a, &'a str>,
    pub body: BumpVec<'a, Statement<'a>>,
}
pub enum Statement<'a> {
    Let(&'a str, &'a Expr<'a>),
    Return(&'a Expr<'a>),
}
pub fn build_function<'a>(bump: &'a Bump) -> Function<'a> {
    let mut params = BumpVec::new_in(bump);
    let x = bump.alloc_str("x");
    let y = bump.alloc_str("y");
    params.push(&*x);
    params.push(&*y);

    let mut body = BumpVec::new_in(bump);

    // let sum = x + y
    let x = bump.alloc(Expr::Number(10));
    let y = bump.alloc(Expr::Number(20));
    let sum_expr = bump.alloc(Expr::Add(x, y));
    body.push(Statement::Let("sum", sum_expr));

    // return sum * 2
    let two = bump.alloc(Expr::Number(2));
    let result = bump.alloc(Expr::Multiply(sum_expr, two));
    body.push(Statement::Return(result));

    Function {
        name: bump.alloc_str("calculate"),
        params,
        body,
    }
}
/// Shows how to reset and reuse a bump allocator
pub fn reset_and_reuse() -> (Vec<i32>, Vec<i32>) {
    let mut bump = Bump::new();

    // First allocation cycle
    let first = {
        let vec = BumpVec::new_in(&bump);
        let mut vec = vec;
        vec.extend([1, 2, 3].iter().copied());
        vec.iter().copied().collect::<Vec<_>>()
    };

    // Reset the allocator to reclaim all memory
    bump.reset();

    // Second allocation cycle reuses the same memory
    let second = {
        let vec = BumpVec::new_in(&bump);
        let mut vec = vec;
        vec.extend([4, 5, 6].iter().copied());
        vec.iter().copied().collect::<Vec<_>>()
    };

    (first, second)
}
/// Demonstrates scoped allocation for temporary computations
pub fn scoped_allocation() -> i32 {
    let bump = Bump::new();

    // Create a temporary allocation scope

    // Memory is automatically freed when bump goes out of scope
    {
        // Allocate temporary working data
        let mut temps = BumpVec::new_in(&bump);
        for i in 0..100 {
            temps.push(i);
        }

        // Process data
        temps.iter().sum::<i32>()
    }
}
/// Shows using bump allocation with closures
pub fn with_allocator<F, R>(f: F) -> R
where
    F: FnOnce(&Bump) -> R, {
    let bump = Bump::new();
    f(&bump)
}
pub fn closure_example() -> i32 {
    with_allocator(|bump| {
        let numbers = bump.alloc_slice_copy(&[1, 2, 3, 4, 5]);
        numbers.iter().sum()
    })
}
/// Custom type that uses bump allocation internally
pub struct SymbolTable<'a> {
    bump: &'a Bump,
    symbols: BumpVec<'a, &'a str>,
}
impl<'a> SymbolTable<'a> {
    pub fn new(bump: &'a Bump) -> Self {
        Self {
            bump,
            symbols: BumpVec::new_in(bump),
        }
    }

    pub fn intern(&mut self, s: &str) -> usize {
        // Check if symbol already exists
        for (i, &sym) in self.symbols.iter().enumerate() {
            if sym == s {
                return i;
            }
        }

        // Allocate new symbol
        let symbol = self.bump.alloc_str(s);
        let id = self.symbols.len();
        self.symbols.push(symbol);
        id
    }

    pub fn get(&self, id: usize) -> Option<&'a str> {
        self.symbols.get(id).copied()
    }
}
/// Demonstrates using bump allocation for graph structures
pub struct Node<'a> {
    pub value: i32,
    pub children: BumpVec<'a, &'a Node<'a>>,
}
pub fn build_tree<'a>(bump: &'a Bump) -> &'a Node<'a> {
    // Build a simple tree structure
    let leaf1 = bump.alloc(Node {
        value: 1,
        children: BumpVec::new_in(bump),
    });

    let leaf2 = bump.alloc(Node {
        value: 2,
        children: BumpVec::new_in(bump),
    });

    let mut branch_children = BumpVec::new_in(bump);
    branch_children.push(&*leaf1);
    branch_children.push(&*leaf2);

    bump.alloc(Node {
        value: 3,
        children: branch_children,
    })
}
/// Shows statistics about memory usage
pub fn allocation_stats() {
    let mut bump = Bump::new();

    // Allocate some data
    for i in 0..1000 {
        bump.alloc(i);
    }

    // Get allocation statistics
    let allocated = bump.allocated_bytes();
    println!("Allocated: {} bytes", allocated);

    // Reset and check again
    bump.reset();
    let after_reset = bump.allocated_bytes();
    println!("After reset: {} bytes", after_reset);
}
/// Demonstrates bump boxes for single-value allocation
pub fn bump_box_example() -> i32 {
    let bump = Bump::new();

    // Create a bump-allocated box
    let boxed: BumpBox<i32> = BumpBox::new_in(100, &bump);

    // Bump boxes can be dereferenced like regular boxes
    *boxed
}
/// Shows efficient string building with bump allocation
pub struct StringBuilder<'a> {
    bump: &'a Bump,
    parts: BumpVec<'a, &'a str>,
}
#[cfg(test)]
mod tests {
    use super::*;

    #[test]
    fn test_basic_allocation() {
        let result = basic_allocation();
        assert_eq!(result, vec![10, 20, 30]);
    }

    #[test]
    fn test_string_allocation() {
        let bump = Bump::new();
        let result = allocate_strings(&bump);
        assert_eq!(result, "Hello, World!");
    }

    #[test]
    fn test_ast_evaluation() {
        let bump = Bump::new();
        let ast = build_ast(&bump);
        assert_eq!(eval_expr(ast), 20); // (2 + 3) * 4 = 20
    }

    #[test]
    fn test_reset_reuse() {
        let (first, second) = reset_and_reuse();
        assert_eq!(first, vec![1, 2, 3]);
        assert_eq!(second, vec![4, 5, 6]);
    }

    #[test]
    fn test_symbol_table() {
        let bump = Bump::new();
        let mut table = SymbolTable::new(&bump);

        let id1 = table.intern("hello");
        let id2 = table.intern("world");
        let id3 = table.intern("hello"); // Should return same ID

        assert_eq!(id1, id3);
        assert_ne!(id1, id2);
        assert_eq!(table.get(id1), Some("hello"));
        assert_eq!(table.get(id2), Some("world"));
    }

    #[test]
    fn test_tree_building() {
        let bump = Bump::new();
        let tree = build_tree(&bump);

        assert_eq!(tree.value, 3);
        assert_eq!(tree.children.len(), 2);
        assert_eq!(tree.children[0].value, 1);
        assert_eq!(tree.children[1].value, 2);
    }

    #[test]
    fn test_string_builder() {
        let bump = Bump::new();
        let mut builder = StringBuilder::new(&bump);

        builder.append("Hello");
        builder.append(", ");
        builder.append("World!");

        assert_eq!(builder.build(), "Hello, World!");
    }
}
impl<'a> StringBuilder<'a> {
    pub fn new(bump: &'a Bump) -> Self {
        Self {
            bump,
            parts: BumpVec::new_in(bump),
        }
    }

    pub fn append(&mut self, s: &str) {
        let part = self.bump.alloc_str(s);
        self.parts.push(part);
    }

    pub fn build(&self) -> String {
        self.parts.iter().flat_map(|s| s.chars()).collect()
    }
}
}

This avoids the repeated allocations that would occur with String::push_str or format strings.

Performance Characteristics

Bump allocation provides several performance advantages for compilers:

Allocation Speed: O(1) allocation with just a pointer increment and bounds check. No searching for free blocks or managing free lists.

Deallocation Speed: O(1) for the entire arena. No need to track individual object lifetimes or run destructors.

Memory Locality: Sequential allocations are contiguous in memory, providing excellent cache performance during traversal.

Low Overhead: No per-allocation metadata like headers or reference counts. The only overhead is unused space at the end of the current chunk.

Predictable Performance: No garbage collection pauses or reference counting overhead. Performance is deterministic and easy to reason about.

Best Practices

Structure your compiler passes to match arena lifetimes. Each major phase (parsing, type checking, optimization, code generation) can use its own arena that’s dropped when the phase completes.

Avoid storing bump-allocated values in long-lived data structures. The arena lifetime must outlive all references to its allocated values.

Use typed arenas for hot paths. Creating type-specific arenas can eliminate pointer indirection and improve cache performance for frequently accessed types.

Reset and reuse arenas when processing multiple compilation units. This amortizes the cost of the initial memory allocation across all units.

Consider using multiple arenas for different lifetimes. For example, use one arena for the AST that lives through type checking, and another for temporary values during each optimization pass.

Profile your allocator usage to find the optimal chunk size. Larger chunks mean fewer allocations from the system allocator but potentially more wasted space.