Reputation: 312
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
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 Entry
s 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.
Upvotes: 5