I know that this is the classic Rust beginner's problem. I feel like I have an understanding of why this is a problem, but I don't have enough background to understand what the idiomatic solution(s) to it are.
I'm trying to implement a basic parser - where I read tokens one at a time, advance the position, and build a syntax tree (not shown here).
pub struct Parser {
// this field is actually going to be static for the lifecycle of the parser
tokens: Vec<Token>,
// this field is mutated as the parser advances
position: usize,
}
impl Parser {
// fetch the current token
fn peek(&self) -> Option<&Token> {
if self.position < self.tokens.len() {
Some(&self.tokens[self.position])
} else {
None
}
}
// fetch the current token and advance the position
fn read(&mut self) -> Option<&Token> {
let token = self.peek();
if token != None {
self.position += 1;
}
token
}
}
My understanding of why this is a problem (please correct me if I'm misunderstanding): The token pointer returned by peek() is associated with the lifecycle of self, so without further information, the borrow checker has to assume I have exclusive ownership of the whole reference. The self.position increment also requires ownership of self, hence the conflict.
I'd like to be able to indicate to the compiler (which I feel does make what I'm doing safe) is that I'm actually only mutating position, and that token is a pointer to an immutable structure (as far as the application logic is concerned).
I think that understanding the problem is simpler than understanding the idiomatic way to fix it - hence why I'm coming here ![]()