Skip to content

Vec::leak

Vec methods · Collections

Level: reference · for working programmers

One line: Consume the vector and return a slice that outlives it, by never freeing the buffer.

pub fn leak<'a>(self) -> &'a mut [T]
where
    A: 'a,

Stable since 1.47.0.

The memory is deliberately not reclaimed. In exchange you get a &'a mut [T] whose lifetime you choose — usually 'static.

The use is a value built once at startup and needed for the whole run: a lookup table computed from configuration, an interned string set. The alternatives are a static (which cannot be computed at runtime in general), OnceLock, or threading an owner through every call — and leak is sometimes simply the clearest of the four.

'static is the common choice, not the required one; a shorter lifetime is legal and just as leaky.

There is no un-leak. Reclaiming means rebuilding a Vec from the raw parts and dropping it, which is unsafe and needs the original capacity — so if you might want the memory back, use into_raw_parts instead, which hands you all three numbers.

Box::leak is the same idea for a single value. And most of the time the honest answer is neither: keep the Vec alive and pass &[T].

Example

vec_leak.rs in full — pasted here by tools/run_examples.py from the file CI compiles and runs.

fn main() {
    // Consumes the Vec and gives back a mutable slice that outlives it,
    // by never freeing the buffer.
    let leaked: &'static mut [i32] = vec![1, 2, 3].leak();
    leaked[0] = 99;
    println!("{leaked:?}");

    // It is a slice, so the length is fixed and every slice method works.
    leaked.sort();
    println!("sorted in place: {leaked:?} first {:?}", leaked.first());

    // Why it exists: a value the program builds once at startup and needs for
    // the whole run, without a static, a Box::leak dance, or an Rc.
    let table: &'static [u8] = vec![0u8, 1, 4, 9, 16].leak();
    fn lookup(t: &'static [u8], i: usize) -> u8 { t[i] }
    println!("lookup(3) = {}", lookup(table, 3));

    // The lifetime is inferred, and 'static is only the most common choice.
    // A shorter one is legal and just as leaky.
    let short: &mut [u8] = vec![7, 8].leak();
    println!("borrowed for less than 'static: {short:?}");

    // The memory is NOT freed. If you need it back, reconstruct and drop —
    // which is the only way, and it is unsafe.
    let v = vec![1u8, 2, 3];
    let (ptr, len, cap) = v.into_raw_parts();
    let reclaimed = unsafe { Vec::from_raw_parts(ptr, len, cap) };
    println!("reclaimed instead of leaked: {reclaimed:?}");

    // Box::leak is the same idea for a single value.
    let one: &'static mut u32 = Box::leak(Box::new(42));
    *one += 1;
    println!("Box::leak: {one}");

    // And the honest alternative most of the time: keep the Vec alive.
    let owned = vec![1, 2, 3];
    fn borrow(xs: &[i32]) -> usize { xs.len() }
    println!("no leak needed: {}", borrow(&owned));
}

Verified output of vec_leak.rs — regenerated by tools/run_examples.py, never hand-typed.

[99, 2, 3]
sorted in place: [2, 3, 99] first Some(2)
lookup(3) = 9
borrowed for less than 'static: [7, 8]
reclaimed instead of leaked: [1, 2, 3]
Box::leak: 43
no leak needed: 3

See also

Vec::leak in the standard library ↗