#cannot borrow `*self` as mutable because it is also borrowed as immutable

11 messages · Page 1 of 1 (latest)

viscid crow
#

str is a String btw, problems seems to be with it

gaunt sorrel
#

you need to do the str.clone() before you call self.advance() so that the borrow taken by self.peek() can be released

#
TokenType::String(ref str) => {
    let expr = Expr::Literal {
        literal: LiteralType::String(str.clone()),
    };
    self.advance();
    Ok(expr)
}
viscid crow
#

wouldn't it be released after str goes out of scope?

gaunt sorrel
#

No, this is “non-lexical lifetimes” in action. The borrow is released after its last use, not at end of scope.

#

This was implemented because it turned out that not having it was really inconvenient.

viscid crow
#

So basically the compiler will check its last usage and it will release the borrow there, right?

#

I think I understand now, thank you

gaunt sorrel
#

Yes, but there isn't really a “release” step that happens at a specific time.

#

There are two constraints upon the lifetime:

let expr = Expr::Literal {
    literal: LiteralType::String(
        str.clone() // Lifetime must end AFTER this
    ),
};
self.advance();  // Lifetime must end BEFORE this
Ok(expr)

The lifetime must end somewhere in that space, but it can never matter exactly where it is considered to end. It is equally valid for you, and the implementation of the borrow checker, to think about it as any of:

  • self.advance() conflicts with it, so it stops here
  • str.clone() is the last use, so it stops here
  • there are two constraints which do not conflict, and that's all that matters
    All give the same answer.