Having trouble wtih lifetimes

In the following example, the rust compiler is complaining that I am borrowing bar as mutable and immutable at the same time. Why is that so ? Why are the borrows accuring at the same time and not one after the other ?

What I would like is to be able to use .buffers and .buffers_bind in a method inside of Bar.

struct BufferBinding<'a> {
    bind: &'a Buffer
}
struct Buffer {
    name: String,
}
struct Bar<'a> {
    buffers: Vec<Buffer>,
    buffers_bind: Vec<BufferBinding<'a>>
}
impl<'a> Bar<'a> {
    pub fn new<'b>() -> Bar<'b> {
        Bar {
            buffers: vec![],
            buffers_bind: vec![]
        }
    }
    pub fn add(&'a mut self, name: String) {
        self.buffers.push(Buffer {name});
        self.buffers_bind.push(BufferBinding {
            bind: &self.buffers.last().unwrap()
        })
    }
    pub fn do_smh(&self) -> Vec<i32> {
        // this is meant to do something with self.buffers_bind and self.buffers
        vec![1, 2, 3]
    }
}
fn main() {
    let mut bar = Bar::new();
    bar.add(String::from("buf1"));
    bar.add(String::from("buf2")); //cannot borrow `bar` as mutable more than once at a time
    let result = bar.do_smh();
    println!("{:?}", result);
}

This is a death sentence:

impl<'a> SomeType<'a> {
    fn some_fn(&'a mut self, ...) {

These lifetimes are always incorrect. Remove the lifetime on &mut self.

1 Like

Already tried that, then I get this slightly more complicated looking error :

error[E0495]: cannot infer an appropriate lifetime for lifetime parameter in function call due to conflicting requirements
  --> src\main.rs:24:33
   |
24 |             bind: &self.buffers.last().unwrap()
   |                                 ^^^^
   |
note: first, the lifetime cannot outlive the anonymous lifetime defined here...
  --> src\main.rs:21:16
   |
21 |     pub fn add(&mut self, name: String) {
   |                ^^^^^^^^^
note: ...so that reference does not outlive borrowed content
  --> src\main.rs:24:20
   |
24 |             bind: &self.buffers.last().unwrap()
   |                    ^^^^^^^^^^^^
note: but, the lifetime must be valid for the lifetime `'a` as defined here...
  --> src\main.rs:13:6
   |
13 | impl<'a> Bar<'a> {
   |      ^^
note: ...so that the expression is assignable
  --> src\main.rs:23:32
   |
23 |           self.buffers_bind.push(BufferBinding {
   |  ________________________________^
24 | |             bind: &self.buffers.last().unwrap()
25 | |         })
   | |_________^
   = note: expected `BufferBinding<'a>`
              found `BufferBinding<'_>`

Looking more closely, the issue is that your struct is self-referential. It's impossible to have references in one field point into another field of the same struct. References can only go between two completely separate variables.

1 Like

That is good to know.

Oh ok. So what I want is impossible. Thank you very much for your help !

Common alternatives involve storing an index into the vector, or using Rc/Arc.

1 Like

In the end, I went with a vector of indices, worked great ! Thank you !

This topic was automatically closed 90 days after the last reply. We invite you to open a new topic if you have further questions or comments.