Skip to content

String::extend_from_within

String methods · Strings

Level: reference · for working programmers

One line: Appends a copy of one of the string's own ranges to its end — self-append without a temporary.

pub fn extend_from_within<R>(&mut self, src: R)
where
    R: RangeBounds<usize>,

Stable since 1.87.0.

s.extend_from_within(0..3) copies the first three bytes onto the end. Written the obvious way — s.push_str(&s[0..3]) — the borrow checker refuses it: push_str needs &mut s while the argument still borrows s. The usual workaround is a temporary String, and this method removes it.

The range is byte offsets and panics on the same two conditions as slicing, plus out of range.

s.extend_from_within(..) doubles the string, which is the tidiest way to repeat it once.

Stable since 1.87.

Example

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

fn main() {
    let mut s = String::from("abc");
    s.extend_from_within(0..2);
    println!("{s:?}");

    // Doubling.
    let mut d = String::from("xy");
    d.extend_from_within(..);
    println!("{d:?}");

    // The version the borrow checker refuses, and its usual workaround:
    //     s.push_str(&s[0..2]);            // E0502
    let mut w = String::from("abc");
    let temp = w[0..2].to_string();
    w.push_str(&temp);
    println!("{w:?} (via a temporary)");

    // Byte offsets, with the usual boundary rule.
    let mut accented = String::from("héllo");
    println!("boundary at 2? {}", accented.is_char_boundary(2));
    accented.extend_from_within(0..3);
    println!("{accented:?}");
}

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

"abcab"
"xyxy"
"abcab" (via a temporary)
boundary at 2? false
"héllohé"

See also

String::extend_from_within in the standard library ↗

Po polsku

extend_from_within dopisuje na koniec łańcucha znaków kopię jego własnego fragmentu i istnieje dokładnie po to, żeby nie walczyć z borrow checkerem: oczywisty zapis s.push_str(&s[0..3]) się nie skompiluje, bo push_str żąda &mut s, podczas gdy argument wciąż trzyma współdzieloną referencję do s. Starsze polskie poradniki każą w tym miejscu zrobić tymczasowy String (let temp = s[0..2].to_string();) — to działa, ale kosztuje dodatkową alokację, a od wersji 1.87 jest już zbędne. Zakres podaje się w bajtach, nie w znakach, więc na "héllo" zakres 0..3 dokłada "hé" (samo é zajmuje dwa bajty), a trafienie w środek znaku kończy się paniką — ta sama reguła granic co przy zwykłym wycinku. Skrót s.extend_from_within(..) podwaja cały łańcuch i jest najkrótszym sposobem na powtórzenie go raz.

Szukaj po polsku: dopisywanie do łańcucha znaków · granica znaku UTF-8 · rust extend_from_within · rust push_str borrow checker E0502