Vec::extend_from_within¶
Level: reference · for working programmers
One line: Clone a range of this vector onto its own end.
Stable since 1.53.0.
The one that needs no second vector. The obvious hand-written version does not compile:
fn main() {
let mut v = vec![0, 1, 2, 3];
// v.extend_from_slice(&v[1..3]); // error[E0502]: cannot borrow `v` as mutable
// // because it is also borrowed as immutable
v.extend_from_within(1..3);
println!("{v:?}"); // [0, 1, 2, 3, 1, 2]
}
extend_from_slice would need &self and &mut self at the same time. extend_from_within takes only &mut self and reads the range internally, which is why the method exists at all rather than being a two-liner.
Any RangeBounds<usize> shape works — .., 2.., ..=1, 1..3. The full range doubles the vector, and repeated doubling is the cheap way to build a long repeating pattern.
T: Clone, and the clone really happens: the appended elements are independent, not aliases.
Panics if the range is out of bounds or inverted.
Example¶
vec_extend_from_within.rs in full — pasted here by tools/run_examples.py from the file CI compiles and runs.
fn main() {
// Copies a range of this vector onto its own end. No second vector,
// no temporary, no borrow conflict.
let mut v = vec![0, 1, 2, 3, 4];
v.extend_from_within(1..3);
println!("{v:?}");
// The obvious hand-written version does not compile: extend_from_slice
// would need &self and &mut self at the same time.
// v.extend_from_slice(&v[1..3]); // error[E0502]
// Full range doubles the vector.
let mut v = vec!["a", "b", "c"];
v.extend_from_within(..);
println!("{v:?}");
// Any RangeBounds shape works.
let mut v = vec![1, 2, 3, 4];
v.extend_from_within(2..);
println!("2.. {v:?}");
let mut v = vec![1, 2, 3, 4];
v.extend_from_within(..=1);
println!("..=1 {v:?}");
// T: Clone, and the clone really happens — this is a copy, not an alias.
let mut v = vec![String::from("x")];
v.extend_from_within(..);
v[0].push('!');
println!("{v:?}");
// Repeated doubling is how you build a long repeating pattern cheaply.
let mut pattern = vec![1u8, 2, 3];
while pattern.len() < 12 { pattern.extend_from_within(..); }
println!("{pattern:?} len {}", pattern.len());
// An out-of-range end panics, like any slice index.
let hook = std::panic::take_hook();
std::panic::set_hook(Box::new(|_| {}));
let caught = std::panic::catch_unwind(|| {
let mut v = vec![1, 2];
v.extend_from_within(0..9);
});
std::panic::set_hook(hook);
println!("out-of-range range panicked: {}", caught.is_err());
}
Verified output of vec_extend_from_within.rs — regenerated by tools/run_examples.py, never hand-typed.
[0, 1, 2, 3, 4, 1, 2]
["a", "b", "c", "a", "b", "c"]
2.. [1, 2, 3, 4, 3, 4]
..=1 [1, 2, 3, 4, 1, 2]
["x!", "x"]
[1, 2, 3, 1, 2, 3, 1, 2, 3, 1, 2, 3] len 12
out-of-range range panicked: true
See also¶
Vec::extend_from_slice— the same, from a slice you holdVec::resize— padding with one repeated value insteadVec::splice— the general range-replacing operation