Skip to content

Vec::push_mut

Vec methods · Collections

Level: reference · for working programmers

One line: push, returning a &mut to the element it just stored.

pub fn push_mut(&mut self, value: T) -> &mut T

Stable since 1.95.0. Its const form is still unstable.

The value is appended exactly as push appends it; the difference is the return. That saves the push-then-index-the-last dance, which repeats a bounds check and reads worse:

fn main() {
    let mut v: Vec<String> = Vec::new();
    let slot = v.push_mut(String::from("Ada"));
    slot.push_str(" Lovelace");
    println!("{v:?}");   // ["Ada Lovelace"]
}

It earns its keep when the element is built in stages — push an empty row, then fill it — which otherwise needs an index or a last_mut().unwrap().

It is #[must_use]: ignoring the reference means you wanted push.

The borrow is exclusive and lasts as long as you hold it, so no second push while the handle is alive. Dropping it first — a block, or just letting it fall out of scope — is the whole discipline.

Stable since 1.95.0. Before that the spelling was v.push(x); v.last_mut().unwrap().

Example

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

fn main() {
    // push_mut appends and hands back a &mut to the element it just stored.
    let mut v: Vec<String> = Vec::new();
    let slot = v.push_mut(String::from("Ada"));
    slot.push_str(" Lovelace");
    println!("{v:?}");

    // Without it the idiom is push-then-index-the-last, which repeats the
    // bounds check and reads worse.
    let mut old = Vec::new();
    old.push(String::from("Ben"));
    let n = old.len();
    old[n - 1].push_str(" Franklin");
    println!("{old:?}");

    // It shines when the element is built in stages.
    let mut rows: Vec<Vec<u8>> = Vec::new();
    for start in [1u8, 10, 100] {
        let row = rows.push_mut(Vec::new());
        row.push(start);
        row.push(start + 1);
    }
    println!("{rows:?}");

    // The borrow is exclusive and lasts as long as you hold it: no second
    // push while `slot` is alive. Dropping it first is the whole discipline.
    let mut v = vec![1, 2];
    {
        let slot = v.push_mut(3);
        *slot *= 10;
    }
    v.push(4);
    println!("{v:?}");

    // Stable since 1.95 — before that this was push followed by last_mut().
    let mut v = vec![1];
    v.push(2);
    if let Some(last) = v.last_mut() { *last = 99; }
    println!("the pre-1.95 spelling: {v:?}");
}

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

["Ada Lovelace"]
["Ben Franklin"]
[[1, 2], [10, 11], [100, 101]]
[1, 2, 30, 4]
the pre-1.95 spelling: [1, 99]

See also

Vec::push_mut in the standard library ↗