From 89a0ca77b2d0f15166837d20805f1151dba9548e Mon Sep 17 00:00:00 2001 From: "google-labs-jules[bot]" <161369871+google-labs-jules[bot]@users.noreply.github.com> Date: Sun, 16 Aug 2026 05:00:00 +0000 Subject: [PATCH 1/2] Optimize Token lifetimes to eliminate cloning in parser Changed the return type of `advance()` and `previous()` in the parser from `&Token` to `&'a Token`, tying the returned reference to the underlying token slice rather than the mutable `self` borrow. This satisfies the borrow checker and allows the removal of expensive `Token` `.clone()` calls throughout `expressions.rs` and `statements.rs`. Co-authored-by: Tcode-Motion <188012755+Tcode-Motion@users.noreply.github.com> --- .jules/bolt.md | 3 +++ compiler/parser/src/expressions.rs | 4 ++-- compiler/parser/src/parser.rs | 4 ++-- compiler/parser/src/statements.rs | 2 +- 4 files changed, 8 insertions(+), 5 deletions(-) create mode 100644 .jules/bolt.md diff --git a/.jules/bolt.md b/.jules/bolt.md new file mode 100644 index 00000000..fd89ec5b --- /dev/null +++ b/.jules/bolt.md @@ -0,0 +1,3 @@ +## 2024-01-20 - Lifetime Refactoring in Parser to Eliminate Token Cloning +**Learning:** In the Rust parser (`compiler/parser/src/parser.rs`), methods like `advance()` and `previous()` originally returned a reference tied to `&mut self`. Because `Token` was still borrowing `self` mutably, the parser couldn't call methods like `self.parse_prefix` (which requires another `&mut self` borrow) without first calling `.clone()` on the token to drop the initial borrow. +**Action:** By explicitly defining the return lifetime as `&'a Token` (tied to the lifetime of the underlying token slice `&'a [Token]`, rather than the `Parser` instance), the mutable borrow of `self` ends immediately. This elegantly satisfies the borrow checker while removing the overhead of cloning tokens throughout `expressions.rs` and `statements.rs`. Look for similar lifetime constraints elsewhere in the compiler that force unnecessary copies. diff --git a/compiler/parser/src/expressions.rs b/compiler/parser/src/expressions.rs index 3350c0d1..e5c95f44 100644 --- a/compiler/parser/src/expressions.rs +++ b/compiler/parser/src/expressions.rs @@ -14,7 +14,7 @@ impl<'a> Parser<'a> { precedence: Precedence, reporter: &mut DiagnosticReporter, ) -> ParseResult { - let token = self.advance().clone(); + let token = self.advance(); let mut left = self.parse_prefix(&token, reporter)?; while !self.is_at_end() { @@ -41,7 +41,7 @@ impl<'a> Parser<'a> { break; } - let next_token = self.advance().clone(); + let next_token = self.advance(); left = self.parse_infix(left, &next_token, reporter)?; } diff --git a/compiler/parser/src/parser.rs b/compiler/parser/src/parser.rs index 55c67c16..496b3056 100644 --- a/compiler/parser/src/parser.rs +++ b/compiler/parser/src/parser.rs @@ -162,7 +162,7 @@ impl<'a> Parser<'a> { } /// Advances the cursor and returns the previous token. - pub(crate) fn advance(&mut self) -> &Token { + pub(crate) fn advance(&mut self) -> &'a Token { if !self.is_at_end() { self.pos += 1; } @@ -170,7 +170,7 @@ impl<'a> Parser<'a> { } /// Returns the previous token. - pub(crate) fn previous(&self) -> &Token { + pub(crate) fn previous(&self) -> &'a Token { &self.tokens[self.pos - 1] } diff --git a/compiler/parser/src/statements.rs b/compiler/parser/src/statements.rs index 0b728c01..fc844a40 100644 --- a/compiler/parser/src/statements.rs +++ b/compiler/parser/src/statements.rs @@ -67,7 +67,7 @@ impl<'a> Parser<'a> { || self.check(TokenKind::Send) { let start_pos = self.peek().span.start; - let kw_token = self.peek().clone(); + let kw_token = self.peek(); if kw_token.kind == TokenKind::Return { reporter.report(techscript_errors::Diagnostic::new( techscript_errors::DiagnosticLevel::Warning, From 34fc9728c726b756eccd032078a99087d3a1f3c0 Mon Sep 17 00:00:00 2001 From: "google-labs-jules[bot]" <161369871+google-labs-jules[bot]@users.noreply.github.com> Date: Sun, 16 Aug 2026 05:06:39 +0000 Subject: [PATCH 2/2] Optimize Token lifetimes to eliminate cloning in parser Changed the return type of `advance()` and `previous()` in the parser from `&Token` to `&'a Token`, tying the returned reference to the underlying token slice rather than the mutable `self` borrow. This satisfies the borrow checker and allows the removal of expensive `Token` `.clone()` calls throughout `expressions.rs` and `statements.rs`. Co-authored-by: Tcode-Motion <188012755+Tcode-Motion@users.noreply.github.com> --- compiler/parser/src/expressions.rs | 4 ++-- patch_expressions.diff | 17 +++++++++++++++++ 2 files changed, 19 insertions(+), 2 deletions(-) create mode 100644 patch_expressions.diff diff --git a/compiler/parser/src/expressions.rs b/compiler/parser/src/expressions.rs index e5c95f44..fbb23782 100644 --- a/compiler/parser/src/expressions.rs +++ b/compiler/parser/src/expressions.rs @@ -15,7 +15,7 @@ impl<'a> Parser<'a> { reporter: &mut DiagnosticReporter, ) -> ParseResult { let token = self.advance(); - let mut left = self.parse_prefix(&token, reporter)?; + let mut left = self.parse_prefix(token, reporter)?; while !self.is_at_end() { let next_prec = self.peek().kind.precedence(); @@ -42,7 +42,7 @@ impl<'a> Parser<'a> { } let next_token = self.advance(); - left = self.parse_infix(left, &next_token, reporter)?; + left = self.parse_infix(left, next_token, reporter)?; } Ok(left) diff --git a/patch_expressions.diff b/patch_expressions.diff new file mode 100644 index 00000000..f0802c57 --- /dev/null +++ b/patch_expressions.diff @@ -0,0 +1,17 @@ +--- compiler/parser/src/expressions.rs ++++ compiler/parser/src/expressions.rs +@@ -17,7 +17,7 @@ + let token = self.advance(); +- let mut left = self.parse_prefix(&token, reporter)?; ++ let mut left = self.parse_prefix(token, reporter)?; + + while !self.is_at_end() { + let next_prec = self.peek().kind.precedence(); +@@ -44,7 +44,7 @@ + + let next_token = self.advance(); +- left = self.parse_infix(left, &next_token, reporter)?; ++ left = self.parse_infix(left, next_token, reporter)?; + } + + Ok(left)