From 23090f4337fd295142bf15d53adc3bbd13c89863 Mon Sep 17 00:00:00 2001 From: Lily Acorn Date: Fri, 5 Sep 2025 10:08:04 +0100 Subject: [PATCH 1/6] Avoid .collect with Itertools --- rust/src/filesystem.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/rust/src/filesystem.rs b/rust/src/filesystem.rs index 844c6ad3..d2b8873a 100644 --- a/rust/src/filesystem.rs +++ b/rust/src/filesystem.rs @@ -1,3 +1,4 @@ +use itertools::Itertools; use pyo3::exceptions::{PyFileNotFoundError, PyUnicodeDecodeError}; use pyo3::prelude::*; use regex::Regex; @@ -200,7 +201,6 @@ impl FileSystem for FakeBasicFileSystem { components .into_iter() .map(|c| c.trim_end_matches(&sep).to_string()) - .collect::>() .join(&sep) } From 1baee8ca92d0ff51e8f849503269ebb04f741f60 Mon Sep 17 00:00:00 2001 From: Lily Acorn Date: Fri, 5 Sep 2025 10:11:44 +0100 Subject: [PATCH 2/6] Update FileSystem::sep to return &str instead of String --- rust/src/filesystem.rs | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/rust/src/filesystem.rs b/rust/src/filesystem.rs index d2b8873a..b5365c95 100644 --- a/rust/src/filesystem.rs +++ b/rust/src/filesystem.rs @@ -15,7 +15,7 @@ lazy_static! { } pub trait FileSystem: Send + Sync { - fn sep(&self) -> String; + fn sep(&self) -> &str; fn join(&self, components: Vec) -> String; @@ -38,8 +38,8 @@ pub struct PyRealBasicFileSystem { } impl FileSystem for RealBasicFileSystem { - fn sep(&self) -> String { - std::path::MAIN_SEPARATOR.to_string() + fn sep(&self) -> &str { + std::path::MAIN_SEPARATOR_STR } fn join(&self, components: Vec) -> String { @@ -137,7 +137,7 @@ impl PyRealBasicFileSystem { } #[getter] - fn sep(&self) -> String { + fn sep(&self) -> &str { self.inner.sep() } @@ -192,16 +192,16 @@ impl FakeBasicFileSystem { } impl FileSystem for FakeBasicFileSystem { - fn sep(&self) -> String { - "/".to_string() + fn sep(&self) -> &str { + "/" } fn join(&self, components: Vec) -> String { let sep = self.sep(); components .into_iter() - .map(|c| c.trim_end_matches(&sep).to_string()) - .join(&sep) + .map(|c| c.trim_end_matches(sep).to_string()) + .join(sep) } fn split(&self, file_name: &str) -> (String, String) { @@ -246,7 +246,7 @@ impl PyFakeBasicFileSystem { } #[getter] - fn sep(&self) -> String { + fn sep(&self) -> &str { self.inner.sep() } From d74a2dee93916fccdf15f157c490b70a597adc53 Mon Sep 17 00:00:00 2001 From: Lily Acorn Date: Fri, 5 Sep 2025 10:29:18 +0100 Subject: [PATCH 3/6] Add helpful error message to FakeBasicFileSystem::read --- rust/src/filesystem.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/rust/src/filesystem.rs b/rust/src/filesystem.rs index b5365c95..4ae3cb3a 100644 --- a/rust/src/filesystem.rs +++ b/rust/src/filesystem.rs @@ -230,7 +230,7 @@ impl FileSystem for FakeBasicFileSystem { fn read(&self, file_name: &str) -> PyResult { match self.contents.get(file_name) { Some(file_name) => Ok(file_name.clone()), - None => Err(PyFileNotFoundError::new_err("")), + None => Err(PyFileNotFoundError::new_err(format!("No such file: {file_name}"))), } } } From 0b37a8eb5fd69c049d74e9229b2f1a26581f9ff8 Mon Sep 17 00:00:00 2001 From: Lily Acorn Date: Fri, 5 Sep 2025 10:30:39 +0100 Subject: [PATCH 4/6] Avoid vec clone by pulling a variable out of the loop --- rust/src/filesystem.rs | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/rust/src/filesystem.rs b/rust/src/filesystem.rs index 4ae3cb3a..9b9ecf8b 100644 --- a/rust/src/filesystem.rs +++ b/rust/src/filesystem.rs @@ -288,7 +288,8 @@ pub fn parse_indented_file_system_string(file_system_string: &str) -> HashMap = buffer.split('\n').collect(); - for line_raw in lines.clone() { + let first_line_starts_with_slash = lines[0].trim().starts_with('/'); + for line_raw in lines { let line = line_raw.trim_end(); // Remove trailing whitespace if line.is_empty() { continue; // Skip empty lines @@ -331,7 +332,7 @@ pub fn parse_indented_file_system_string(file_system_string: &str) -> HashMap Date: Fri, 5 Sep 2025 10:42:38 +0100 Subject: [PATCH 5/6] Replace .unwrap with .expect for clarity --- rust/src/filesystem.rs | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/rust/src/filesystem.rs b/rust/src/filesystem.rs index 9b9ecf8b..2f1c4806 100644 --- a/rust/src/filesystem.rs +++ b/rust/src/filesystem.rs @@ -47,7 +47,7 @@ impl FileSystem for RealBasicFileSystem { for component in components { path.push(component); } - path.to_str().unwrap().to_string() + path.to_str().expect("Path components should be valid unicode").to_string() } fn split(&self, file_name: &str) -> (String, String) { @@ -66,8 +66,8 @@ impl FileSystem for RealBasicFileSystem { }; ( - head.to_str().unwrap().to_string(), - tail.to_str().unwrap().to_string(), + head.to_str().expect("Path components should be valid unicode").to_string(), + tail.to_str().expect("Path components should be valid unicode").to_string(), ) } @@ -217,8 +217,8 @@ impl FileSystem for FakeBasicFileSystem { tail = path.file_name().unwrap_or(OsStr::new("")); } ( - head.to_str().unwrap().to_string(), - tail.to_str().unwrap().to_string(), + head.to_str().expect("Path components should be valid unicode").to_string(), + tail.to_str().expect("Path components should be valid unicode").to_string(), ) } @@ -354,7 +354,7 @@ pub fn parse_indented_file_system_string(file_system_string: &str) -> HashMap Date: Fri, 5 Sep 2025 11:11:35 +0100 Subject: [PATCH 6/6] Replace lazy_static with LazyLock Remove unused `EMPTY_IMPORTS`. --- rust/Cargo.lock | 7 ------- rust/Cargo.toml | 1 - rust/src/filesystem.rs | 8 ++++---- rust/src/graph/mod.rs | 24 +++++++++++++----------- rust/src/module_expressions.rs | 9 ++++----- 5 files changed, 21 insertions(+), 28 deletions(-) diff --git a/rust/Cargo.lock b/rust/Cargo.lock index d5c457f5..3b11604a 100644 --- a/rust/Cargo.lock +++ b/rust/Cargo.lock @@ -13,7 +13,6 @@ dependencies = [ "getset", "indexmap 2.9.0", "itertools 0.14.0", - "lazy_static", "parameterized", "pyo3", "rayon", @@ -274,12 +273,6 @@ version = "1.0.15" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4a5f13b858c8d314ee3e8f639011f7ccefe71f97f96e50151fb991f267928e2c" -[[package]] -name = "lazy_static" -version = "1.5.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bbd2bcb4c963f2ddae06a2efc7e9f3591312473c50c6685e1f298068316e66fe" - [[package]] name = "libc" version = "0.2.172" diff --git a/rust/Cargo.toml b/rust/Cargo.toml index 1b346c8a..c9ca82aa 100644 --- a/rust/Cargo.toml +++ b/rust/Cargo.toml @@ -13,7 +13,6 @@ bimap = "0.6.3" slotmap = "1.0.7" getset = "0.1.3" derive-new = "0.7.0" -lazy_static = "1.5.0" string-interner = "0.18.0" thiserror = "2.0.11" itertools = "0.14.0" diff --git a/rust/src/filesystem.rs b/rust/src/filesystem.rs index 2f1c4806..1ae4b987 100644 --- a/rust/src/filesystem.rs +++ b/rust/src/filesystem.rs @@ -6,13 +6,13 @@ use std::collections::HashMap; use std::ffi::OsStr; use std::fs; use std::path::{Path, PathBuf}; +use std::sync::LazyLock; use unindent::unindent; -use lazy_static::lazy_static; -lazy_static! { - static ref ENCODING_RE: Regex = Regex::new(r"^[ \t\f]*#.*?coding[:=][ \t]*([-_.a-zA-Z0-9]+)").unwrap(); -} +static ENCODING_RE: LazyLock = LazyLock::new(|| { + Regex::new(r"^[ \t\f]*#.*?coding[:=][ \t]*([-_.a-zA-Z0-9]+)").unwrap() +}); pub trait FileSystem: Send + Sync { fn sep(&self) -> &str; diff --git a/rust/src/graph/mod.rs b/rust/src/graph/mod.rs index 88ffe891..54674648 100644 --- a/rust/src/graph/mod.rs +++ b/rust/src/graph/mod.rs @@ -1,10 +1,9 @@ use bimap::BiMap; use derive_new::new; use getset::{CopyGetters, Getters}; -use lazy_static::lazy_static; use rustc_hash::{FxHashMap, FxHashSet}; use slotmap::{SecondaryMap, SlotMap, new_key_type}; -use std::sync::RwLock; +use std::sync::{LazyLock, RwLock}; use string_interner::backend::StringBackend; use string_interner::{DefaultSymbol, StringInterner}; @@ -16,15 +15,18 @@ pub mod import_chain_queries; pub(crate) mod pathfinding; -lazy_static! { - static ref MODULE_NAMES: RwLock> = - RwLock::new(StringInterner::default()); - static ref IMPORT_LINE_CONTENTS: RwLock> = - RwLock::new(StringInterner::default()); - static ref EMPTY_MODULE_TOKENS: FxHashSet = FxHashSet::default(); - static ref EMPTY_IMPORT_DETAILS: FxHashSet = FxHashSet::default(); - static ref EMPTY_IMPORTS: FxHashSet<(ModuleToken, ModuleToken)> = FxHashSet::default(); -} +static MODULE_NAMES: LazyLock>> = LazyLock::new(|| { + RwLock::new(StringInterner::default()) +}); +static IMPORT_LINE_CONTENTS: LazyLock>> = LazyLock::new(|| { + RwLock::new(StringInterner::default()) +}); +static EMPTY_MODULE_TOKENS: LazyLock> = LazyLock::new(|| { + FxHashSet::default() +}); +static EMPTY_IMPORT_DETAILS: LazyLock> = LazyLock::new(|| { + FxHashSet::default() +}); new_key_type! { pub struct ModuleToken; } diff --git a/rust/src/module_expressions.rs b/rust/src/module_expressions.rs index df1b02b0..6e2a1687 100644 --- a/rust/src/module_expressions.rs +++ b/rust/src/module_expressions.rs @@ -1,15 +1,14 @@ use crate::errors::{GrimpError, GrimpResult}; use const_format::formatcp; use itertools::Itertools; -use lazy_static::lazy_static; use regex::Regex; use std::fmt::Display; use std::str::FromStr; +use std::sync::LazyLock; -lazy_static! { - static ref MODULE_EXPRESSION_PATTERN: Regex = - Regex::new(r"^(\w+|\*{1,2})(\.(\w+|\*{1,2}))*$").unwrap(); -} +static MODULE_EXPRESSION_PATTERN: LazyLock = LazyLock::new(|| { + Regex::new(r"^(\w+|\*{1,2})(\.(\w+|\*{1,2}))*$").unwrap() +}); /// A module expression is used to refer to sets of modules. ///