Cannot assign to 'self.x' because it is borrowed

In the code below, I get cannot assign to 'self.index' because it is borrowed compiler error in the line self.index = tmp;

I understand that Self was borrowed by f1, but do not understand, why compiler is complaining, after f1 has already returned - which should mean the scope of the borrow must have ended.

Please help me understand what is going on here and what is the solution.

struct Foo {index: usize}

impl Foo {
    fn f1(&self) -> Result<usize,&str> {
        Ok(12)
    }

    pub fn f2(&mut self) -> Result<(), &str> {
        let tmp = self.f1()?;
        self.index = tmp;
        Ok(())
    }
}

Playground

But it woudn't, if you returned Err, since the full signature is like this:

fn f1<'a>(&'a self) -> Result<usize,&'a str> {
    todo!()
}

Are you sure that the error must borrow from the struct, as the current signature requires?

1 Like

Thanks got it. So the solution is to make the lifetimes explicitly different.

impl<'a, 'b> Foo {
    fn f1(&'a self) -> Result<usize,&'b str> {
        Ok(12)
    }
.
.
.

To expand on that, I find preferable having only static types in the error variant.

Changing from &str to either &'static str or String makes your code compile.

1 Like

Note that unconstrained (i.e. not attached to any input) lifetime parameter in the return value is equivalent to 'static - it is chosen by the caller, so it can be 'static, if they choose, but then you must return something that is indeed 'static; therefore, you can use &'static str instead of &'b str without change in semantics.

2 Likes