Skip to main content

salsa_macros/
lib.rs

1//! Procedural macros for defining Salsa databases, ingredients, and queries.
2//!
3//! This crate is an implementation detail of [`salsa`](https://docs.rs/salsa/latest/salsa/). Its
4//! macros are re-exported from that crate and should normally be invoked through the `salsa::`
5//! path.
6//!
7//! See the [`salsa` crate documentation](https://docs.rs/salsa/latest/salsa/) for the concepts
8//! behind each macro.
9
10#![recursion_limit = "256"]
11
12#[macro_use]
13extern crate quote;
14
15use proc_macro::TokenStream;
16
17macro_rules! parse_quote {
18    ($($inp:tt)*) => {
19        {
20            let tt = quote!{$($inp)*};
21            syn::parse2(tt.clone()).unwrap_or_else(|err| {
22                panic!("failed to parse `{}` at {}:{}:{}: {}", tt, file!(), line!(), column!(), err)
23            })
24        }
25    }
26}
27
28/// Similar to `syn::parse_macro_input`, however, when a parse error is encountered, it will return
29/// the input token stream in addition to the error. This will make it so that rust-analyzer can work
30/// with incomplete code.
31macro_rules! parse_macro_input {
32    ($tokenstream:ident as $ty:ty) => {
33        match syn::parse::<$ty>($tokenstream.clone()) {
34            Ok(data) => data,
35            Err(err) => {
36                return $crate::token_stream_with_error($tokenstream, err);
37            }
38        }
39    };
40}
41
42mod accumulator;
43mod db;
44mod db_lifetime;
45mod debug;
46mod fn_util;
47mod hygiene;
48mod input;
49mod interned;
50mod options;
51mod salsa_struct;
52mod salsa_value;
53mod supertype;
54mod tracked;
55mod tracked_fn;
56mod tracked_impl;
57mod tracked_struct;
58mod xform;
59
60/// Defines a type whose values can be accumulated by tracked functions.
61///
62/// Accumulated values are auxiliary outputs, such as diagnostics, collected while a tracked query
63/// runs. They are stored alongside the query's memoized result but do not contribute to that result
64/// or its equality.
65///
66/// The macro implements [`salsa::Accumulator`] for the annotated struct.
67///
68/// See [accumulators in the `salsa` crate documentation] for their semantics and lifecycle.
69///
70/// This macro accepts no options. The annotated type must be a struct and implement
71/// [`Send`] + [`Sync`] + [`UnwindSafe`] + `'static`.
72///
73/// # Example
74///
75/// ```ignore
76/// #[salsa::accumulator]
77/// struct Diagnostic(String);
78///
79/// #[salsa::tracked]
80/// fn check(db: &dyn salsa::Database) {
81///     salsa::Accumulator::accumulate(Diagnostic("something went wrong".into()), db);
82/// }
83/// ```
84///
85/// [`salsa::Accumulator`]: https://docs.rs/salsa/latest/salsa/trait.Accumulator.html
86/// [`UnwindSafe`]: std::panic::UnwindSafe
87/// [accumulators in the `salsa` crate documentation]: https://docs.rs/salsa/latest/salsa/#accumulators
88#[proc_macro_attribute]
89pub fn accumulator(args: TokenStream, input: TokenStream) -> TokenStream {
90    accumulator::accumulator(args, input)
91}
92
93/// Defines a Salsa database struct or database trait.
94///
95/// A database is the state container passed to Salsa operations. Its storage holds inputs, tracked
96/// and interned values, and memoized query results.
97///
98/// This macro accepts no options. Its effect depends on the annotated item:
99///
100/// - On a struct, it implements Salsa's storage plumbing. The struct must have named fields and
101///   one of them must be named `storage`, conventionally with type [`salsa::Storage<Self>`].
102/// - On a trait, it adds the hidden methods Salsa uses to view a database as that trait. Database
103///   traits conventionally extend [`salsa::Database`].
104/// - On a trait implementation, it implements those hidden view methods. Every implementation of
105///   a trait annotated with `#[salsa::db]` must also carry `#[salsa::db]`.
106///
107/// # Example
108///
109/// ```ignore
110/// #[salsa::db]
111/// #[derive(Clone, Default)]
112/// struct MyDatabase {
113///     storage: salsa::Storage<Self>,
114/// }
115///
116/// #[salsa::db]
117/// trait MyDatabaseView: salsa::Database {}
118///
119/// #[salsa::db]
120/// impl MyDatabaseView for MyDatabase {}
121///
122/// #[salsa::db]
123/// impl salsa::Database for MyDatabase {}
124/// ```
125///
126/// [`salsa::Database`]: https://docs.rs/salsa/latest/salsa/trait.Database.html
127/// [`salsa::Storage<Self>`]: https://docs.rs/salsa/latest/salsa/struct.Storage.html
128#[proc_macro_attribute]
129pub fn db(args: TokenStream, input: TokenStream) -> TokenStream {
130    db::db(args, input)
131}
132
133/// Defines an interned struct.
134///
135/// All fields jointly determine the struct's identity. Within a revision, every occurrence of equal
136/// field values maps to the same compact handle. Interned fields are immutable.
137///
138/// The annotated item must be a struct with named fields. It may declare one lifetime parameter,
139/// which Salsa treats as the database lifetime, but no type or const parameters. The generated
140/// struct is [`Copy`] and provides a constructor and field getters. Every field type must implement
141/// [`Clone`] + [`Eq`] + [`Hash`] + [`Send`] + [`Sync`]. A field whose type is unconditionally
142/// `'static` is accepted directly; any other field must implement [`salsa::SalsaValue`].
143///
144/// See [interned structs in the `salsa` crate documentation] for their identity and lifecycle.
145///
146/// # Options
147///
148/// Options are comma-separated inside the attribute:
149///
150/// - `constructor = IDENT` renames the generated constructor from `new` to `IDENT`.
151/// - `debug` implements [`Debug`] using the field values when a database is attached to the current
152///   thread. The generated `default_debug_fmt` method can also be called from a manual [`Debug`]
153///   implementation.
154/// - `revisions = EXPR` sets the minimum number of active revisions an unused value is retained
155///   before its slot may be reused. The default is `3`. The value must be nonzero; `usize::MAX`
156///   disables reuse.
157/// - `heap_size = PATH` records heap use for Salsa's unstable memory-usage reporting. `PATH` must
158///   accept a reference to the tuple of all fields and return its heap allocation size in bytes.
159/// - `persist` enables persistent caching when Salsa's `persistence` feature is enabled. Fields
160///   are serialized as a tuple with [`serde`] by default.
161/// - `persist(serialize = PATH, deserialize = PATH)` enables persistence with custom tuple
162///   serialization functions. Either path may be omitted to use the corresponding [`serde`]
163///   implementation.
164///
165/// ## Legacy adapters
166///
167/// These options exist to adapt older code or external representations to Salsa. New code should
168/// use the default lifetime-bearing struct and [`salsa::Id`], and its field types should implement
169/// [`salsa::SalsaValue`].
170///
171/// - `id = PATH` uses `PATH` as a legacy ID adapter instead of [`salsa::Id`]. The custom type must
172///   implement [`Copy`] + [`Clone`] + [`PartialEq`] + [`Eq`] + [`Hash`] as well as
173///   `salsa::plumbing::AsId` and `salsa::plumbing::FromId`.
174/// - **Unsafe: `no_lifetime` is strongly discouraged.** It adapts code that cannot carry the
175///   database lifetime by generating a struct without one. This bypasses the compile-time
176///   guarantee that an interned handle cannot outlive its database revision. The caller becomes
177///   responsible for ensuring every handle remains valid as revisions advance and interned slots
178///   may be reclaimed or reused.
179/// - **Unsafe: `unsafe(non_salsa_values)` is strongly discouraged.** It adapts field types that do
180///   not implement [`salsa::SalsaValue`] by suppressing the generated checks. The caller becomes
181///   responsible for ensuring retained values remain valid across revisions. Prefer adapting only
182///   the affected field with `#[salsa_value(unsafe(prove_safe_to_retain_manually))]`.
183///
184/// # Field attributes
185///
186/// Every field generates a getter with the same name and visibility as the field. These helper
187/// attributes configure that getter:
188///
189/// - `#[returns(MODE)]` selects how the getter returns the field. `ref` (the default) returns
190///   `&FieldTy`; `clone` returns an owned `FieldTy` using [`Clone`]; `copy` returns an owned
191///   `FieldTy` using [`Copy`]; and `deref` uses [`Deref`] to return
192///   `&<FieldTy as Deref>::Target`. `as_ref` and `as_deref` use [`salsa::SalsaAsRef`] and
193///   [`salsa::SalsaAsDeref`] to return borrowed forms such as `Option<&T>` and
194///   `Option<&T::Target>`. Every borrowed result is tied to the database borrow.
195/// - `#[get(IDENT)]` renames the generated getter.
196/// - **Unsafe: `#[salsa_value(unsafe(prove_safe_to_retain_manually))]`** suppresses the retention
197///   check for this field. The caller must ensure Salsa can retain the field and expose it with a
198///   later database lifetime.
199///
200/// Other attributes, including documentation and lint attributes, are copied to the generated
201/// getter.
202///
203/// # Example
204///
205/// ```ignore
206/// #[salsa::interned(debug)]
207/// struct Name<'db> {
208///     #[returns(deref)]
209///     text: String,
210///     #[returns(copy)]
211///     #[get(disambiguator)]
212///     index: u32,
213/// }
214/// ```
215///
216/// [`Debug`]: std::fmt::Debug
217/// [`Deref`]: std::ops::Deref
218/// [`Hash`]: std::hash::Hash
219/// [`salsa::Id`]: https://docs.rs/salsa/latest/salsa/struct.Id.html
220/// [`salsa::SalsaAsDeref`]: https://docs.rs/salsa/latest/salsa/trait.SalsaAsDeref.html
221/// [`salsa::SalsaAsRef`]: https://docs.rs/salsa/latest/salsa/trait.SalsaAsRef.html
222/// [`salsa::SalsaValue`]: https://docs.rs/salsa/latest/salsa/trait.SalsaValue.html
223/// [`serde`]: https://docs.rs/serde/latest/serde/
224/// [interned structs in the `salsa` crate documentation]: https://docs.rs/salsa/latest/salsa/#interned-structs
225/// [return mode]: https://docs.rs/salsa/latest/salsa/#return-modes
226#[proc_macro_attribute]
227pub fn interned(args: TokenStream, input: TokenStream) -> TokenStream {
228    interned::interned(args, input)
229}
230
231/// Derives a heterogeneous query key from an enum of Salsa structs.
232///
233/// Use a supertype when one tracked function should accept several input, tracked, or interned
234/// struct types. Salsa uses the wrapped struct's ID directly as the query key, while its concrete
235/// Salsa struct type determines the enum variant. Every wrapped value is therefore memoized
236/// independently.
237///
238/// Variants may also wrap another supertype, allowing supertypes to be nested. A concrete Salsa
239/// struct type must be reachable through exactly one variant, including through nested supertypes,
240/// so that Salsa can determine its enum variant unambiguously.
241///
242/// See [supertypes in the `salsa` crate documentation] for more details.
243///
244/// # Example
245///
246/// ```ignore
247/// #[salsa::input]
248/// struct File {
249///     #[returns(deref)]
250///     path: String,
251/// }
252///
253/// #[salsa::interned]
254/// struct Symbol<'db> {
255///     #[returns(deref)]
256///     name: String,
257/// }
258///
259/// #[derive(Clone, Copy, PartialEq, Eq, Hash, salsa::Supertype)]
260/// enum Source<'db> {
261///     File(File),
262///     Symbol(Symbol<'db>),
263/// }
264///
265/// #[salsa::tracked(returns(deref))]
266/// fn display_name<'db>(db: &'db dyn salsa::Database, source: Source<'db>) -> String {
267///     let name = match source {
268///         Source::File(file) => file.path(db),
269///         Source::Symbol(symbol) => symbol.name(db),
270///     };
271///     name.to_owned()
272/// }
273/// ```
274///
275/// [supertypes in the `salsa` crate documentation]: https://docs.rs/salsa/latest/salsa/#supertypes
276#[proc_macro_derive(Supertype)]
277pub fn supertype(input: TokenStream) -> TokenStream {
278    supertype::supertype(input)
279}
280
281/// Defines a mutable input to a Salsa database.
282///
283/// Each constructed input has a distinct identity that remains stable when its fields are changed.
284/// Reading a field records a dependency on that field; setting it invalidates queries that read it.
285///
286/// The macro replaces a named-field struct with a compact, [`Copy`] Salsa ID and generates a
287/// constructor, a builder, and getter and setter methods for every field.
288///
289/// See [input structs in the `salsa` crate documentation] for their identity, field-level
290/// dependencies, and lifecycle.
291///
292/// The annotated item must be a struct with named fields and no generic parameters.
293///
294/// # Options
295///
296/// Options are comma-separated inside the attribute:
297///
298/// - `constructor = IDENT` renames the generated constructor from `new` to `IDENT`.
299/// - `debug` implements [`Debug`] using the field values when a database is attached to the current
300///   thread. The generated `default_debug_fmt` method can also be called from a manual [`Debug`]
301///   implementation.
302/// - `singleton` permits only one instance of this input type in a database and generates
303///   `try_get(db)` and `get(db)` methods for retrieving it.
304/// - `heap_size = PATH` records heap use for Salsa's unstable memory-usage reporting. `PATH` must
305///   accept a reference to the tuple of all fields and return its heap allocation size in bytes.
306/// - `persist` enables persistent caching when Salsa's `persistence` feature is enabled. Fields
307///   are serialized as a tuple with [`serde`] by default.
308/// - `persist(serialize = PATH, deserialize = PATH)` enables persistence with custom tuple
309///   serialization functions. Either path may be omitted to use the corresponding [`serde`]
310///   implementation.
311///
312/// # Field attributes
313///
314/// Every field generates getter and setter methods with the same name and visibility as the field.
315/// These helper attributes configure those methods:
316///
317/// - `#[returns(MODE)]` selects how the getter returns the field. `ref` (the default) returns
318///   `&FieldTy`; `clone` returns an owned `FieldTy` using [`Clone`]; `copy` returns an owned
319///   `FieldTy` using [`Copy`]; and `deref` uses [`Deref`] to return
320///   `&<FieldTy as Deref>::Target`. `as_ref` and `as_deref` use [`salsa::SalsaAsRef`] and
321///   [`salsa::SalsaAsDeref`] to return borrowed forms such as `Option<&T>` and
322///   `Option<&T::Target>`. Every borrowed result is tied to the database borrow.
323/// - `#[get(IDENT)]` renames the generated getter.
324/// - `#[set(IDENT)]` renames the generated setter.
325/// - `#[default]` initializes the field with [`Default::default`], omits it from the constructor's
326///   arguments, and adds a builder method for overriding the default.
327///
328/// Other attributes, including documentation and lint attributes, are copied to the generated
329/// getter.
330///
331/// [`Debug`]: std::fmt::Debug
332/// [`Deref`]: std::ops::Deref
333/// [`salsa::SalsaAsDeref`]: https://docs.rs/salsa/latest/salsa/trait.SalsaAsDeref.html
334/// [`salsa::SalsaAsRef`]: https://docs.rs/salsa/latest/salsa/trait.SalsaAsRef.html
335/// [`serde`]: https://docs.rs/serde/latest/serde/
336/// [input structs in the `salsa` crate documentation]: https://docs.rs/salsa/latest/salsa/#input-structs
337/// [return mode]: https://docs.rs/salsa/latest/salsa/#return-modes
338#[proc_macro_attribute]
339pub fn input(args: TokenStream, input: TokenStream) -> TokenStream {
340    input::input(args, input)
341}
342
343/// Defines a tracked struct or function, or enables tracked methods in an `impl` block.
344///
345/// The accepted syntax and generated API depend on the annotated item. See the sections below for
346/// the options and field attributes accepted by each form.
347///
348/// # Tracked structs
349///
350/// A tracked struct represents a derived entity created during tracked-function execution. Its
351/// identity belongs to the producing query, which can recreate and update the entity in a later
352/// revision.
353///
354/// The annotated item must have named fields and exactly one lifetime parameter, conventionally
355/// `'db`; type and const parameters are not supported. A field whose type is unconditionally
356/// `'static` is accepted directly; any other field must implement [`salsa::SalsaValue`].
357///
358/// See [tracked structs in the `salsa` crate documentation] for their identity, change tracking,
359/// and lifecycle.
360///
361/// ## Struct options
362///
363/// - `constructor = IDENT` renames the generated constructor from `new` to `IDENT`.
364/// - `debug` implements [`Debug`] using the field values when a database is attached to the current
365///   thread. The generated `default_debug_fmt` method can also be called from a manual [`Debug`]
366///   implementation.
367/// - `heap_size = PATH` records heap use for Salsa's unstable memory-usage reporting. `PATH` must
368///   accept a reference to the tuple of all fields and return its heap allocation size in bytes.
369/// - `persist` enables persistent caching when Salsa's `persistence` feature is enabled. Fields
370///   are serialized as a tuple with [`serde`] by default.
371/// - `persist(serialize = PATH, deserialize = PATH)` enables persistence with custom tuple
372///   serialization functions. Either path may be omitted to use the corresponding [`serde`]
373///   implementation.
374///
375/// ## Struct field attributes
376///
377/// - `#[tracked]` excludes the field from the struct's identity. When the producing query recreates
378///   the same entity with a new value for this field, Salsa updates the existing entity instead of
379///   creating a new one. Reads of the field are tracked separately, so changing it invalidates only
380///   queries that read that field. Use this for properties that may change while the conceptual
381///   entity remains the same.
382/// - `#[returns(MODE)]` selects how the getter returns the field. `ref` (the default) returns
383///   `&FieldTy`; `clone` returns an owned `FieldTy` using [`Clone`]; `copy` returns an owned
384///   `FieldTy` using [`Copy`]; and `deref` uses [`Deref`] to return
385///   `&<FieldTy as Deref>::Target`. `as_ref` and `as_deref` use [`salsa::SalsaAsRef`] and
386///   [`salsa::SalsaAsDeref`] to return borrowed forms such as `Option<&T>` and
387///   `Option<&T::Target>`. Every borrowed result is tied to the database borrow.
388/// - `#[get(IDENT)]` renames the generated getter.
389/// - `#[no_eq]` replaces the stored value and treats the field as changed whenever the struct is
390///   recreated, avoiding the [`PartialEq`] requirement. It is most useful together with
391///   `#[tracked]`: because the field does not contribute to identity, the struct can retain its
392///   identity when recreated, while readers of the field are always invalidated.
393/// - **Unsafe: `#[salsa_value(unsafe(prove_safe_to_retain_manually))]`** suppresses the retention
394///   check for this field. The caller must ensure Salsa can retain the field and expose it with a
395///   later database lifetime.
396///
397/// Other attributes, including documentation and lint attributes, are copied to the generated
398/// getter.
399///
400/// # Tracked functions
401///
402/// A tracked function memoizes its result and records the Salsa values read by its body. Salsa
403/// reuses the memoized result while those dependencies remain unchanged.
404///
405/// The first parameter must be an immutable `&dyn DatabaseTrait`; the remaining parameters form
406/// the query key. The function may declare one database lifetime but no type or const parameters.
407/// Every key parameter and the output must implement [`Send`] + [`Sync`]. With no key parameters,
408/// the function has one memoized query per database. A single key parameter must be a Salsa struct
409/// and uses its ID directly. With multiple key parameters, Salsa first interns their tuple to
410/// obtain an ID, adding an interning step to every call. Each key parameter must additionally
411/// implement [`Clone`] + [`Eq`] + [`Hash`]. Equality and hashing determine whether calls use the
412/// same memo, and Salsa always clones the stored tuple when materializing the function arguments.
413/// Interned key parameters and outputs whose types are not unconditionally `'static` must implement
414/// [`salsa::SalsaValue`].
415///
416/// See [tracked functions in the `salsa` crate documentation] for query identity, dependency
417/// tracking, result equality, and memo lifecycle.
418///
419/// ## Function options
420///
421/// - `returns(MODE)` selects how callers receive the memoized result. `ref` (the default) returns
422///   `&Output`; `clone` returns an owned `Output` using [`Clone`]; `copy` returns an owned `Output`
423///   using [`Copy`]; and `deref` uses [`Deref`] to return `&<Output as Deref>::Target`.
424///   `as_ref` and `as_deref` use [`salsa::SalsaAsRef`] and [`salsa::SalsaAsDeref`] to return
425///   borrowed forms such as `Option<&T>` and `Option<&T::Target>`. Every borrowed result is tied to
426///   the database borrow and remains stored in the query's memo.
427/// - `no_eq` treats every newly computed result as changed and removes the output's equality
428///   requirement. It cannot be combined with `cycle_fn`.
429/// - `specify` generates `FUNCTION::specify(db, key, value)`. It supports queries that have both a
430///   per-key incremental implementation and a batch implementation that computes many results at
431///   once. The function must take exactly one key argument, and it must be a tracked struct, not an
432///   input or interned struct. `specify` must be called during the same tracked query invocation
433///   that created the key. It cannot be combined with `lru`. See [specifying query results in the
434///   Salsa book] for an example.
435/// - `lru = INTEGER` bounds the number of memoized values retained by the function and sets the
436///   initial capacity used by `FUNCTION::set_lru_capacity`.
437/// - `cycle_initial = EXPR` enables fixed-point cycle recovery and computes the initial value. The
438///   expression is called as `(db, cycle_head_id, query_arguments...)`.
439/// - `cycle_fn = EXPR` combines successive fixed-point values. It must be accompanied by
440///   `cycle_initial` and is called as
441///   `(db, cycle, previous_value, new_value, query_arguments...)`. See [fixed-point cycle recovery
442///   in the Salsa book] for the convergence requirements and a complete example.
443/// - `cycle_result = EXPR` supplies an immediate fallback for cycles instead of fixed-point
444///   iteration. It is called with the same arguments as `cycle_initial` and cannot be combined
445///   with `cycle_initial` or `cycle_fn`.
446/// - `heap_size = PATH` records heap use for Salsa's unstable memory-usage reporting. `PATH` must
447///   accept a reference to the output and return its heap allocation size in bytes.
448/// - `persist` enables persistent caching when Salsa's `persistence` feature is enabled. The query
449///   inputs and output must implement [`serde::Serialize`] and [`serde::Deserialize`].
450/// - `self_ty = TYPE` prefixes the query's debug name with `TYPE`. The impl-block form supplies
451///   this automatically for methods and associated functions.
452///
453/// ## Legacy function adapter
454///
455/// - **Unsafe: `unsafe(non_salsa_values)` is strongly discouraged.** It adapts output or internally
456///   interned input types that do not implement [`salsa::SalsaValue`] by suppressing the generated
457///   checks. The caller becomes responsible for ensuring retained values remain valid across
458///   revisions. Prefer deriving or implementing [`salsa::SalsaValue`] for those types.
459///
460/// # Tracked impl blocks
461///
462/// Applying `#[salsa::tracked]` to an inherent or trait `impl` allows individual methods and
463/// associated functions in it to also use `#[salsa::tracked(...)]`. The outer attribute accepts no
464/// options; inner attributes accept all tracked-function options.
465///
466/// A tracked method takes `self` by value followed by the database parameter. A tracked associated
467/// function takes the database parameter first. Other methods and associated items are left
468/// unchanged.
469///
470/// # Examples
471///
472/// ```ignore
473/// #[salsa::input]
474/// struct File {
475///     #[returns(deref)]
476///     text: String,
477/// }
478///
479/// #[salsa::tracked(returns(copy))]
480/// fn word_count(db: &dyn salsa::Database, file: File) -> usize {
481///     file.text(db).split_whitespace().count()
482/// }
483///
484/// #[salsa::tracked]
485/// impl File {
486///     #[salsa::tracked(returns(copy))]
487///     fn line_count(self, db: &dyn salsa::Database) -> usize {
488///         self.text(db).lines().count()
489///     }
490/// }
491/// ```
492///
493/// [`Debug`]: std::fmt::Debug
494/// [`Deref`]: std::ops::Deref
495/// [`Eq`]: std::cmp::Eq
496/// [`Hash`]: std::hash::Hash
497/// [`salsa::SalsaAsDeref`]: https://docs.rs/salsa/latest/salsa/trait.SalsaAsDeref.html
498/// [`salsa::SalsaAsRef`]: https://docs.rs/salsa/latest/salsa/trait.SalsaAsRef.html
499/// [`salsa::SalsaValue`]: https://docs.rs/salsa/latest/salsa/trait.SalsaValue.html
500/// [`serde`]: https://docs.rs/serde/latest/serde/
501/// [`serde::Deserialize`]: https://docs.rs/serde/latest/serde/trait.Deserialize.html
502/// [`serde::Serialize`]: https://docs.rs/serde/latest/serde/trait.Serialize.html
503/// [fixed-point cycle recovery in the Salsa book]: https://salsa-rs.github.io/salsa/cycles.html#fixed-point-iteration
504/// [return mode]: https://docs.rs/salsa/latest/salsa/#return-modes
505/// [specifying query results in the Salsa book]: https://salsa-rs.github.io/salsa/overview.html#specify-the-result-of-tracked-functions-for-particular-structs
506/// [tracked functions in the `salsa` crate documentation]: https://docs.rs/salsa/latest/salsa/#tracked-functions-and-memoized-values
507/// [tracked structs in the `salsa` crate documentation]: https://docs.rs/salsa/latest/salsa/#tracked-structs
508#[proc_macro_attribute]
509pub fn tracked(args: TokenStream, input: TokenStream) -> TokenStream {
510    tracked::tracked(args, input)
511}
512
513/// Derives the unsafe [`salsa::SalsaValue`] trait for a struct or enum.
514///
515/// A field whose type is unconditionally `'static` is accepted directly; any other field must
516/// implement [`salsa::SalsaValue`].
517///
518/// The type may declare at most one lifetime parameter. Type and const parameters are supported;
519/// unions are not. Named fields, tuple fields, unit structs, and enum variants are supported.
520///
521/// # Field attributes
522///
523/// A field accepts at most one `#[salsa_value(...)]` attribute:
524///
525/// - **Unsafe: `#[salsa_value(unsafe(prove_safe_to_retain_manually))]`** suppresses the generated
526///   retention check for this field. The author must ensure Salsa can replace its database lifetime
527///   with `'static` for storage and safely restore it later.
528///
529/// # Safety
530///
531/// Its field checks establish the structural requirements, but cannot inspect
532/// invariants maintained by unsafe code in the derived type's methods. By
533/// deriving `SalsaValue`, the author asserts that any such invariants remain
534/// valid when Salsa retains the value across revisions and rebinds its database
535/// lifetime.
536///
537/// # Example
538///
539/// ```ignore
540/// #[derive(salsa::SalsaValue)]
541/// struct QueryValue<'db> {
542///     item: MyInterned<'db>,
543/// }
544/// ```
545///
546/// [`salsa::SalsaValue`]: https://docs.rs/salsa/latest/salsa/trait.SalsaValue.html
547#[proc_macro_derive(SalsaValue, attributes(salsa_value))]
548pub fn salsa_value(input: TokenStream) -> TokenStream {
549    let item = parse_macro_input!(input as syn::DeriveInput);
550    match salsa_value::salsa_value_derive(item) {
551        Ok(tokens) => tokens.into(),
552        Err(error) => error.into_compile_error().into(),
553    }
554}
555
556pub(crate) fn token_stream_with_error(mut tokens: TokenStream, error: syn::Error) -> TokenStream {
557    tokens.extend(TokenStream::from(error.into_compile_error()));
558    tokens
559}
560
561mod kw {
562    syn::custom_keyword!(prove_safe_to_retain_manually);
563}