#105 Apr 27, 2026

105. Vec::extend_from_within — Duplicate a Range Without Fighting the Borrow Checker

Trying to copy a slice of a Vec back onto the end of itself? v.extend_from_slice(&v[..k]) won’t compile — &v and &mut v collide. extend_from_within is the one-call answer.

The borrow checker says no

It looks innocent: take the first few bytes of a buffer and append them to the end. The naïve write doesn’t even reach the type checker without complaint:

1
2
3
let mut buf: Vec<u8> = vec![0xCA, 0xFE, 0xBA, 0xBE];
// buf.extend_from_slice(&buf[..2]);
// ^^ error: cannot borrow `buf` as immutable because it is also borrowed as mutable

extend_from_slice needs &mut self, and &buf[..2] is an immutable borrow of the same Vec. Two borrows, one of them mutable, same value — instant rejection.

The usual workarounds bloat the call site. Either make a temporary copy, or reach for unsafe and a raw pointer dance:

1
2
3
4
5
6
let mut buf: Vec<u8> = vec![0xCA, 0xFE, 0xBA, 0xBE];

let head: Vec<u8> = buf[..2].to_vec();   // extra allocation
buf.extend_from_slice(&head);

assert_eq!(buf, [0xCA, 0xFE, 0xBA, 0xBE, 0xCA, 0xFE]);

A whole heap allocation just to copy two bytes inside a vector you already own. There’s a better way.

extend_from_within — one call, no temp

Vec::extend_from_within takes a range into self and appends those elements. No second buffer, no unsafe, no fight with the borrow checker:

1
2
3
4
let mut buf: Vec<u8> = vec![0xCA, 0xFE, 0xBA, 0xBE];
buf.extend_from_within(..2);

assert_eq!(buf, [0xCA, 0xFE, 0xBA, 0xBE, 0xCA, 0xFE]);

It accepts any RangeBounds<usize>..k, i..j, i..=j, .. — so you can grab whatever slice you want, including the whole Vec:

1
2
3
4
let mut v = vec![1, 2, 3];
v.extend_from_within(..);   // double the contents

assert_eq!(v, [1, 2, 3, 1, 2, 3]);

It requires T: Clone, and clones each element exactly once. For Copy types like primitives it lowers to a single memcpy.

A real use: building patterns

It’s especially nice for building repeating or growing patterns where each step depends on the previous one — think DSP buffers, simple test fixtures, or doubling tricks:

1
2
3
4
5
6
7
let mut data = vec![1u32];
for _ in 0..4 {
    data.extend_from_within(..); // double in place
}

assert_eq!(data.len(), 16);
assert!(data.iter().all(|&x| x == 1));

When to reach for it

Any time you’d write v.extend_from_slice(&v[range]) and the borrow checker stops you, swap in v.extend_from_within(range). Stable since Rust 1.53, exists for both Vec<T> and VecDeque<T>, and quietly turns a frustrating compile error into a one-liner.

← Previous 103. bool::then_some — Turn a Condition Into an Option Without an if Next → 106. Iterator::by_ref — Take Part of an Iterator and Keep the Rest