The default lifetime for dynamic objects for some reasons is 'static, despite the fact that some variables like Box < dyn SomeTrait > may live much less than the entire lifetime of a program. In combination with custom specified lifetimes this leads to the situations where borrow checker cannot infer an appropriate lifetime, e.g. [E0495].
Here is a toy example, where I cannot figure out, how to specify lifetimes right:
use std::rc::Rc;
use std::cell::RefCell;
trait Tree {
fn callback(&self, parent: &mut Node);
}
struct A<'t> {
rule: &'t usize,
first: Rc<RefCell<Node>>,
}
impl<'t> A<'t> {
fn next(&self) -> A<'t> {
A {
first: Rc::clone(&self.first),
..*self
}
}
}
impl<'t> Tree for A<'t> {
fn callback(&self, parent: &mut Node) {
parent.add_this_way(Rc::new(self.next()))
}
}
struct B<'t> {
rule: &'t usize,
first: Rc<RefCell<Node>>,
}
impl<'t> B<'t> {
fn next(&self) -> B {
B {
first: Rc::clone(&self.first),
..*self
}
}
}
impl<'t> Tree for B<'t> {
fn callback(&self, parent: &mut Node) {
parent.add_another_way(Rc::new(self.next()))
}
}
struct Node {
backpointers: Vec<Rc<dyn Tree>>,
}
impl Node {
fn add_this_way(&mut self, tree: Rc<Tree>) {
self.backpointers.push(tree)
}
fn add_another_way(&mut self, tree: Rc<Tree>) {
self.backpointers.push(tree);
}
}
fn main() {
let x: usize = 0;
let mut root = Node {
backpointers: Vec::new(),
};
let child = Rc::new(RefCell::new(Node {
backpointers: Vec::new(),
}));
let a = A {
rule: &x,
first: Rc::clone(&child),
};
let b = B {
rule: &x,
first: Rc::clone(&child),
};
a.callback(&mut root);
b.callback(&mut root);
}
Here is the compiler output:
error[E0495]: cannot infer an appropriate lifetime for lifetime parameter `'t` due to conflicting requirements
--> src/main.rs:24:42
|
24 | parent.add_this_way(Rc::new(self.next()))
| ^^^^
|
note: first, the lifetime cannot outlive the lifetime 't as defined on the impl at 22:1...
--> src/main.rs:22:1
|
22 | impl<'t> Tree for A<'t> {
| ^^^^^^^^^^^^^^^^^^^^^^^
= note: ...so that the types are compatible:
expected &A<'_>
found &A<'t>
= note: but, the lifetime must be valid for the static lifetime...
= note: ...so that the expression is assignable:
expected std::rc::Rc<Tree + 'static>
found std::rc::Rc<Tree>
error[E0495]: cannot infer an appropriate lifetime for autoref due to conflicting requirements
--> src/main.rs:44:45
|
44 | parent.add_another_way(Rc::new(self.next()))
| ^^^^
|
note: first, the lifetime cannot outlive the lifetime 't as defined on the impl at 42:1...
--> src/main.rs:42:1
|
42 | impl<'t> Tree for B<'t> {
| ^^^^^^^^^^^^^^^^^^^^^^^
note: ...so that the type `B<'t>` is not borrowed for too long
--> src/main.rs:44:40
|
44 | parent.add_another_way(Rc::new(self.next()))
| ^^^^
= note: but, the lifetime must be valid for the static lifetime...
= note: ...so that the expression is assignable:
expected std::rc::Rc<Tree + 'static>
found std::rc::Rc<Tree>
error: aborting due to 2 previous errors
If I specify a custom lfietime like Vec<Rc<dyn Tree + 's> >, I get other [E0495] errors, like
error[E0495]: cannot infer an appropriate lifetime for lifetime parameter in function call due to conflicting requirements
What should I change in this code to get it pass through compiler?