fix(clippy): Rust 1.95 compatibility — sort_by_key + collapsible_match

CI runs on stable Rust which advanced from 1.93 to 1.95, introducing
two newly-enforced lints under -D warnings:

- clippy::unnecessary_sort_by (12 sites) — rewrite sort_by closures
  that only call .cmp on Copy keys as sort_by_key, using std::cmp::Reverse
  for the descending ones.
- clippy::collapsible_match (1 site) — merge the MemoryState::Dormant
  inner if into a match guard. The equivalent rewrite for the Ping/Pong
  arm in websocket.rs is blocked by a move of non-Copy Bytes across the
  match-guard boundary, so that one site gets an explicit #[allow].

Files touched:
- crates/vestige-core/src/advanced/{chains,compression,cross_project,reconsolidation}.rs
- crates/vestige-core/src/codebase/{git,relationships}.rs
- crates/vestige-core/src/neuroscience/{importance_signals,memory_states,predictive_retrieval}.rs
- crates/vestige-mcp/src/tools/{changelog,cross_reference}.rs
- crates/vestige-mcp/src/dashboard/websocket.rs

Verified: cargo clippy --workspace -- -D warnings green on rustc 1.95.0;
cargo test --workspace unchanged (1292 tests green).
This commit is contained in:
Sam Valladares 2026-04-19 21:11:49 -05:00
parent 4c2016596c
commit 318d4db147
12 changed files with 21 additions and 20 deletions

View file

@ -333,7 +333,7 @@ impl MemoryChainBuilder {
// Sort by frequency
let mut bridge_list: Vec<_> = bridges.into_iter().collect();
bridge_list.sort_by(|a, b| b.1.cmp(&a.1));
bridge_list.sort_by_key(|b| std::cmp::Reverse(b.1));
bridge_list.into_iter().map(|(id, _)| id).collect()
}

View file

@ -298,7 +298,7 @@ impl MemoryCompressor {
// Sort by age (oldest first)
let mut sorted: Vec<_> = memories.iter().collect();
sorted.sort_by(|a, b| a.created_at.cmp(&b.created_at));
sorted.sort_by_key(|a| a.created_at);
for memory in sorted {
if assigned.contains(&memory.id) {

View file

@ -417,7 +417,7 @@ impl CrossProjectLearner {
}
}
suggestions.sort_by(|a, b| b.priority.cmp(&a.priority));
suggestions.sort_by_key(|b| std::cmp::Reverse(b.priority));
suggestions
}

View file

@ -678,7 +678,7 @@ impl ReconsolidationManager {
.read()
.map(|history| {
let mut recent: Vec<_> = history.iter().cloned().collect();
recent.sort_by(|a, b| b.retrieved_at.cmp(&a.retrieved_at));
recent.sort_by_key(|b| std::cmp::Reverse(b.retrieved_at));
recent.into_iter().take(limit).collect()
})
.unwrap_or_default()

View file

@ -673,11 +673,11 @@ impl GitAnalyzer {
// Top contributors
let mut top_contributors: Vec<_> = author_counts.into_iter().collect();
top_contributors.sort_by(|a, b| b.1.cmp(&a.1));
top_contributors.sort_by_key(|b| std::cmp::Reverse(b.1));
// Hot files (most frequently changed)
let mut hot_files: Vec<_> = file_counts.into_iter().collect();
hot_files.sort_by(|a, b| b.1.cmp(&a.1));
hot_files.sort_by_key(|b| std::cmp::Reverse(b.1));
Ok(HistoryAnalysis {
bug_fixes,

View file

@ -579,7 +579,7 @@ impl RelationshipTracker {
}
let mut sorted: Vec<_> = file_degrees.into_iter().collect();
sorted.sort_by(|a, b| b.1.cmp(&a.1));
sorted.sort_by_key(|b| std::cmp::Reverse(b.1));
sorted.truncate(limit);
sorted

View file

@ -464,7 +464,7 @@ impl PredictionModel {
.filter_map(|ng| patterns.get(&ng).map(|&count| (ng, count)))
.collect();
familiar.sort_by(|a, b| b.1.cmp(&a.1));
familiar.sort_by_key(|b| std::cmp::Reverse(b.1));
familiar.into_iter().take(5).map(|(ng, _)| ng).collect()
}
@ -489,7 +489,7 @@ impl PredictionModel {
fn apply_decay(&self, patterns: &mut HashMap<String, u32>) {
// Remove lowest frequency patterns
let mut entries: Vec<_> = patterns.iter().map(|(k, v)| (k.clone(), *v)).collect();
entries.sort_by(|a, b| a.1.cmp(&b.1));
entries.sort_by_key(|a| a.1);
// Remove bottom 20%
let remove_count = patterns.len() / 5;

View file

@ -1276,14 +1276,12 @@ impl MemoryStateInfo {
));
}
}
MemoryState::Dormant => {
if duration_since_access.num_days() > 20 {
recommendations.push(
"Consider accessing this memory soon to prevent it from \
becoming harder to retrieve."
.to_string(),
);
}
MemoryState::Dormant if duration_since_access.num_days() > 20 => {
recommendations.push(
"Consider accessing this memory soon to prevent it from \
becoming harder to retrieve."
.to_string(),
);
}
_ => {}
}

View file

@ -582,7 +582,7 @@ impl UserModel {
}
// Sort by count and keep top patterns
patterns.sort_by(|a, b| b.1.cmp(&a.1));
patterns.sort_by_key(|b| std::cmp::Reverse(b.1));
patterns.truncate(50);
}

View file

@ -123,6 +123,9 @@ async fn handle_socket(socket: WebSocket, state: AppState) {
msg = receiver.next() => {
match msg {
Some(Ok(Message::Close(_))) | None => break,
// Match guards can't move out of the bound `data` (Bytes is
// not Copy), so the nested `if` is required here.
#[allow(clippy::collapsible_match, clippy::collapsible_if)]
Some(Ok(Message::Ping(data))) => {
if sender.send(Message::Pong(data)).await.is_err() {
break;

View file

@ -237,7 +237,7 @@ fn execute_system_wide(
}
// Sort by timestamp descending
events.sort_by(|a, b| b.0.cmp(&a.0));
events.sort_by_key(|b| std::cmp::Reverse(b.0));
// Truncate to limit
events.truncate(limit as usize);

View file

@ -560,7 +560,7 @@ pub async fn execute(
// Sort by date descending for supersession
let mut by_date = scored.iter().collect::<Vec<_>>();
by_date.sort_by(|a, b| b.updated_at.cmp(&a.updated_at));
by_date.sort_by_key(|b| std::cmp::Reverse(b.updated_at));
for i in 0..by_date.len() {
for j in (i + 1)..by_date.len() {