The second version of test
, with owned/unique strings does work, just the compiler has to be assisted to convert the ~str
to a &'r str
:
fn test<'r>(xs: &'r [~str]) -> &'r str {
let tmp: &'r str = xs[0];
tmp
}
The reason this works is the xs
vector owns the ~str
s it contains and so the compiler knows that their lifetime is at least the lifetime of the vector (because it is also careful about mutability in the presence of borrows like this, so the string can never be removed from the vector). The only problem is convincing the compiler to coerce xs[0]
to a slice, which is most easily performed by a temporary.
extend
might look something like:
fn extend<'r>(xs: ~[&'r str], ys: &'r [~str]) -> ~[&'r str] {
let mut xs = xs;
for vec::each(ys) |s| {
let tmp: &'r str = *s;
xs.push(tmp)
}
xs
}
It seems that vec::each(ys)
works, but ys.each
doesn't, which is probably a bug (I'm investigating it now I opened #6655).
If you want to modify a vector in-place, the normal method is to pass a mutable reference to the vector, i.e.
fn extend<'r>(xs: &mut ~[&'r str], ys: &'r [~str]) {
for vec::each(ys) |s| {
let tmp: &'r str = *s;
xs.push(tmp)
}
}
which is called like extend(&mut vec, additions)
.
To illustrate:
rusti> let a = &[~"a", ~"b", ~"c"];
()
rusti> test(a)
"a"
rusti> extend(~["1", "2", "3"], a)
~["1", "2", "3", "a", "b", "c"]