user103716
user103716

Reputation: 312

"does not necessarily outlive the lifetime" issue

My goal is to have a Store which contains various Entry items. The Entry items can live longer than the store itself, and so Store keeps a Vec<&Entry> (playground):

struct Entry {
    title: String,
    content: String,
}

struct Store<'a> {
    // name: String,
    entries: Vec<&'a Entry>,
}

impl<'a> Store<'a> {
    fn new() -> Store<'a> {
        Store {
            // name,
            entries: Vec::new(),
        }
    }

    fn add_entry(self: &mut Store, entry: &Entry) {
        self.entries.push(entry);
    }
}

fn main() {
    let entry = Entry {
        title: "my title",
        content: "my content",
    };
    let mut store = Store::new();
    store.add_entry(entry);
}
error[E0308]: mismatched `self` parameter type
  --> src/main.rs:19:24
   |
19 |     fn add_entry(self: &mut Store, entry: &Entry) {
   |                        ^^^^^^^^^^ lifetime mismatch
   |
   = note: expected struct `Store<'a>`
              found struct `Store<'_>`
note: the anonymous lifetime #2 defined on the method body at 19:5...
  --> src/main.rs:19:5
   |
19 |     fn add_entry(self: &mut Store, entry: &Entry) {
   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
note: ...does not necessarily outlive the lifetime `'a` as defined on the impl at 11:6
  --> src/main.rs:11:6
   |
11 | impl<'a> Store<'a> {
   |      ^^

error[E0308]: mismatched `self` parameter type
  --> src/main.rs:19:24
   |
19 |     fn add_entry(self: &mut Store, entry: &Entry) {
   |                        ^^^^^^^^^^ lifetime mismatch
   |
   = note: expected struct `Store<'a>`
              found struct `Store<'_>`
note: the lifetime `'a` as defined on the impl at 11:6...
  --> src/main.rs:11:6
   |
11 | impl<'a> Store<'a> {
   |      ^^
note: ...does not necessarily outlive the anonymous lifetime #2 defined on the method body at 19:5
  --> src/main.rs:19:5
   |
19 |     fn add_entry(self: &mut Store, entry: &Entry) {
   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

Error E0308 is not very helpful in this case.

I don't understand why the lifetime at the add_entry method must outlive the one of the impl, which is what I understand from the error.

I am sure this is something quite basic, but I cannot figure it out by reading The Rust Programming Language up to chapter 15.

Upvotes: 3

Views: 1252

Answers (1)

phimuemue
phimuemue

Reputation: 36081

Fixing the errors to make it compile: add_entry should look like this:

fn add_entry(&mut self, entry: &'a Entry) {
    self.entries.push(entry);
}

I.e. you must specify the lifetime of entry explicitly. Your Store assumes that its Entrys have a certain lifetime. If add_entry does not explicitly store this lifetime, Rust tries to infer automatic lifetimes - and it cannot prove that entry's lifetime is actually the one your Store requires.

If you left add_entry as you did, you could essentially call it like this store.add_entry(&Entry{...}) (i.e. you could pass a reference to a temporary entry). This temporary entry would go out of scope/be after the statement. Thus, Rust disallows to put it into entries, as it would then point to a already dropped (read: invalid) value.

Playground

Upvotes: 5

Related Questions