I wrote the following piece of code trying to implement universal Visitor trait parameterized by trait which is being visited. To me it looks like I placed all lifetime annotations correctly. My goal was to designate that visited item outlives the visitor. Compiler shows E0597
error for the final call. Could you please help me to understand where I made a mistake?
The code:
use std::fmt::Display;
trait Visitor<'a, 'b: 'a, T: 'b> {
fn visit(&'a self, t: T);
}
struct Printer { }
impl<'a, 'b: 'a, T: Display + 'b> Visitor<'a, 'b, T> for Printer {
fn visit(&'a self, t: T) {
println!("{}", t);
}
}
trait Visitable<'a, 'b: 'a, T: 'b> {
fn accept(&'b self, visitor: &'a dyn Visitor<'a, 'b, T>);
}
#[derive(Debug)]
struct ItemA<T> {
v: T,
}
impl<T: Display> Display for ItemA<T> {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> Result<(), std::fmt::Error> {
write!(f, "ItemA.v = {}", self.v)
}
}
impl<'a, 'b: 'a, T: Display> Visitable<'a, 'b, &'b dyn Display> for ItemA<T> {
fn accept(&'b self, visitor: &'a dyn Visitor<'a, 'b, &'b dyn Display>) {
visitor.visit(self as &dyn Display);
}
}
fn print_items<'a, 'b: 'a, T: Display + 'b>(
vec: &'b Vec<Box<dyn Visitable<'a, 'b, &'b dyn Display>>>,
visitor: &'a dyn Visitor<'a, 'b, &'b dyn Display>) {
for v in vec {
v.accept(visitor);
}
}
fn main() {
let vec: Vec<Box<dyn Visitable<&dyn Display>>> = vec![Box::new(ItemA{ v: 3 })];
let printer = Printer{};
print_items::<&dyn Display>(&vec, &printer);
}
Compilation fails with E0597
:
Compiling a v0.1.0 (/home/vital/projects/trueagi/a)
error[E0597]: `vec` does not live long enough
--> src/main.rs:47:33
|
47 | print_items::<&dyn Display>(&vec, &printer);
| ^^^^ borrowed value does not live long enough
48 | }
| -
| |
| `vec` dropped here while still borrowed
| borrow might be used here, when `vec` is dropped and runs the `Drop` code for type `Vec`
error[E0597]: `printer` does not live long enough
--> src/main.rs:47:39
|
47 | print_items::<&dyn Display>(&vec, &printer);
| ^^^^^^^^ borrowed value does not live long enough
48 | }
| -
| |
| `printer` dropped here while still borrowed
| borrow might be used here, when `vec` is dropped and runs the `Drop` code for type `Vec`
|
= note: values in a scope are dropped in the opposite order they are defined
For more information about this error, try `rustc --explain E0597`.
error: could not compile `a` due to 2 previous errors