Skip to content

str::to_lowercase

str methods · Strings

Level: reference · for working programmers

One line: A new String lowercased by the full Unicode rules — which can change the length, and is context-sensitive for Greek sigma.

pub fn to_lowercase(&self) -> String

Stable since 1.2.0.

It allocates, because the result need not fit: case mapping is not a per-byte or even a per-character operation. Three facts follow, and each one breaks a plausible assumption:

  • The length can change. "İ" (Latin capital I with dot above, 2 bytes) lowercases to 3 bytes.
  • It is context-sensitive. A Greek capital sigma lowercases to ς at the end of a word and σ elsewhere — "ΣΣ".to_lowercase() is "σς", two different characters from the same input character.
  • It is not locale-aware. Turkish requires dotless ı for a lowercased I; std gives i, because a locale-correct answer needs a locale, and str has none. If you need Turkish, you need a crate.

For case-insensitive comparison, prefer eq_ignore_ascii_case when the data is ASCII — it allocates nothing. Lowercasing both sides works for Unicode but is not the same as proper caseless matching, which needs case folding rather than case mapping.

Example

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

fn main() {
    println!("{:?}", "Hello World".to_lowercase());

    // The length can change.
    let dotted = "\u{0130}";                  // LATIN CAPITAL LETTER I WITH DOT ABOVE
    println!("{} bytes -> {} bytes", dotted.len(), dotted.to_lowercase().len());

    // Context-sensitive: one input character, two different outputs.
    println!("{:?}", "ΣΣ".to_lowercase());
    println!("{:?}", "ΟΔΟΣ".to_lowercase());

    // Not locale-aware: Turkish would want 'ı' here.
    println!("{:?}", "I".to_lowercase());

    // Allocates; the original is untouched.
    let original = "MiXeD";
    let lowered = original.to_lowercase();
    println!("{original:?} {lowered:?}");

    // Case-insensitive comparison, ASCII and otherwise.
    println!("{}", "HELLO".eq_ignore_ascii_case("hello"));
    println!("{}", "ΑΒΓ".to_lowercase() == "αβγ".to_lowercase());
}

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

"hello world"
2 bytes -> 3 bytes
"σς"
"οδος"
"i"
"MiXeD" "mixed"
true
true

See also

str::to_lowercase in the standard library ↗

Po polsku

Dla polszczyzny to jest właśnie ta metoda, i da się powiedzieć wprost dlaczego: pełne reguły Unicode obejmują komplet naszych znaków diakrytycznych ("ŻÓŁW".to_lowercase() daje "żółw"), a to, że metoda nie zna ustawień lokalnych (locale) — co psuje sprawę tureckiemu I, bo std zwraca i zamiast ı — polskiemu nie szkodzi w niczym, ponieważ polski nie ma reguł zależnych od języka. Płaci się za to trzema niespodziankami, których wersja ASCII nie ma: metoda alokuje nowy String, długość może się zmienić ("İ" zajmuje 2 bajty, a po zamianie na małe litery 3) i wynik bywa zależny od kontekstu — greckie "ΣΣ" daje "σς", dwa różne znaki z dwóch takich samych. Praktyczny wniosek przy polskim tekście jest jeden: eq_ignore_ascii_case tu nie zadziała ("ŁÓDŹ".eq_ignore_ascii_case("łódź") to false, bo ta metoda porównuje wielkość liter wyłącznie w ASCII), trzeba zamienić na małe litery obie strony — pamiętając, że to nadal odwzorowanie wielkości liter, a nie pełne case folding.

Szukaj po polsku: małe litery a polskie znaki diakrytyczne · porównywanie bez rozróżniania wielkości liter · rust to_lowercase · rust case folding vs case mapping