I have a problem to solve where I need a Data
struct with a reference to it's Builder
in order to retain some useful properties. I then also have a Container
struct which holds a vector of Data
structs as well as a reference to the Builder
. The container struct has a fill
method to push instances of Data
to the vector after building one using some math; I have the build_one
method for this purpose. When I try to use the build_one
method in fill
, I get issues about the lifetime of self
, since &self
is used by build_one
, then &mut self
is required to push to the vector, but the &self
for build_one
is still alive for some reason when that occurs. If I work around the issue by extracting the self.builder.build
and running that on the calculated value, everything works, so logically the compiler is able to resolve the lifetimes as intended.
Why is this happening? Is there a way I can specify what the lifetimes should be so that I don't need the extra self.builder.build
line to rebuild the same object twice?
#[derive(Debug)]
struct Data<'a> {
value: i32,
builder: &'a Builder,
}
impl<'a> Data<'a> {
fn get_original(&self) -> i32 {
self.value / self.builder.multiplier
}
}
#[derive(Debug)]
struct Builder {
multiplier: i32,
}
impl Builder {
fn build(&self, value: i32) -> Data {
Data {
value: self.multiplier * value,
builder: self,
}
}
}
#[derive(Debug)]
struct Container<'a> {
vals: Vec<Data<'a>>,
builder: &'a Builder,
}
impl<'a> Container<'a> {
fn build_one(&self, value: i32) -> Data {
// Do math with value
self.builder.build(value)
}
fn fill(mut self, value: i32) -> Self {
// This line causes errors
let new = self.build_one(value);
// But this one is okay
// let new = self.builder.build(value);
// Or adding this lets it compile
// let new = self.builder.build(new.value);
self.vals.push(new);
self
}
}
fn main() {
let builder = Builder { multiplier: 7 };
let container = Container {
vals: vec![],
builder: &builder,
}
.fill(1)
.fill(2);
println!("{:?}", container);
for d in container.vals {
println!(
"{} * {} = {}",
d.builder.multiplier,
d.get_original(),
d.value
);
}
}
Errors:
Compiling playground v0.0.1 (/playground)
error[E0597]: `self` does not live long enough
--> src/main.rs:41:19
|
33 | impl<'a> Container<'a> {
| -- lifetime `'a` defined here
...
39 | fn fill(mut self, value: i32) -> Self {
| -------- binding `self` declared here
40 | // This line causes errors
41 | let new = self.build_one(value);
| ^^^^^^^^^^^^^^^^^^^^^
| |
| borrowed value does not live long enough
| argument requires that `self` is borrowed for `'a`
...
49 | }
| - `self` dropped here while still borrowed
error[E0502]: cannot borrow `self.vals` as mutable because it is also borrowed as immutable
--> src/main.rs:47:9
|
33 | impl<'a> Container<'a> {
| -- lifetime `'a` defined here
...
41 | let new = self.build_one(value);
| ---------------------
| |
| immutable borrow occurs here
| argument requires that `self` is borrowed for `'a`
...
47 | self.vals.push(new);
| ^^^^^^^^^^^^^^^^^^^ mutable borrow occurs here
error[E0505]: cannot move out of `self` because it is borrowed
--> src/main.rs:48:9
|
33 | impl<'a> Container<'a> {
| -- lifetime `'a` defined here
...
39 | fn fill(mut self, value: i32) -> Self {
| -------- binding `self` declared here
40 | // This line causes errors
41 | let new = self.build_one(value);
| ---------------------
| |
| borrow of `self` occurs here
| argument requires that `self` is borrowed for `'a`
...
48 | self
| ^^^^ move out of `self` occurs here
Some errors have detailed explanations: E0502, E0505, E0597.
For more information about an error, try `rustc --explain E0502`.
error: could not compile `playground` (bin "playground") due to 3 previous errors