Skip to content

str::split_at_mut

str methods · Strings

Level: reference · for working programmers

One line: split_at for a &mut str — two mutable halves at once, which the borrow checker would otherwise refuse.

pub const fn split_at_mut(&mut self, mid: usize) -> (&mut str, &mut str)

Stable since 1.4.0. Usable in a const context.

Two &mut into the same string cannot be produced by ordinary borrowing, because the compiler cannot see that the ranges do not overlap. split_at_mut is the escape hatch: it consumes one &mut str and hands back two that provably cover disjoint bytes.

The panics are identical to split_at — out of range, or inside a character.

What you can then do with the halves is limited, because a &mut str cannot change length. In practice that means the ASCII in-place edits (make_ascii_uppercase) or unsafe byte work. Anything that resizes has to go through String.

Example

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

fn main() {
    let mut owned = String::from("hello world");

    let (left, right) = owned.as_mut_str().split_at_mut(5);
    left.make_ascii_uppercase();
    right.make_ascii_lowercase();
    println!("{owned}");

    // Two &mut into one string, which plain borrowing cannot express.
    let mut s = String::from("abcdef");
    let (a, b) = s.as_mut_str().split_at_mut(3);
    println!("{a:?} {b:?}");
    a.make_ascii_uppercase();
    println!("{s}");

    // The checked form refuses instead of panicking.
    let mut acc = String::from("héllo");
    println!("{:?}", acc.as_mut_str().split_at_mut_checked(2).is_none());
}

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

HELLO world
"abc" "def"
ABCdef
true

See also

str::split_at_mut in the standard library ↗

Po polsku

Zwykłe pożyczanie (borrowing) nie pozwala uzyskać dwóch &mut do jednego tekstu — reguła „wielu czytających albo jeden piszący” nie zna wyjątku „ale te zakresy się nie nakładają”, bo borrow checker nie potrafi tego sam udowodnić. split_at_mut jest właśnie tą furtką: zjada jedną referencję mutowalną i oddaje dwie, które z samej konstrukcji pokrywają rozłączne bajty; panikuje przy tym w tych samych dwóch sytuacjach co split_at — offset poza zakresem albo w środku znaku. Warto od razu wiedzieć, co takimi połówkami da się zrobić: &mut str nie może zmienić długości, więc w praktyce zostają edycje ASCII w miejscu, a make_ascii_uppercase podnosi wyłącznie litery az, przez co „żółw” zamienia się w „żółW”, nie w „ŻÓŁW”. Prawdziwa zmiana wielkości polskich liter to to_uppercase, które zwraca nowy String — wszystko, co może zmienić długość tekstu, musi iść przez String, a nie przez &mut str.

Szukaj po polsku: dwie referencje mutowalne naraz · rozłączne wycinki tekstu · rust split_at_mut two mutable borrows · rust make_ascii_uppercase non-ascii