str::from_utf8_unchecked¶
Level: reference · for working programmers
One line: Reinterprets &[u8] as &str with no validation — unsafe, and undefined behaviour if the bytes are not valid UTF-8.
Stable since 1.87.0. unsafe — the caller carries the invariant described below. Usable in a const context.
The contract is one clause: the bytes must already be valid UTF-8. Nothing checks, and a &str over invalid bytes is UB rather than a wrong answer — later calls are entitled to skip bounds and boundary reasoning because the invariant is assumed.
The check being skipped is a single linear scan, and it is fast. So the only honest justification is that the bytes provably came from a &str in the first place — a round trip through as_bytes, or a buffer your own encoder filled.
"I validated it earlier" is weaker than it sounds if anything could have written to the buffer since. When in doubt, from_utf8 and handle the Err.
Example¶
str_from_utf8_unchecked.rs in full — pasted here by tools/run_examples.py from the file CI compiles and runs.
// The invalid byte arrays below are the point of the example, so the
// lint that spots them is turned off rather than worked around.
#![allow(invalid_from_utf8)]
fn main() {
let s = "héllo";
// Sound: these bytes came from a &str a moment ago.
let bytes = s.as_bytes();
let back = unsafe { str::from_utf8_unchecked(bytes) };
println!("{back:?} identical={}", back == s);
// The check being skipped, for comparison.
println!("{:?}", str::from_utf8(bytes));
// What the checked version refuses -- and what the unchecked one would
// have made undefined behaviour instead of an error.
let invalid = [0xff, 0xfe];
println!("{:?}", str::from_utf8(&invalid).is_err());
// A round trip through a Vec, still sound.
let owned: Vec<u8> = s.as_bytes().to_vec();
println!("{:?}", unsafe { str::from_utf8_unchecked(&owned) });
}
Verified output of str_from_utf8_unchecked.rs — regenerated by tools/run_examples.py, never hand-typed.
See also¶
str::from_utf8— the checked versionstr::from_utf8_unchecked_mut— the mutable counterpartstr::as_bytes— the direction that is always soundString::from_utf8_unchecked— the owning version
str::from_utf8_unchecked in the standard library ↗
Po polsku¶
from_utf8_unchecked niczego nie sprawdza — po prostu każe patrzeć na te same bajty jak na &str. Koszt pomyłki warto nazwać dokładnie: to nie jest „zepsuty napis”, tylko niezdefiniowane zachowanie (undefined behaviour), bo kolejne metody str mają prawo pominąć sprawdzanie granic znaków właśnie dlatego, że ten niezmiennik uznają za dany. unsafe nie znaczy tu „kod niebezpieczny”, tylko „kompilator przestaje sprawdzać, umowę podpisujesz ty”, a umowa ma jeden punkt: bajty już są poprawnym UTF-8. Oszczędzasz jedno liniowe przejście po buforze, więc jedynym uczciwym uzasadnieniem jest pochodzenie danych — bajty wyszły przed chwilą z &str przez as_bytes() — a nie „przecież sprawdzałem je wcześniej”: jeśli od tamtej pory cokolwiek mogło do bufora pisać, tamto sprawdzenie jest już nieważne.
Szukaj po polsku: niezdefiniowane zachowanie · niezmiennik typu · kontrakt bezpieczeństwa · rust from_utf8_unchecked UB · rust unsafe safety contract