Reputation: 33
I need to find the index of an element, given by reference, in a vector that hold references to elements that satisfy a trait.
There is a layer system, which includes the layer trait and a layer stack (to have control over operations):
pub trait Layer {
fn new(name: &str) -> Self where Self: Sized;
fn on_attach(&mut self);
fn on_detach(&mut self);
fn on_update(&mut self);
fn on_event(&mut self, event: &mut dyn Event);
fn get_debug_name(&self) -> &String;
}
impl PartialEq for dyn Layer {
fn eq(&self, other: &dyn Layer) -> bool {
self.get_debug_name() == other.get_debug_name()
}
}
pub struct LayerStack<'a> {
layers: Vec<&'a mut dyn Layer>,
overlay_position: usize,
}
impl<'a> LayerStack<'a> {
pub fn new() -> Self {
Self {
layers: Vec::new(),
overlay_position: 0
}
}
// ...
pub fn find_index(&self, element: &'a dyn Layer) -> Option<usize> {
self.layers.iter().position(|item| *item == element)
}
}
There is an error in the find_index
method:
error: lifetime may not live long enough
8 | impl<'a> LayerStack<'a> {
| -- lifetime `'a` defined here
...
48 | self.layers.iter().position(|item| *item == element)
| ^^^^^^^^^^^^^^^^ requires that `'a` must outlive `'static`
This is some kind of a lifetime issue but I can't see any problems here. What can I do about it?
I know that owning the elements themselves instead of references partly solves this problem, but I have to only have mutable ref to layers but not own them. Static lifetime in a struct generic also doesn't work: the layers don't have a static lifetime.
I'm a complete newbie at rust, so dealing with all the lifetime things is a complete nightmare
Upvotes: 2
Views: 186
Reputation: 8813
In the implementation below; type expression(dyn Layer
) is called as trait object.
(need to note that Layer
needs to be an object safe trait)
impl PartialEq for dyn Layer { /*...*/ }
Since dyn Layer
is not used as a type argument of a generic type, Rust follows the rules below (reference:
- If the trait is defined with a single lifetime bound then that bound is used.
- If 'static is used for any lifetime bound then 'static is used.
- If the trait has no lifetime bounds, then the lifetime is inferred in expressions and is 'static outside of expressions.
The highlighted part is applied to your implementation since there is no bound defined in the implementation you made.
Thus we can tell that your PartialEq
implementation is only valid when the operands have static lifetime for ==
operator. But your operands live in 'a
which can be 'static
or something else.
impl<'a> LayerStack<'a> {
//...
pub fn find_index(&self, element: &'a dyn Layer) -> Option<usize> {
self.layers.iter().position(|item| *item == element)
}
To fix this problem we can apply the first rule (adding single lifetime bound)
impl<'a> PartialEq for dyn Layer + 'a { /*...*/ }
Or even better, from the reference above:
If '_ is used as the lifetime bound then the bound follows the usual elision rules.
It can be implemented like this:
impl PartialEq for dyn Layer + '_ { /*...*/ }
Upvotes: 2