I'd like to have an iterator that points into a Vec
of the same struct.
The following works fine (playground):
struct Holder1<'a> {
vec: Vec<i32>,
iterator: Option<Box<std::slice::Iter<'a, i32>>>,
}
fn holder1_test() {
let vec = vec![1, 2, 3, 4];
let mut holder = Holder1 {
vec,
iterator: None,
};
let iterator: Box<std::slice::Iter<'_, i32>> = Box::new(holder.vec.iter());
holder.iterator = Some(iterator);
for iter_elem in holder.iterator.as_mut().unwrap() {
println!("iter: {}", iter_elem);
}
}
(I know the Box
isn't needed here, I just wanted to keep this as close as possible to the next code snippet.)
I'd like to use a trait object, dyn Iterator
, instead of the concrete type. I've slightly modified the example from above for that (playground):
struct Holder2<'a> {
vec: Vec<i32>,
iterator: Option<Box<dyn Iterator<Item = &'a i32>>>,
}
fn holder2_test() {
let vec = vec![1, 2, 3, 4];
let mut holder = Holder2 {
vec,
iterator: None,
};
let iterator: Box<dyn Iterator<Item = &'_ i32>> = Box::new(holder.vec.iter());
holder.iterator = Some(iterator);
for iter_elem in holder.iterator.as_mut().unwrap() {
println!("iter: {}", iter_elem);
}
}
This fails to compile:
error[E0597]: `holder.vec` does not live long enough
--> src/lib.rs:12:64
|
12 | let iterator: Box<dyn Iterator<Item = &'_ i32>> = Box::new(holder.vec.iter());
| ^^^^^^^^^^ borrowed value does not live long enough
...
18 | }
| -
| |
| `holder.vec` dropped here while still borrowed
| borrow might be used here, when `holder` is dropped and runs the destructor for type `Holder2<'_>`
What makes the second example so different to the first example that causes the compilation failure? Both iterators point to an element in the Vec
of the same struct - so what's the conceptual difference here? Is there a way to get this to work with trait objects?
I'm aware that using an index instead of an iterator would solve this, but I'm rather interested in the underlying reasons of why this doesn't work.