salsa_macros/
lib.rs

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