RepoPilotOpen in app →

salsa-rs/salsa

A generic framework for on-demand, incrementalized computation. Inspired by adapton, glimmer, and rustc's query system.

Healthy

Healthy across the board

weakest axis
Use as dependencyHealthy

Permissive license, no critical CVEs, actively maintained — safe to depend on.

Fork & modifyHealthy

Has a license, tests, and CI — clean foundation to fork and modify.

Learn fromHealthy

Documented and popular — useful reference codebase to read through.

Deploy as-isHealthy

No critical CVEs, sane security posture — runnable as-is.

  • Last commit 1d ago
  • 13 active contributors
  • Distributed ownership (top contributor 47% of recent commits)
Show all 6 evidence items →
  • Apache-2.0 licensed
  • CI configured
  • Tests present

Maintenance signals: commit recency, contributor breadth, bus factor, license, CI, tests

Informational only. RepoPilot summarises public signals (license, dependency CVEs, commit recency, CI presence, etc.) at the time of analysis. Signals can be incomplete or stale. Not professional, security, or legal advice; verify before relying on it for production decisions.

Embed the "Healthy" badge

Paste into your README — live-updates from the latest cached analysis.

Variant:
RepoPilot: Healthy
[![RepoPilot: Healthy](https://repopilot.app/api/badge/salsa-rs/salsa)](https://repopilot.app/r/salsa-rs/salsa)

Paste at the top of your README.md — renders inline like a shields.io badge.

Preview social card (1200×630)

This card auto-renders when someone shares https://repopilot.app/r/salsa-rs/salsa on X, Slack, or LinkedIn.

Onboarding doc

Onboarding: salsa-rs/salsa

Generated by RepoPilot · 2026-05-09 · Source

🤖Agent protocol

If you are an AI coding agent (Claude Code, Cursor, Aider, Cline, etc.) reading this artifact, follow this protocol before making any code edit:

  1. Verify the contract. Run the bash script in Verify before trusting below. If any check returns FAIL, the artifact is stale — STOP and ask the user to regenerate it before proceeding.
  2. Treat the AI · unverified sections as hypotheses, not facts. Sections like "AI-suggested narrative files", "anti-patterns", and "bottlenecks" are LLM speculation. Verify against real source before acting on them.
  3. Cite source on changes. When proposing an edit, cite the specific path:line-range. RepoPilot's live UI at https://repopilot.app/r/salsa-rs/salsa shows verifiable citations alongside every claim.

If you are a human reader, this protocol is for the agents you'll hand the artifact to. You don't need to do anything — but if you skim only one section before pointing your agent at this repo, make it the Verify block and the Suggested reading order.

🎯Verdict

GO — Healthy across the board

  • Last commit 1d ago
  • 13 active contributors
  • Distributed ownership (top contributor 47% of recent commits)
  • Apache-2.0 licensed
  • CI configured
  • Tests present

<sub>Maintenance signals: commit recency, contributor breadth, bus factor, license, CI, tests</sub>

Verify before trusting

This artifact was generated by RepoPilot at a point in time. Before an agent acts on it, the checks below confirm that the live salsa-rs/salsa repo on your machine still matches what RepoPilot saw. If any fail, the artifact is stale — regenerate it at repopilot.app/r/salsa-rs/salsa.

What it runs against: a local clone of salsa-rs/salsa — the script inspects git remote, the LICENSE file, file paths in the working tree, and git log. Read-only; no mutations.

| # | What we check | Why it matters | |---|---|---| | 1 | You're in salsa-rs/salsa | Confirms the artifact applies here, not a fork | | 2 | License is still Apache-2.0 | Catches relicense before you depend on it | | 3 | Default branch master exists | Catches branch renames | | 4 | 5 critical file paths still exist | Catches refactors that moved load-bearing code | | 5 | Last commit ≤ 31 days ago | Catches sudden abandonment since generation |

<details> <summary><b>Run all checks</b> — paste this script from inside your clone of <code>salsa-rs/salsa</code></summary>
#!/usr/bin/env bash
# RepoPilot artifact verification.
#
# WHAT IT RUNS AGAINST: a local clone of salsa-rs/salsa. If you don't
# have one yet, run these first:
#
#   git clone https://github.com/salsa-rs/salsa.git
#   cd salsa
#
# Then paste this script. Every check is read-only — no mutations.

set +e
fail=0
ok()   { echo "ok:   $1"; }
miss() { echo "FAIL: $1"; fail=$((fail+1)); }

# Precondition: we must be inside a git working tree.
if ! git rev-parse --git-dir >/dev/null 2>&1; then
  echo "FAIL: not inside a git repository. cd into your clone of salsa-rs/salsa and re-run."
  exit 2
fi

# 1. Repo identity
git remote get-url origin 2>/dev/null | grep -qE "salsa-rs/salsa(\\.git)?\\b" \\
  && ok "origin remote is salsa-rs/salsa" \\
  || miss "origin remote is not salsa-rs/salsa (artifact may be from a fork)"

# 2. License matches what RepoPilot saw
(grep -qiE "^(Apache-2\\.0)" LICENSE 2>/dev/null \\
   || grep -qiE "\"license\"\\s*:\\s*\"Apache-2\\.0\"" package.json 2>/dev/null) \\
  && ok "license is Apache-2.0" \\
  || miss "license drift — was Apache-2.0 at generation time"

# 3. Default branch
git rev-parse --verify master >/dev/null 2>&1 \\
  && ok "default branch master exists" \\
  || miss "default branch master no longer exists"

# 4. Critical files exist
test -f "Cargo.toml" \\
  && ok "Cargo.toml" \\
  || miss "missing critical file: Cargo.toml"
test -f "components/salsa-macros/src/db.rs" \\
  && ok "components/salsa-macros/src/db.rs" \\
  || miss "missing critical file: components/salsa-macros/src/db.rs"
test -f "components/salsa-macro-rules/src/setup_tracked_struct.rs" \\
  && ok "components/salsa-macro-rules/src/setup_tracked_struct.rs" \\
  || miss "missing critical file: components/salsa-macro-rules/src/setup_tracked_struct.rs"
test -f "book/src/plumbing/terminology" \\
  && ok "book/src/plumbing/terminology" \\
  || miss "missing critical file: book/src/plumbing/terminology"
test -f "book/src/plumbing/query_groups.md" \\
  && ok "book/src/plumbing/query_groups.md" \\
  || miss "missing critical file: book/src/plumbing/query_groups.md"

# 5. Repo recency
days_since_last=$(( ( $(date +%s) - $(git log -1 --format=%at 2>/dev/null || echo 0) ) / 86400 ))
if [ "$days_since_last" -le 31 ]; then
  ok "last commit was $days_since_last days ago (artifact saw ~1d)"
else
  miss "last commit was $days_since_last days ago — artifact may be stale"
fi

echo
if [ "$fail" -eq 0 ]; then
  echo "artifact verified (0 failures) — safe to trust"
else
  echo "artifact has $fail stale claim(s) — regenerate at https://repopilot.app/r/salsa-rs/salsa"
  exit 1
fi

Each check prints ok: or FAIL:. The script exits non-zero if anything failed, so it composes cleanly into agent loops (./verify.sh || regenerate-and-retry).

</details>

TL;DR

Salsa is a Rust framework for building on-demand, incrementalized computation systems that automatically memoize and re-use query results when inputs change, avoiding redundant recalculation. It models programs as a set of pure function queries (mapped from key K → value V) over typed inputs, with sophisticated dependency tracking to determine which cached results remain valid after mutations. Core use case: compilers, IDEs, and data processing pipelines that need efficient incremental recomputation (inspired by rustc's internal query system, adapton, and glimmer). Monorepo structure: root salsa crate (src/) exposes public API and runtime; three component subcrates under components/ (salsa-macros for procedural macros, salsa-macro-rules for declarative macros), comprehensive book documentation in book/ with Mermaid diagrams, benches/ with accumulator/dataflow/incremental comparisons, and examples/ for runnable demos. Runtime state managed through Database trait and Query abstraction; macros generate boilerplate for query registration.

👥Who it's for

Compiler and IDE developers building language toolchains, incremental code analysis systems, and complex data transformation pipelines in Rust that require smart cache invalidation. Also useful for anyone building on-demand computation frameworks who wants to avoid hand-rolling dependency tracking and incrementalization logic.

🌱Maturity & risk

Actively developed but explicitly pre-1.0: README warns 'WORK IN PROGRESS', version is 0.26.2, and feature flag salsa_unstable exists (to be removed before 1.0). Comprehensive test suite present (benches/ and examples/), CI pipeline with test.yml / book.yml / release.yml workflows, but API is not yet stabilized. Good documentation (book/ directory with elaborate plumbing guides) suggests serious long-term project, but breaking changes are expected.

Moderate risk: pre-1.0 API means breaking changes between minor versions are possible (check CHANGELOG.md before upgrading). Large dependency tree (parking_lot, rayon, hashbrown, crossbeam, intrusive-collections) increases maintenance surface, though all are mature ecosystem crates. Single active maintainer apparent from GitHub structure; community discussion on Zulip suggests niche audience. Feature flag fragmentation (inventory, persistence, macros, accumulator, shuttle) adds testing complexity.

Active areas of work

Actively maintained with release automation (release.yml publishes to crates.io on version bump in Cargo.toml). Book and documentation are live targets (book.yml builds mdbook site). Feature development ongoing (shuttle integration for concurrent testing, persistence/serde support, inventory-based auto-registration). Pre-1.0 means design discussions likely in open issues; check GitHub issues for direction.

🚀Get running

git clone https://github.com/salsa-rs/salsa.git
cd salsa
cargo build
cargo test
cargo run --example hello

Read book/src/overview.md or examples/ directory for patterns. Requires Rust 1.70+ (check MSRV in workspace Cargo.toml).

Daily commands:

cargo build              # dev build
cargo test --all       # run full test suite
cargo doc --open       # view rustdoc
cargo bench            # run benchmarks in benches/
just                   # if using justfile (see justfile in root)

For book: cd book && mdbook serve (requires mdbook installation).

🗺️Map of the codebase

  • Cargo.toml — Root workspace manifest defining all dependencies (boxcar, crossbeam, parking_lot) and component structure essential for understanding the build.
  • components/salsa-macros/src/db.rs — Core macro implementation for the #[salsa::db] attribute that generates the database trait implementations—foundational to every Salsa user's codebase.
  • components/salsa-macro-rules/src/setup_tracked_struct.rs — Macro rule generator for tracked structs, the primary abstraction for incremental data dependencies in Salsa.
  • book/src/plumbing/terminology — Essential vocabulary definitions (revision, durability, ingredient, memo) required to understand Salsa's incremental computation model.
  • book/src/plumbing/query_groups.md — Documents how query groups organize derived and input queries—critical for structuring contributions and understanding the query system.
  • book/src/how_salsa_works.md — High-level explanation of Salsa's on-demand computation and versioning strategy; essential mental model for contributors.
  • README.md — Project overview, credit to inspirations (adapton, glimmer, rustc query system), and fundamental query concept definitions.

🛠️How to make changes

Add a new derived query to a query group

  1. Define a query trait method in your #[salsa::query_group] trait with the #[salsa::tracked] attribute, specifying input and output types. (book/src/tutorial/db.md)
  2. Implement the query function logic in the impl YourQueryGroup for Database block, using db.input_query() to read dependencies. (components/salsa-macro-rules/src/setup_tracked_fn.rs)
  3. Call the query via db.your_query(args) from other queries or tests; Salsa automatically memoizes and increments only if inputs change. (book/src/plumbing/query_ops.md)

Add a new input query and update its value

  1. Define an input query using #[salsa::input] attribute on a query group method, specifying the value type (e.g., String, struct). (components/salsa-macro-rules/src/setup_input_struct.rs)
  2. In your database implementation, call db.set_input_query(key, new_value) to update the input; Salsa automatically invalidates dependent derived queries. (book/src/plumbing/database.md)
  3. Wrap input mutations in a db.snapshot() or explicit revision bump if coordinating multiple input changes. (book/src/reference/algorithm.md)

Create a new tracked struct with memoized methods

  1. Use #[salsa::tracked] on a struct definition with fields marked as constructor parameters; Salsa interns the struct for efficient equality. (book/src/plumbing/tracked_structs.md)
  2. Add methods to the struct using #[salsa::tracked] on impl blocks; each method becomes a derived query keyed by (struct_id, method_name). (components/salsa-macro-rules/src/setup_tracked_method_body.rs)
  3. Invoke methods via tracked_instance.your_method(db) and depend on them from other queries; results are memoized per struct instance per revision. (book/src/plumbing/memo.md)

Handle cycles in recursive queries

  1. If queries call each other recursively, mark the query with #[salsa::tracked(cycle_recovery)] to enable cycle detection. (book/src/cycles.md)
  2. Implement fallback logic (return a default or cached value) in the query function when a Cycle error is detected. (components/salsa-macro-rules/src/unexpected_cycle_recovery.rs)
  3. Test cycle behavior using expect_panic! or by setting up queries that directly recurse, and verify Salsa breaks the cycle gracefully. (book/src/plumbing/cycles.md)

🔧Why these technologies

  • Procedural macros (salsa-macros) + macro-rules (salsa-macro-rules) — Eliminates boilerplate for trait implementations, ingredient setup, and query code generation; allows zero-cost abstraction while keeping API surface clean.
  • parking_lot (parking_lot::Mutex, RwLock) — Faster and more flexible synchronization primitives than std::sync; essential for lock-free query memoization and runtime performance.
  • crossbeam (queue, utils) — Provides concurrent data structures and utilities for safe multi-threaded query execution and dependency tracking.
  • hashbrown / indexmap — High-performance hash map and ordered map implementations for memo storage, ingredient lookup, and dependency graph representation.
  • intrusive-collections — Zero-allocation linked list and intrusive data structures for efficient LRU eviction and cycle detection in the query graph.

⚖️Trade-offs already made

  • On-demand lazy evaluation with memoization

    • Why: Allows incremental recomputation: only dirty queries re-run, batching input changes minimizes redundant work.
    • Consequence: Adds memory overhead (memo table) and complexity (revision/durability tracking); requires precise dependency tracking to avoid cache invalidation bugs.
  • Trait-based ingredient abstraction (input, derived, tracked, interned)

    • Why: Decouples query logic from storage strategy; makes it easy to add new query types (e.g., accumulators, custom ingredients) without changing core runtime.
    • Consequence: Steeper learning curve for contributors; more indirection and trait object overhead at runtime.
  • Versioning model: revisions + durability + backdate strategy

    • Why: Enables fine-grained incremental invalidation; queries only recompute if dependencies changed (not just inputs), avoiding cascading recomputation.
    • Consequence: Complex state machine (memo states, durability levels, changed_at tracking); bugs in invalidation logic cause silent correctness issues.
  • Cycle detection and recovery (not prevention)

    • Why: Allows recursive/cyclic query dependencies; pragmatic for real-world compiler/analysis workloads (e.g., type inference loops).
    • Consequence:

🪤Traps & gotchas

Cycle detection is strict: recursive queries that depend on themselves will panic unless explicitly marked cycle-safe (handled via cycle recovery in src/cycle.rs); test with --release as debug assertions impact performance. Macro hygiene: salsa-macros generates method names and trait impls; renaming query functions can break generated code (no IDE refactoring support). Lifetime complexity: Database lifetime parameter threads through all query signatures; trait object queries have subtle rules (see db_lifetime.md in book). Testing concurrent mutation: shuttle feature (dep:shuttle) required for deterministic concurrent testing; without it, race conditions may be intermittent. Versioning: each input/query has internal version counter; manual version bumps (via set()) can cause false cache misses if not paired with actual data changes.

🏗️Architecture

💡Concepts to learn

  • Memoization with version-based invalidation — Core mechanism of Salsa: queries cache results tagged with input revision numbers; when inputs mutate, Salsa compares versions to decide if cache is stale without re-running the query function
  • Incremental computation — The entire value proposition: recomputation is scoped to only affected queries (those transitively depending on changed inputs), not the whole program; critical for IDE responsiveness
  • Dependency graph with cycle detection — Salsa builds a dynamic call graph of query dependencies and must detect cycles (recursive queries) to prevent infinite loops; handled via Tarjan's algorithm in src/cycle.rs
  • Self-adjusting computation (SAC) — Theoretical foundation: SAC systems (like Adapton) automatically track computation dependencies; Salsa implements SAC for Rust, enabling compiler writers to add incrementality without manual cache management
  • LRU eviction with pinning — Salsa uses LRU (Least Recently Used) cache with ability to pin active queries; prevents memory unbounded growth while preserving hot results across revision boundaries
  • Query revisions and changed_at tracking — Each query result is tagged with a Revision (monotonicly increasing integer); Salsa tracks when a query's result last changed to enable efficient re-use across unrelated input mutations
  • Procedural + declarative macro-based code generation — Salsa uses salsa-macros (proc-macros) and salsa-macro-rules (declarative) to eliminate boilerplate; #[salsa::tracked] generates memo table, dependency tracking, and update logic automatically
  • rust-lang/rust — rustc's query system (ty::query) is Salsa's primary inspiration; rustc-hash crate is a dep here
  • adapton/adapton.rust — Adapton is foundational prior art for self-adjusting computation and incrementalization that Salsa adapts to Rust
  • helix-editor/helix — Production user of Salsa for incremental tree-sitter parsing and syntax analysis in a modern Rust editor
  • RA-dev/rust-analyzer — Largest Salsa consumer; rust-analyzer uses Salsa extensively for incremental IDE queries (name resolution, type checking)
  • gleam-lang/gleam — Gleam compiler uses Salsa for incremental compilation of functional language, demonstrating cross-language applicability

🪄PR ideas

To work on one of these in Claude Code or Cursor, paste: Implement the "<title>" PR idea from CLAUDE.md, working through the checklist as the task list.

Add comprehensive tests for cycle detection in derived queries

The repo has extensive documentation about cycle handling (book/src/plumbing/cycles.md, book/src/cycles.md) and cycle detection is core to salsa's architecture, but there's no dedicated test file visible in benches/ for cycle scenarios. This would validate that cycles are properly detected, reported, and handled across different query configurations.

  • [ ] Create tests/cycle_detection.rs testing basic cycle detection between derived queries
  • [ ] Add tests for cycle detection with tracked structs (mentioned in book/src/plumbing/tracked_structs.md)
  • [ ] Test cycle behavior with different durability levels (reference in book/src/reference/durability.md)
  • [ ] Add tests for cycle recovery and re-execution after cycle breaks
  • [ ] Document expected panic/error messages for cycles in test comments

Add persistence integration tests for tracked structs and accumulators

The repo has optional persistence feature (serde/erased-serde dependencies) and accumulator support, but no visible integration tests combining these features. Tests should verify that complex tracked structs and accumulators can be correctly serialized/deserialized and restored across database revisions.

  • [ ] Create tests/persistence_integration.rs with serde feature gate
  • [ ] Test serialization of tracked structs with nested fields
  • [ ] Test accumulator persistence and recovery after database reload
  • [ ] Test that memoized results are correctly invalidated after persistence restore
  • [ ] Add test for persistence with durability levels to verify revision tracking is preserved

Create missing reference documentation for inventory-based automatic ingredient registration

The inventory feature is enabled by default in Cargo.toml but book/src/reference/ lacks specific documentation on how it works, when to use it, and how to debug registration issues. Given it's a non-obvious feature, this would help contributors and users understand optional ingredient registration patterns.

  • [ ] Create book/src/reference/automatic_registration.md documenting inventory feature
  • [ ] Add section explaining when automatic registration helps vs. manual registration
  • [ ] Include example code showing #[salsa::tracked] structs with inventory attribute
  • [ ] Document troubleshooting: how to verify ingredients were registered and debug missing registrations
  • [ ] Add cross-reference in book/src/SUMMARY.md to integrate into documentation hierarchy

🌿Good first issues

  • Add integration test for persistence feature (persistence flag enabled): create tests/persistence_integration.rs covering salsa::Update trait serialization for tracked structs, since book/src/plumbing/database.md documents persistence but tests/ appears sparse
  • Write example demonstrating accumulator pattern with cycle detection: examples/ has hello.rs but no example showing #[salsa::accumulator] with recursive queries and cycle recovery (cycles.md in book covers this but no runnable example exists)
  • Document the changed_at(Revision) return value semantics: book/src/plumbing/terminology/changed_at.md exists but could use a code example in src/function.rs or examples/ showing when to use changed_at vs direct dependency edges for cache invalidation strategies

Top contributors

Click to expand

📝Recent commits

Click to expand
  • 7e77c49 — Remove outdated RELEASES.md file; exclude a few more files from published crates (#1091) (musicinmybrain)
  • 236d2c3 — Skip memory usage tests on 32-bit (non-64-bit) targets (#1094) (musicinmybrain)
  • 22d0fe6 — Convert CRLF-terminated sources to LF-terminated (#1092) (musicinmybrain)
  • c9114d4 — chore: release v0.26.2 (#1078) (github-actions[bot])
  • 86bbd77 — Do not use #[allow(non_local_definitions)] (#1090) (ChayimFriedman2)
  • f8e29a4 — Exclude the book from published crates (#1089) (musicinmybrain)
  • 4e1a468 — fix tracked impl db lifetime for as_deref return mode (#1084) (Veykril)
  • 8afa6c9 — Detect overlapping supertype variants via leaf type IDs (#1080) (Veykril)
  • 1fa3d5b — Bump hashbrown to 0.17 (#1087) (MichaReiser)
  • 11ef4c4 — Expose Revision::max() and make it const (#1086) (ChayimFriedman2)

🔒Security observations

The salsa codebase demonstrates generally good security practices for a Rust framework library. No critical vulnerabilities were identified in the dependency manifest, build configuration, or file structure. The main security considerations are: (1) the project is marked as 'WORK IN PROGRESS' with an unstable API that should be finalized before 1.0, (2) optional persistence features should include clear security guidance, and (3) dependency management should be monitored proactively. The codebase includes proper licensing and repository organization. No exposed secrets, hardcoded credentials, SQL injection risks, or infrastructure misconfigurations were detected in the provided file structure.

  • Low · Unstable API Feature Flag Not Removed — Cargo.toml - [features] section. The codebase includes a 'salsa_unstable' feature flag with a comment indicating it should be removed before version 1.0. This suggests the API is not yet stable and may have breaking changes, which could introduce security-relevant bugs. Fix: Plan and execute removal of the 'salsa_unstable' feature flag before the 1.0 release. Ensure comprehensive security audit before stabilization.
  • Low · Optional Persistence Feature Without Clear Documentation — Cargo.toml - [features] persistence section. The 'persistence' feature enables serde-based serialization with 'erased-serde', which could be exploited if deserialization is not carefully validated. The feature appears optional but lacks clear security guidance. Fix: Add security documentation about safe deserialization practices when using the persistence feature. Consider input validation guidelines in the book/documentation.
  • Low · Dependency Version Pinning — Cargo.toml - [dependencies] section. Most dependencies use caret versions (e.g., '0.2.14', '0.3.12') which allow automatic minor/patch updates. While necessary for Rust ecosystem, this could introduce unexpected behavior changes from transitive dependencies. Fix: Regularly audit and update dependencies. Consider using 'cargo-audit' and 'cargo-deny' in CI/CD pipeline to detect known vulnerabilities in transitive dependencies.

LLM-derived; treat as a starting point, not a security audit.


Generated by RepoPilot. Verdict based on maintenance signals — see the live page for receipts. Re-run on a new commit to refresh.

Healthy signals · salsa-rs/salsa — RepoPilot