Skip to content

Vec::as_mut_slice

Vec methods · Collections

Level: reference · for working programmers

One line: Borrow the whole vector as a &mut [T]. Also free.

pub const fn as_mut_slice(&mut self) -> &mut [T]

Stable since 1.7.0. Callable in a const context since 1.87.0.

Same free view as as_slice, with write access — and the same rule that DerefMut usually inserts it for you, so v.sort() needs no as_mut_slice at all.

The length is fixed. A slice can reorder, overwrite and fill; it can never push or remove. That is exactly the distinction between the two types: Vec owns and resizes, [T] is a window on elements that already exist.

Writing it explicitly is for passing a &mut [T] to a function — which, like &[T], is the signature to prefer, because it also accepts arrays and sub-slices.

split_at_mut is the payoff: two disjoint &mut halves of one buffer, which indexes cannot express and the borrow checker accepts here because the slices provably do not overlap.

While the slice is alive the vector is exclusively borrowed, so a push in between is a compile error — which is what stops the slice dangling when the buffer moves.

Example

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

fn main() {
    let mut v = vec![3, 1, 2];
    let s: &mut [i32] = v.as_mut_slice();
    s.sort();
    println!("{v:?}");

    // Same free view as as_slice, with write access. The LENGTH is fixed:
    // a slice can reorder and overwrite, never push or remove.
    let mut v = vec![1, 2, 3];
    let s = v.as_mut_slice();
    s[0] = 99;
    s.swap(1, 2);
    s.reverse();
    println!("{v:?}");

    // DerefMut inserts it, so most slice mutation needs no as_mut_slice at all.
    let mut v = vec![5, 4, 3];
    v.sort();
    v.fill_with(|| 0);
    println!("{v:?}");

    // Where it earns its keep: handing a &mut [T] to a function.
    fn double_all(xs: &mut [i32]) { for x in xs { *x *= 2; } }
    let mut v = vec![1, 2, 3];
    double_all(v.as_mut_slice());
    double_all(&mut v);
    println!("{v:?}");

    // split_at_mut gives two disjoint &mut halves — impossible with indexes,
    // routine with slices.
    let mut v = vec![1, 2, 3, 4];
    let (left, right) = v.as_mut_slice().split_at_mut(2);
    left[0] = 10;
    right[0] = 30;
    println!("{v:?}");

    // While the slice is alive the Vec is exclusively borrowed, so a push in
    // between is a compile error — which is what stops the slice dangling.
    let mut v = vec![1, 2];
    { let s = v.as_mut_slice(); s[0] = 7; }
    v.push(3);
    println!("{v:?}");
}

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

[1, 2, 3]
[2, 3, 99]
[0, 0, 0]
[4, 8, 12]
[10, 2, 30, 4]
[7, 2, 3]

See also

Vec::as_mut_slice in the standard library ↗