---
# System prepended metadata

title: Salsa patterns and FAQs

---

# Salsa patterns and FAQs

## How do I model spans (line/column numbers)?

- Anchors! The identity of a tracked span doesn't change, but the values of its fields might.
- https://salsa.zulipchat.com/#narrow/stream/333573-Contributing-to-Salsa/topic/salsa.20patterns.20and.20FAQs/near/472909190

## How do I model a virtual file system?

* [Lazy with lazy source text](https://github.com/astral-sh/ruff/blob/main/crates/ruff_db/src/files.rs#L52)

## How do I move an "eager" computation into a "lazy" one (something done on demand?)

Imagine you have some 

## When should I use `salsa::tracked` vs `salsa::interned`?

The semantic difference between the two is based on *identity*:

* Interned structs have no identity, so `InternedStruct::new(a, b, c) == InternedStruct::new(x, y, z)` is true if `a == x && b == y && c == z`.
* Tracked structs have individual identity, so every `TrackedStruct::new` yields a value struct that is not `==` to any other tracked struct.

## How cheap are interned/tracked structs?

Cheap! You should be able to use them freely. If you find that's not true, let's talk about it.

## What's the `Update` trait for?

## How to update data "in-place"

```rust
// Salsa will cancel any pending queries and remove its own reference to `open_files`
// so that the reference counter to `open_files` now drops to 1.
let open_files = self.set_open_fileset(db).to(None);

let open_files = if let Some(open_files) = open_files {
    Arc::try_unwrap(open_files).unwrap()
} else {
    FxHashSet::default()
};

// Now mutate the data strucuture
open_files.insert(file);
// And write it back to the database
self.set_open_files(db).to(open_files);
```

[source](https://github.com/astral-sh/ruff/blob/bbb044ebda2890061dba6ec53d3d55e0932041ba/crates/red_knot_workspace/src/workspace.rs#L268-L280)