I am trying to optimize a Rust program through reduced allocations. I have many borrowed string slices that sometimes need to be turned into owned string slices. There is a function that takes in two Vecs of Cow<str> values, one of them 'static (V1) and one '_ (V2). I need to clear V2, then read the 'static values from V1 and copy them into V2, returning a Vec<Cow<'static, str>>. This is problematic because the compiler thinks the lifetime of V2 is '_ even though at runtime it will only hold values that are 'static. I have presently made it work by using transmute, but transmuting to the static lifetime is a major code smell IMO. Here is a minimum example of what I'm trying to accomplish:
use std::borrow::Cow;
fn drain(owned: Vec<Cow<'static, str>>, mut borrowed: Vec<Cow<'_, str>>) -> Vec<Cow<'static, str>> {
borrowed.clear();
let mut out = unsafe {
fn assert_static<T: 'static>(_x: &T) {}
assert_static(&owned);
std::mem::transmute::<Vec<Cow<'_, str>>, Vec<Cow<'static, str>>>(borrowed)
};
for v in owned {
out.push(v);
}
out
}
Is it possible to write this function without any additional allocations and without using transmute?
Here are some alternatives that I've considered:
- Why not just return
owned? In real code I do not add every element fromownedtoout, and I sometimes need to add in new elements in between the elements fromowned. - Why not
let mut out = Vec::with_capacity(owned.len())? In my testing, this has a performance cost of around 0.8MiB/s. This represents an approximately 10% difference and I'd like to minimize runtime to the greatest extent possible.