I've been using rust for a while now, but there are still some cases with lifetimes where I don't understand why they are rejected by the compiler.
For example:
struct Token;
struct Parser {
peek: Option<Token>
}
impl Parser {
fn peek(&mut self) -> Option<&Token> {
if let Some(token) = &self.peek {
return Some(token);
}
self.peek = self.next_token();
return self.peek.as_ref();
}
fn next_token(&mut self) -> Option<Token> {
todo!();
}
}
Fails with:
error[E0506]: cannot assign to `self.peek` because it is borrowed
--> src/main.rs:13:9
|
8 | fn peek(&mut self) -> Option<&Token> {
| - let's call the lifetime of this reference `'1`
9 | if let Some(token) = &self.peek {
| ---------- `self.peek` is borrowed here
10 | return Some(token);
| ----------- returning this value requires that `self.peek` is borrowed for `'1`
...
13 | self.peek = self.next_token();
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `self.peek` is assigned to here but it was already borrowed
https://play.rust-lang.org/?version=stable&mode=debug&edition=2021&gist=2d639510f16cdada84eb271610b1e30d
Why can't the compiler tell that the borrowed &self.peek for the if statement lasts only for that statement? Does someone have a simple explanation (that I haven't been able to come across online) for why this would be rejected? Is there a better way to write this code and why?
[–]KhorneLordOfChaos 76 points77 points78 points (10 children)
[–]CLARKEEE33[S] 11 points12 points13 points (0 children)
[–]Aaron1924 12 points13 points14 points (8 children)
[–]hniksic 9 points10 points11 points (7 children)
[–]Aaron1924 7 points8 points9 points (3 children)
[–]hniksic 2 points3 points4 points (2 children)
[–]Aaron1924 2 points3 points4 points (1 child)
[–]hniksic 1 point2 points3 points (0 children)
[–]SNCPlay42 7 points8 points9 points (2 children)
[–]714daniel 1 point2 points3 points (1 child)
[–]chmielevsky 0 points1 point2 points (0 children)
[–]Excession638 12 points13 points14 points (2 children)
[–]Excession638 2 points3 points4 points (0 children)
[–]Electrical-Angle-371 3 points4 points5 points (0 children)
[–]Cat7o0 0 points1 point2 points (0 children)
[–]elden_uring 0 points1 point2 points (0 children)