ra_salsa_macros/
lib.rs

1//! This crate provides salsa's macros and attributes.
2
3#![recursion_limit = "256"]
4
5#[macro_use]
6extern crate quote;
7
8use proc_macro::TokenStream;
9
10mod database_storage;
11mod parenthesized;
12mod query_group;
13
14/// The decorator that defines a salsa "query group" trait. This is a
15/// trait that defines everything that a block of queries need to
16/// execute, as well as defining the queries themselves that are
17/// exported for others to use.
18///
19/// This macro declares the "prototype" for a group of queries. It will
20/// expand into a trait and a set of structs, one per query.
21///
22/// For each query, you give the name of the accessor method to invoke
23/// the query (e.g., `my_query`, below), as well as its parameter
24/// types and the output type. You also give the name for a query type
25/// (e.g., `MyQuery`, below) that represents the query, and optionally
26/// other details, such as its storage.
27///
28/// # Examples
29///
30/// The simplest example is something like this:
31///
32/// ```ignore
33/// #[salsa::query_group]
34/// trait TypeckDatabase {
35///     #[salsa::input] // see below for other legal attributes
36///     fn my_query(&self, input: u32) -> u64;
37///
38///     /// Queries can have any number of inputs (including zero); if there
39///     /// is not exactly one input, then the key type will be
40///     /// a tuple of the input types, so in this case `(u32, f32)`.
41///     fn other_query(&self, input1: u32, input2: f32) -> u64;
42/// }
43/// ```
44///
45/// Here is a list of legal `salsa::XXX` attributes:
46///
47/// - Storage attributes: control how the query data is stored and set. These
48///   are described in detail in the section below.
49///   - `#[salsa::input]`
50///   - `#[salsa::memoized]`
51///   - `#[salsa::dependencies]`
52/// - Query execution:
53///   - `#[salsa::invoke(path::to::my_fn)]` -- for a non-input, this
54///     indicates the function to call when a query must be
55///     recomputed. The default is to call a function in the same
56///     module with the same name as the query.
57///   - `#[query_type(MyQueryTypeName)]` specifies the name of the
58///     dummy struct created for the query. Default is the name of the
59///     query, in camel case, plus the word "Query" (e.g.,
60///     `MyQueryQuery` and `OtherQueryQuery` in the examples above).
61///
62/// # Storage attributes
63///
64/// Here are the possible storage values for each query.  The default
65/// is `storage memoized`.
66///
67/// ## Input queries
68///
69/// Specifying `storage input` will give you an **input
70/// query**. Unlike derived queries, whose value is given by a
71/// function, input queries are explicitly set by doing
72/// `db.query(QueryType).set(key, value)` (where `QueryType` is the
73/// `type` specified for the query). Accessing a value that has not
74/// yet been set will panic. Each time you invoke `set`, we assume the
75/// value has changed, and so we will potentially re-execute derived
76/// queries that read (transitively) from this input.
77///
78/// ## Derived queries
79///
80/// Derived queries are specified by a function.
81///
82/// - `#[salsa::memoized]` (the default) -- The result is memoized
83///   between calls.  If the inputs have changed, we will recompute
84///   the value, but then compare against the old memoized value,
85///   which can significantly reduce the amount of recomputation
86///   required in new revisions. This does require that the value
87///   implements `Eq`.
88/// - `#[salsa::dependencies]` -- does not cache the value, so it will
89///   be recomputed every time it is needed. We do track the inputs, however,
90///   so if they have not changed, then things that rely on this query
91///   may be known not to have changed.
92///
93/// ## Attribute combinations
94///
95/// Some attributes are mutually exclusive. For example, it is an error to add
96/// multiple storage specifiers or to annotate a function to `invoke` on an
97/// `input` query.
98#[proc_macro_attribute]
99pub fn query_group(args: TokenStream, input: TokenStream) -> TokenStream {
100    query_group::query_group(args, input)
101}
102
103/// This attribute is placed on your database struct. It takes a list of the
104/// query groups that your database supports. The format looks like so:
105///
106/// ```rust,ignore
107/// #[salsa::database(MyQueryGroup1, MyQueryGroup2)]
108/// struct MyDatabase {
109///     runtime: salsa::Runtime<MyDatabase>, // <-- your database will need this field, too
110/// }
111/// ```
112///
113/// Here, the struct `MyDatabase` would support the two query groups
114/// `MyQueryGroup1` and `MyQueryGroup2`. In addition to the `database`
115/// attribute, the struct needs to have a `runtime` field (of type
116/// [`salsa::Runtime`]) and to implement the `salsa::Database` trait.
117///
118/// See [the `hello_world` example][hw] for more details.
119///
120/// [`salsa::Runtime`]: struct.Runtime.html
121/// [hw]: https://github.com/salsa-rs/salsa/tree/master/examples/hello_world
122#[proc_macro_attribute]
123pub fn database(args: TokenStream, input: TokenStream) -> TokenStream {
124    database_storage::database(args, input)
125}