diff --git a/book/src/tutorial/jar.md b/book/src/tutorial/jar.md index 48cece5..73204ac 100644 --- a/book/src/tutorial/jar.md +++ b/book/src/tutorial/jar.md @@ -1,21 +1,23 @@ # Jars and databases Salsa programs are composed in **jars**[^jar]. -A **jar** is the salsa version of a Rust crate or module. -It is a struct that contains the memoized results for some subset of your program. +A jar is just a fancy name for a struct whose fields contain the hashmaps and other state required to implement salsa concepts like [memoized function](../overview.md#memoized-functions) or [entity](../overview.md#entity-values)/[interned](../overview.md#interned-values) structs. +Typically you have one jar per crate, but that is not required. +When you declare the salsa database, you will give it a list of all the jar structs in your program, and it will allocate one of each so as to have all the storage it needs. -Typically you define one jar per crate in your program, and you define it at the path `crate::Jar`. -You don't have to do this, but it's more convenient because the various salsa macros have defaults that expect the jar to be at this location. +Each time you declare something like a [memoized function], it is associated with some jar. +By default, that jar is expected to be `crate::Jar`. +You can give the jar struct another name, or put it somewhere else, but then you will have to write `jar = path::to::your::Jar` everywhere, so it's not recommended. -Our `calc` example has only a single crate, but we'll still put the `Jar` struct at the root of the crate: +Our `calc` example has only a single crate. We follow the salsa convention and declare the `Jar` struct at the root of the crate: ```rust {{#include ../../../calc-example/calc/src/main.rs:jar_struct}} ``` -The `#[salsa::jar]` annotation indicates that this struct is a Salsa jar. -The struct must be a tuple struct, and the fields in the struct correspond to the salsa [memoized functions], [entities], and other concepts that we are going to introduce in this tutorial. -The idea is that the field type will contain the storage needed to implement that particular salsa-ized thing. +You can see that a jar is just a tuple struct, but annotated with `#[salsa::Jar]`. +The fields of the struct correspond to the various things that need state in the database. +We're going to be introducing each of those fields through the tutorial. [memoized functions]: ../reference/memoized.md [entities]: ../reference/entity.md @@ -31,8 +33,8 @@ It identifies the **database trait** for this jar. Whereas a salsa jar contains all the storage needed for a particular crate, the salsa **database** is a struct that contains all the storage needed for an entire program. -Jars, however, don't refer directly to this database struct. -Instead, each jar defines a trait, typically called `Db`, that the struct must implement. +Typical salsa functions, however, don't refer directly to this database struct. +Instead, they refer to a trait, typically called `crate::Db`, that the final database must implement. This allows for separate compilation, where you have a database that contains the data for two jars, but those jars don't depend on one another. The database trait for our `calc` crate is very simple: @@ -61,3 +63,14 @@ and that's what we do here: ```rust {{#include ../../../calc-example/calc/src/main.rs:jar_db_impl}} ``` + +## Summary + +If the concept of a jar seems a bit abstract to you, don't overthink it. The TL;DR is that when you create a salsa program, you need to do: + +- In each of your crates: + - Define a `#[salsa::jar(db = Db)]` struct, typically at `crate::Jar`, and list each of your various salsa-annotated things inside of it. + - Define a `Db` trait, typically at `crate::Db`, that you will use in memoized functions and elsewhere to refer to the database struct. +- Once, typically in your final crate: + - Define a database `D`, as described in the [next section](./db.md), that will contain a list of each of the jars for each of your crates. + - Implement the `Db` traits for each jar for your database type `D` (often we do this through blanket impls in the jar crates).