Reputation: 2136
I have a function foo
that takes in parameter an array slice of array slices, however I can't seem to create a variable that lives long enough to pass it as a parameter:
fn main() {
let mut outer_vec = vec![];
for i in 0..10 {
let inner_vec = vec![i];
outer_vec.push(inner_vec.as_slice());
}
foo(&outer_vec);
}
fn foo(_bar: &[&[u8]]) {
println!("foo");
}
I get this error:
error[E0597]: `inner_vec` does not live long enough
--> src/main.rs:5:24
|
5 | outer_vec.push(inner_vec.as_slice());
| ^^^^^^^^^^^^^^^^^^^^ borrowed value does not live long enough
6 | }
| - `inner_vec` dropped here while still borrowed
7 | foo(&outer_vec);
| ---------- borrow later used here
I know that a given inner array slice cannot outlive the lifetime of the inner_vec
it originates from, which is dropped at the end of the for loop, but I want to know if it is possible to fix this error without changing the signature of the foo
function, that is, keep it foo(_bar: &[&[u8]])
and not change it to something like foo(_bar: &[Vec<u8>])
.
Thank you for your help.
Upvotes: 0
Views: 256
Reputation: 796
You could use Vec::leak()
and a turbofish to force the slice to live forever:
let vec_of_slices =
outer_vec.iter()
.map(|inner_vec| inner_vec.leak::<'static>())
.collect::<Vec<_>>();
One downside to this, of course, is that, as the name of the leak()
method suggests, you’d be leaking memory by doing this.
Also note that Vec::leak()
returns a mutable slice — if you need an immutable slice, you can instead use slice::from_raw_parts()
:
let vec_of_slices =
outer_vec.iter()
.map(|inner_vec| unsafe {
use core::mem::ManuallyDrop;
let inner_vec = ManuallyDrop::new(inner_vec);
core::slice::from_raw_parts::<'static>(
inner_vec.as_ptr(),
inner_vec.len()
)
})
.collect::<Vec<_>>();
Note that this call to slice::from_raw_parts()
needs to be marked unsafe
since it deals with raw pointers. This is really a duplication of how Vec::leak()
is defined, only in the upstream case slice::from_raw_parts_mut()
is used.
Upvotes: 0
Reputation: 2136
To keep the same signature for foo
, you can create a variable that keeps the ownership of the inner_vec
s and create slices from it in another variable:
fn main() {
let mut outer_vec = vec![];
for i in 0..10 {
let inner_vec = vec![i];
outer_vec.push(inner_vec);
}
let vec_of_slices: Vec<&[u8]> = outer_vec.iter()
.map(|inner_vec| inner_vec.as_slice()).collect();
foo(&vec_of_slices);
}
fn foo(_bar: &[&[u8]]) {
println!("foo");
}
Upvotes: 1
Reputation: 6061
Your problem has nothing to do with function foo
. It exists inside for
loop. Comment out calling foo
and you will still have an error. In every iteration you create local variable inner_vec
that is dropped at the end of the iteration. You therefore cannot store a reference to it that would escape the for
loop. In other words it's lifetime is to short.
The solution here would be to give the ownership of inner_vec
to outer_vec
by moving it (not the reference). Then you would have to change foo
's signature as well.
Upvotes: 1