Please bear in mind the following code is a simplified example to illustrate my problem, hence the "test".to_string()
which otherwise I wouldn't do.
struct Container<'a> {
string: String,
list: Vec<Item<'a>>,
}
impl<'a> Container<'a> {
pub fn create() -> Container<'a> {
let string = "test".to_string();
Container {
string,
list: vec![],
}
}
pub fn add(&mut self) {
self.list.push(Item::create(&self.string));
}
}
struct Item<'a> {
string: &'a str,
}
impl<'a> Item<'a> {
pub fn create(string: &'a str) -> Item<'a> {
Item { string }
}
}
fn main() {
let container = Container::create();
container.add();
container.add();
}
When I attempt to compile this, I get the following error:
error[E0495]: cannot infer an appropriate lifetime for borrow expression due to conflicting requirements
--> src/main.rs:17:37
|
17 | self.list.push(Item::create(&self.string));
| ^^^^^^^^^^^^
|
note: first, the lifetime cannot outlive the anonymous lifetime #1 defined on the method body at 16:5...
--> src/main.rs:16:5
|
16 | / pub fn add(&mut self) {
17 | | self.list.push(Item::create(&self.string));
18 | | }
| |_____^
note: ...so that reference does not outlive borrowed content
--> src/main.rs:17:37
|
17 | self.list.push(Item::create(&self.string));
| ^^^^^^^^^^^^
note: but, the lifetime must be valid for the lifetime 'a as defined on the impl at 6:1...
--> src/main.rs:6:1
|
6 | impl<'a> Container<'a> {
| ^^^^^^^^^^^^^^^^^^^^^^
= note: ...so that the expression is assignable:
expected Item<'a>
found Item<'_>
I realize this is because the compiler can't figure out what lifetime it should use for self.string
. I have looked at many other examples of lifetimes and I know what needs to be done, but I don't know what syntax I am supposed to use to accomplish this.
I know this is probably a really simple thing, but I haven't found anything in the Rust Book or here that explains the exact situation I'm in, and I don't understand lifetimes well enough to apply other solutions to what I'm trying to do.
These are other things I've tried:
self.list.push(Item::create(&'a self.string));
error: expected `:`, found `self`
--> lifeTest.rs:17:36
|
17 | self.list.push(Item::create(&'a self.string));
|
let reference: &'a str = &self.string;
self.list.push(Item::create(reference));
error[E0495]: cannot infer an appropriate lifetime for borrow expression due to conflicting requirements
--> lifeTest.rs:17:29
|
17 | let reference: &'a str = &self.string;
| ^^^^^^^^^^^^
|
pub fn add(&'a mut self) {
self.list.push(Item::create(&self.string));
}
...
let mut container = Container::create();
error[E0499]: cannot borrow `container` as mutable more than once at a time
--> lifeTest.rs:36:3
|
35 | container.add();
| --------- first mutable borrow occurs here
36 | container.add();
| ^^^^^^^^^ second mutable borrow occurs here
37 | }
| - first borrow ends here
struct Container<'a> {
string: Option<&'a String>,
list: Vec<Item<'a>>
}
....
let string = "test".to_string();
Container {
string: Some(&string),
list: vec![]
}
error[E0597]: `string` does not live long enough
--> lifeTest.rs:11:19
|
11 | string: Some(&string),
| ^^^^^^ borrowed value does not live long enough
...
I feel like I'm getting close with the last one, but I'd like to avoid making the container mutable, if possible.
How do I tell the compiler to use the lifetime 'a
for the reference that it passes into Item
?