Skip to content

str::get_unchecked_mut

str methods · Strings

Level: reference · for working programmers

One line: get_mut with the checks removed — unsafe, same two-clause contract, mutable result.

pub unsafe fn get_unchecked_mut<I: SliceIndex<str>>(&mut self, i: I) -> &mut I::Output

Stable since 1.20.0. unsafe — the caller carries the invariant described below.

Identical contract to get_unchecked: in range, and both endpoints on character boundaries. The result is a &mut str, so the length-preserving restriction still applies on top.

Two unsafeties compound here — a bad range, and then whatever you write through the result. Keeping the edits ASCII-for-ASCII means the second cannot go wrong, which leaves only the range to justify.

Example

str_get_unchecked_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");

    // Sound: 0..5 is in range and both ends are boundaries.
    unsafe { owned.as_mut_str().get_unchecked_mut(0..5) }.make_ascii_uppercase();
    println!("{owned:?}");

    // The safe spelling of the same edit.
    let mut safe = String::from("hello world");
    if let Some(part) = safe.get_mut(0..5) {
        part.make_ascii_uppercase();
    }
    println!("{safe:?}");

    // Boundaries first, then the edit — the offsets justify the unsafe block.
    let mut accented = String::from("héllo");
    let cut = accented.char_indices().nth(2).unwrap().0;
    println!("cut at byte {cut}, boundary={}", accented.is_char_boundary(cut));
    unsafe { accented.as_mut_str().get_unchecked_mut(cut..) }.make_ascii_uppercase();
    println!("{accented:?}");
}

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

"HELLO world"
"HELLO world"
cut at byte 3, boundary=true
"héLLO"

See also

str::get_unchecked_mut in the standard library ↗

Po polsku

Tutaj zagrożenia się mnożą: najpierw zakres — te same dwa warunki co przy get_unchecked, czyli w granicach łańcucha i oba końce na granicy znaku — a potem jeszcze to, co przez otrzymany &mut str zapiszesz. Drugie da się wyeliminować całkowicie, trzymając się zasady „bajt ASCII za bajt ASCII”, i wtedy do uzasadnienia zostaje sam zakres; dokładnie tak postępuje przykład powyżej, w którym przesunięcie pochodzi z char_indices, a edycją jest make_ascii_uppercase. Dla polszczyzny warto od razu założyć, że to jedyne sensowne użycie: &mut str nie może zmienić długości, a nasze litery zajmują po dwa bajty, więc zmiana wielkości liter w miejscu i tak ich nie dotknie — w wyniku "héLLO" widać, że é zostało nietknięte, i ż zachowałoby się identycznie. Prawdziwą zmianę wielkości liter daje dopiero to_uppercase() wraz z nową alokacją, a jeśli chodziło wyłącznie o pominięcie sprawdzeń, to get_mut kosztuje jedno porównanie i nie wymaga unsafe.

Szukaj po polsku: mutowalny wycinek łańcucha · edycja w miejscu · rust get_unchecked_mut · rust make_ascii_uppercase in place