0

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?

Dr_Derp
  • 1,185
  • 6
  • 17
  • 3
    I believe your question is answered by the answers of [Why can't I store a value and a reference to that value in the same struct?](https://stackoverflow.com/q/32300132/155423). If you disagree, please [edit] your question to explain the differences. Otherwise, we can mark this question as already answered. – Shepmaster May 23 '18 at 21:26
  • It's similar but not the same. In that answer, the person is trying to store both `c` and `&c` in the same place. My problem is I have already stored `c` and I'm trying to access `&c` in a mutable way but when I try to reference it the lifetimes screw up. I will try to edit the question to make this more clear. – Dr_Derp May 23 '18 at 22:02
  • Did you read the section "There's one specific case where you can create a type with a reference to itself." ? – Shepmaster May 23 '18 at 22:03
  • That seems like that might work. I gave that a try, but then basically ran into the same error. I put an example up above to show – Dr_Derp May 23 '18 at 22:12
  • I still don't see how this is different from any other self reference example. Except for the last example, which is returning a reference to a stack variable. – Sebastian Redl May 23 '18 at 22:21
  • I imagine it's probably the same. I just don't understand how to apply the lessons in that other example to the code I have here. Which is more of a failure on my part then anything else. – Dr_Derp May 23 '18 at 22:23

0 Answers0