Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions .jules/bolt.md
Original file line number Diff line number Diff line change
Expand Up @@ -61,3 +61,7 @@
## 2026-04-22 - [Avoid string allocation on single-part split]
**Learning:** Calling `.split(delimiter)` on a reference-counted string (`Arc<str>`) and `.map()`ing the results into `Arc::from(s)` unconditionally creates a new allocation for every chunk. If the delimiter doesn't exist, the entire string is re-allocated unnecessarily.
**Action:** When iterating over a split of a reference-counted string, explicitly check if `s.len() == text.len() && !text.is_empty()`. If it is, use `Arc::clone(&text)` to return another reference to the existing string, bypassing the allocation.

## 2024-05-09 - [Optimize text replacement fast path]

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🟑 Incorrect year in bolt.md entry (2024 instead of 2026)

The new bolt.md entry uses the date 2024-05-09 while every other entry in the file uses dates in 2026 (ranging from 2026-01-03 to 2026-04-22), and the current date is 2026-05-09. This is clearly a typo β€” 2024 should be 2026.

Suggested change
## 2024-05-09 - [Optimize text replacement fast path]
## 2026-05-09 - [Optimize text replacement fast path]
Open in Devin Review

Was this helpful? React with πŸ‘ or πŸ‘Ž to provide feedback.

**Learning:** `str::replace` in Rust always allocates a new `String` even when the target substring is not found, which is inefficient when dealing with reference-counted strings (`Arc<str>`).
**Action:** When performing text replacements on reference-counted strings (like `Arc<str>` in `Value::Text`), always add a fast-path check using `.contains()` before calling `.replace()`. If the substring is not found, return an `Arc::clone` of the original string to prevent unnecessary memory allocation by the standard library.
Comment on lines +65 to +67

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟑 Minor | ⚑ Quick win

Date likely incorrect in learning log entry.

Line 65 uses 2024-05-09, but this PR is dated May 9, 2026 and nearby entries are 2026. This looks like a typo and can make the timeline misleading.

πŸ€– Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In @.jules/bolt.md around lines 65 - 67, The entry header currently reads "##
2024-05-09 - [Optimize text replacement fast path]" but the PR and surrounding
entries are dated May 9, 2026; update that header to "## 2026-05-09 - [Optimize
text replacement fast path]" (or the project's canonical date format) in
.jules/bolt.md so the timeline is consistent, and verify the date fits
chronologically with neighboring entries; locate the header text to change using
the exact phrase "Optimize text replacement fast path".

12 changes: 10 additions & 2 deletions src/stdlib/text.rs
Original file line number Diff line number Diff line change
Expand Up @@ -279,8 +279,16 @@ pub fn native_replace(args: Vec<Value>) -> Result<Value, RuntimeError> {
let text = expect_text(&args[0])?;
let old = expect_text(&args[1])?;
let new = expect_text(&args[2])?;
let result = text.replace(old.as_ref(), new.as_ref());
Ok(Value::Text(Arc::from(result)))

// Optimization: str::replace always allocates a new String even if the substring is not found.
// By checking contains first, we can reuse the Arc reference when no replacement is needed,
// avoiding a memory allocation.
if !text.contains(old.as_ref()) {
Ok(Value::Text(Arc::clone(&text)))
} else {
let result = text.replace(old.as_ref(), new.as_ref());
Ok(Value::Text(Arc::from(result)))
}
}

pub fn native_last_index_of(args: Vec<Value>) -> Result<Value, RuntimeError> {
Expand Down
Loading