Borrowing error when calling a method

Hello,

I have an issue w/ a borrowing error that I don't understand. It happens when calling a method multiple times on a struct that has a reference. If I remove the reference (and lifetimes) things work as expected. Grateful for any insights.

Compiling/working code:

pub struct Foo {
}

impl Foo {
    pub(crate) fn new() -> Foo {
        Foo {
        }
    }

    pub fn no_op(&mut self) -> () {}
}

fn main() {
    let mut foo = Foo::new();
    foo.no_op();
    foo.no_op();
}

Playground for success

Problem child:

pub struct Foo<'a> {
    tokens:&'a Vec<i32>,
}

impl<'a> Foo<'a> {
    pub(crate) fn new(tokens:&'a Vec<i32>) -> Foo<'a> {
        Foo {
            tokens,
        }
    }

    pub fn no_op(&'a mut self) -> () {}
}

fn main() {
    let v = vec![];
    let mut foo = Foo::new(&v);
    foo.no_op();
    foo.no_op();
}

Playground for error

Thanks!

In this code, the generic lifetime 'a refers to the time during which the struct is alive:

So when you take &'a mut self:

You're basically saying: "I want to mutably borrow self, and that borrow should last for the entire duration that self is valid for."
So when you try to call no_op the 2nd time, it fails to mutably borrow because the previous mutable borrow is still active.

You probably don't want this. This is the code you probably want, and what lifetime elision would create:

pub struct Foo<'a> {
    tokens:&'a Vec<i32>,
}

impl<'a> Foo<'a> {
    pub(crate) fn new(tokens:&'a Vec<i32>) -> Foo<'a> {
        Foo {
            tokens,
        }
    }

    pub fn no_op<'f>(&'f mut self) -> () {}
}

This basically says: "I want to mutably borrow self for the duration of just this function call. So when you call no_op a second time, you can mutably borrow it a 2nd time because the previous borrow ended when the previous function completed.


Edit: For more reading material, see section 5 of:

3 Likes

Awesome - that was what I needed. Thanks!