I'm trying to make something like immutable Dictionary trait that can be added new items (references) into and used without affecting the previous version. Minimal example:
#[derive(Clone)]
pub struct SetOfValues<'a> {
value: Vec<&'a i32>,
}
pub trait TheSetAccessor<'b> {
fn with_additional_values(&self, new_set: Vec<&'b i32>) -> Box<dyn TheSetAccessor<'b>>;
fn get_from_set(&self, index: usize) -> &i32;
}
impl<'a, 'b : 'a> TheSetAccessor<'b> for SetOfValues<'a> {
fn with_additional_values(&self, new_set: Vec<&'b i32>) -> Box<dyn TheSetAccessor<'b>> {
Box::new(SetOfValues { value: new_set } )
}
fn get_from_set(&self, index: usize) -> &i32 {
self.value[index]
}
}
fn usage() {
let a = 0;
let set = SetOfValues {
value: vec![&a]
};
// ...
let b = 1;
let extended_set = set.with_additional_values(vec![&a, &b]);
// ...
let got_b = extended_set.get_from_set(1);
}
The error message is following:
error[E0495]: cannot infer an appropriate lifetime for lifetime parameter `'a` due to conflicting requirements
--> src/test.rs:13:18
|
13 | Box::new(SetOfValues { value: new_set } )
| ^^^^^^^^^^^
|
note: first, the lifetime cannot outlive the lifetime `'b` as defined here...
--> src/test.rs:11:10
|
11 | impl<'a, 'b : 'a> TheSetAccessor<'b> for SetOfValues<'a> {
| ^^
note: ...so that the expression is assignable
--> src/test.rs:13:39
|
13 | Box::new(SetOfValues { value: new_set } )
| ^^^^^^^
= note: expected `Vec<&i32>`
found `Vec<&'b i32>`
= note: but, the lifetime must be valid for the static lifetime...
note: ...so that the types are compatible
--> src/test.rs:13:9
|
13 | Box::new(SetOfValues { value: new_set } )
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
= note: expected `Box<(dyn TheSetAccessor<'b> + 'static)>`
found `Box<dyn TheSetAccessor<'b>>`
As far as I understand, the new SetOfValues should have the lifetime of the passed vector ('b), but this part
first, the lifetime cannot outlive the lifetime
'b
as defined here...
as I see, suggests that the new instance of SetOfValues has another lifetime ('static ?) that is supposed to live longer than 'b. I don't quite understand how I can restrict this lifetime. What can I do to make this code work?
This is because dyn Trait
is actually dyn Trait + 'static
. Thus, dyn TheSetAccessor<'b>
is actually dyn TheSetAccessor<'b> + 'static
, and cannot contain any non-'static
lifetime, so it requires 'b: 'static
.
To relax this bound add a lifetime to the trait: dyn TheSetAccessor<'b> + 'b
. Note this may not be the best solution, depending on your use case.
fn with_additional_values(&self, new_set: Vec<&'b i32>) -> Box<dyn TheSetAccessor<'b> + 'b>;