2

In the code below, I understand that there seems to be a lifetime conflict between the reference returned by Storage::insert and the lifetime of Consumer<'a>. However, I'm having trouble:

  1. understanding why there is this conflict - that is, both Consumer::storage and Consumer::current_value have the same lifetimes so what other lifetime is Rust inferring that is in conflict with <'a>

  2. how best to specify what the lifetimes are and why does this work

struct Storage {
    value: i64,
}

impl Storage {
    fn new() -> Self {
        Storage { value: 0 }
    }

    fn insert(&mut self, v: i64) -> &i64 {
        self.value = v;
        &self.value
    }
}

struct Consumer<'a> {
    storage: &'a mut Storage,
    current_value: &'a i64,
}

impl<'a> Consumer<'a> {
    fn new(s: &'a mut Storage) -> Self {
        Consumer {
            storage: s,
            current_value: &s.value,
        }
    }

    fn new_value(&mut self, v: i64) {
        self.current_value = self.storage.insert(v);
    }
}

Playground

The error resulting from this code is:

error[E0495]: cannot infer an appropriate lifetime for autoref due to conflicting requirements
  --> src/lib.rs:30:43
   |
30 |         self.current_value = self.storage.insert(v);
   |                                           ^^^^^^
   |
note: first, the lifetime cannot outlive the anonymous lifetime #1 defined on the method body at 29:5...
  --> src/lib.rs:29:5
   |
29 | /     fn new_value(&mut self, v: i64) {
30 | |         self.current_value = self.storage.insert(v);
31 | |     }
   | |_____^
note: ...so that reference does not outlive borrowed content
  --> src/lib.rs:30:30
   |
30 |         self.current_value = self.storage.insert(v);
   |                              ^^^^^^^^^^^^
note: but, the lifetime must be valid for the lifetime 'a as defined on the impl at 21:6...
  --> src/lib.rs:21:6
   |
21 | impl<'a> Consumer<'a> {
   |      ^^
note: ...so that reference does not outlive borrowed content
  --> src/lib.rs:30:30
   |
30 |         self.current_value = self.storage.insert(v);
   |                              ^^^^^^^^^^^^^^^^^^^^^^

I've read the following and I'm not sure I follow how they apply to my question (perhaps they do and I'm just not reading properly):

Shepmaster
  • 388,571
  • 95
  • 1,107
  • 1,366
fpes
  • 964
  • 11
  • 22
  • 1
    In `new`, `current_value: &s.value` is impossible: `&s.value` is a local reborrow of `s`, which means it can't have the same `'a` lifetime as `s`. You can "fix" `new_value` by having it take `&'a mut self`, but you can't fix the core problem which is that `Consumer` is a self-referential struct. – trent Mar 22 '19 at 13:32
  • 1
    The problem is really quite similar to [Why can't I store a value and a reference to that value in the same struct?](https://stackoverflow.com/questions/32300132/why-cant-i-store-a-value-and-a-reference-to-that-value-in-the-same-struct). In that case, things you can do with the owning member can invalidate the reference. In your case, things you can do with the `storage` can invalidate the reference. – trent Mar 22 '19 at 13:40
  • @trentcl Thank you - clearly I was dealing with a symptom of a different problem. – fpes Mar 22 '19 at 17:10

0 Answers0