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: `unsafe(no_lifetime)` is strongly discouraged.** It adapts code that cannot carry
175/// the database lifetime by generating a struct without one. This bypasses the compile-time
176/// guarantee that an interned handle cannot outlive its database. It must be combined with
177/// `revisions = usize::MAX` so that interned slots are never reclaimed or reused.
178/// - **Unsafe: `unsafe(non_salsa_values)` is strongly discouraged.** It adapts field types that do
179/// not implement [`salsa::SalsaValue`] by suppressing the generated checks. The caller becomes
180/// responsible for ensuring retained values remain valid across revisions. Prefer adapting only
181/// the affected field with `#[salsa_value(unsafe(prove_safe_to_retain_manually))]`.
182///
183/// # Field attributes
184///
185/// Every field generates a getter with the same name and visibility as the field. These helper
186/// attributes configure that getter:
187///
188/// - `#[returns(MODE)]` selects how the getter returns the field. `ref` (the default) returns
189/// `&FieldTy`; `clone` returns an owned `FieldTy` using [`Clone`]; `copy` returns an owned
190/// `FieldTy` using [`Copy`]; and `deref` uses [`Deref`] to return
191/// `&<FieldTy as Deref>::Target`. `as_ref` and `as_deref` use [`salsa::SalsaAsRef`] and
192/// [`salsa::SalsaAsDeref`] to return borrowed forms such as `Option<&T>` and
193/// `Option<&T::Target>`. Every borrowed result is tied to the database borrow.
194/// - `#[get(IDENT)]` renames the generated getter.
195/// - **Unsafe: `#[salsa_value(unsafe(prove(Predicate, ...)))]`** replaces the retention check with
196/// predicates that must hold for every database lifetime. The compiler verifies the predicates,
197/// but the caller must ensure they imply that Salsa can retain the field and expose it with a later
198/// database lifetime.
199/// - **Unsafe: `#[salsa_value(unsafe(prove_safe_to_retain_manually))]`** suppresses the retention
200/// check for this field without adding predicates. The caller must ensure Salsa can retain the
201/// field and expose it with a later database lifetime.
202///
203/// Other attributes, including documentation and lint attributes, are copied to the generated
204/// getter.
205///
206/// # Example
207///
208/// ```ignore
209/// #[salsa::interned(debug)]
210/// struct Name<'db> {
211/// #[returns(deref)]
212/// text: String,
213/// #[returns(copy)]
214/// #[get(disambiguator)]
215/// index: u32,
216/// }
217/// ```
218///
219/// [`Debug`]: std::fmt::Debug
220/// [`Deref`]: std::ops::Deref
221/// [`Hash`]: std::hash::Hash
222/// [`salsa::Id`]: https://docs.rs/salsa/latest/salsa/struct.Id.html
223/// [`salsa::SalsaAsDeref`]: https://docs.rs/salsa/latest/salsa/trait.SalsaAsDeref.html
224/// [`salsa::SalsaAsRef`]: https://docs.rs/salsa/latest/salsa/trait.SalsaAsRef.html
225/// [`salsa::SalsaValue`]: https://docs.rs/salsa/latest/salsa/trait.SalsaValue.html
226/// [`serde`]: https://docs.rs/serde/latest/serde/
227/// [interned structs in the `salsa` crate documentation]: https://docs.rs/salsa/latest/salsa/#interned-structs
228/// [return mode]: https://docs.rs/salsa/latest/salsa/#return-modes
229#[proc_macro_attribute]
230pub fn interned(args: TokenStream, input: TokenStream) -> TokenStream {
231 interned::interned(args, input)
232}
233
234/// Derives a heterogeneous query key from an enum of Salsa structs.
235///
236/// Use a supertype when one tracked function should accept several input, tracked, or interned
237/// struct types. Salsa uses the wrapped struct's ID directly as the query key, while its concrete
238/// Salsa struct type determines the enum variant. Every wrapped value is therefore memoized
239/// independently.
240///
241/// Variants may also wrap another supertype, allowing supertypes to be nested. A concrete Salsa
242/// struct type must be reachable through exactly one variant, including through nested supertypes,
243/// so that Salsa can determine its enum variant unambiguously.
244///
245/// See [supertypes in the `salsa` crate documentation] for more details.
246///
247/// # Example
248///
249/// ```ignore
250/// #[salsa::input]
251/// struct File {
252/// #[returns(deref)]
253/// path: String,
254/// }
255///
256/// #[salsa::interned]
257/// struct Symbol<'db> {
258/// #[returns(deref)]
259/// name: String,
260/// }
261///
262/// #[derive(Clone, Copy, PartialEq, Eq, Hash, salsa::Supertype)]
263/// enum Source<'db> {
264/// File(File),
265/// Symbol(Symbol<'db>),
266/// }
267///
268/// #[salsa::tracked(returns(deref))]
269/// fn display_name<'db>(db: &'db dyn salsa::Database, source: Source<'db>) -> String {
270/// let name = match source {
271/// Source::File(file) => file.path(db),
272/// Source::Symbol(symbol) => symbol.name(db),
273/// };
274/// name.to_owned()
275/// }
276/// ```
277///
278/// [supertypes in the `salsa` crate documentation]: https://docs.rs/salsa/latest/salsa/#supertypes
279#[proc_macro_derive(Supertype)]
280pub fn supertype(input: TokenStream) -> TokenStream {
281 supertype::supertype(input)
282}
283
284/// Defines a mutable input to a Salsa database.
285///
286/// Each constructed input has a distinct identity that remains stable when its fields are changed.
287/// Reading a field records a dependency on that field; setting it invalidates queries that read it.
288///
289/// The macro replaces a named-field struct with a compact, [`Copy`] Salsa ID and generates a
290/// constructor, a builder, and getter and setter methods for every field.
291///
292/// See [input structs in the `salsa` crate documentation] for their identity, field-level
293/// dependencies, and lifecycle.
294///
295/// The annotated item must be a struct with named fields and no generic parameters.
296///
297/// # Options
298///
299/// Options are comma-separated inside the attribute:
300///
301/// - `constructor = IDENT` renames the generated constructor from `new` to `IDENT`.
302/// - `debug` implements [`Debug`] using the field values when a database is attached to the current
303/// thread. The generated `default_debug_fmt` method can also be called from a manual [`Debug`]
304/// implementation.
305/// - `singleton` permits only one instance of this input type in a database and generates
306/// `try_get(db)` and `get(db)` methods for retrieving it.
307/// - `heap_size = PATH` records heap use for Salsa's unstable memory-usage reporting. `PATH` must
308/// accept a reference to the tuple of all fields and return its heap allocation size in bytes.
309/// - `persist` enables persistent caching when Salsa's `persistence` feature is enabled. Fields
310/// are serialized as a tuple with [`serde`] by default.
311/// - `persist(serialize = PATH, deserialize = PATH)` enables persistence with custom tuple
312/// serialization functions. Either path may be omitted to use the corresponding [`serde`]
313/// implementation.
314///
315/// # Field attributes
316///
317/// Every field generates getter and setter methods with the same name and visibility as the field.
318/// These helper attributes configure those methods:
319///
320/// - `#[returns(MODE)]` selects how the getter returns the field. `ref` (the default) returns
321/// `&FieldTy`; `clone` returns an owned `FieldTy` using [`Clone`]; `copy` returns an owned
322/// `FieldTy` using [`Copy`]; and `deref` uses [`Deref`] to return
323/// `&<FieldTy as Deref>::Target`. `as_ref` and `as_deref` use [`salsa::SalsaAsRef`] and
324/// [`salsa::SalsaAsDeref`] to return borrowed forms such as `Option<&T>` and
325/// `Option<&T::Target>`. Every borrowed result is tied to the database borrow.
326/// - `#[get(IDENT)]` renames the generated getter.
327/// - `#[set(IDENT)]` renames the generated setter.
328/// - `#[default]` initializes the field with [`Default::default`], omits it from the constructor's
329/// arguments, and adds a builder method for overriding the default.
330///
331/// Input fields do not support `#[salsa_value(...)]`. Input field types are stored without database
332/// lifetime rebinding, so neither conditional nor unconditional retention proofs apply.
333///
334/// Other attributes, including documentation and lint attributes, are copied to the generated
335/// getter.
336///
337/// [`Debug`]: std::fmt::Debug
338/// [`Deref`]: std::ops::Deref
339/// [`salsa::SalsaAsDeref`]: https://docs.rs/salsa/latest/salsa/trait.SalsaAsDeref.html
340/// [`salsa::SalsaAsRef`]: https://docs.rs/salsa/latest/salsa/trait.SalsaAsRef.html
341/// [`serde`]: https://docs.rs/serde/latest/serde/
342/// [input structs in the `salsa` crate documentation]: https://docs.rs/salsa/latest/salsa/#input-structs
343/// [return mode]: https://docs.rs/salsa/latest/salsa/#return-modes
344#[proc_macro_attribute]
345pub fn input(args: TokenStream, input: TokenStream) -> TokenStream {
346 input::input(args, input)
347}
348
349/// Defines a tracked struct or function, or enables tracked methods in an `impl` block.
350///
351/// The accepted syntax and generated API depend on the annotated item. See the sections below for
352/// the options and field attributes accepted by each form.
353///
354/// # Tracked structs
355///
356/// A tracked struct represents a derived entity created during tracked-function execution. Its
357/// identity belongs to the producing query, which can recreate and update the entity in a later
358/// revision.
359///
360/// The annotated item must have named fields and exactly one lifetime parameter, conventionally
361/// `'db`; type and const parameters are not supported. A field whose type is unconditionally
362/// `'static` is accepted directly; any other field must implement [`salsa::SalsaValue`].
363///
364/// See [tracked structs in the `salsa` crate documentation] for their identity, change tracking,
365/// and lifecycle.
366///
367/// ## Struct options
368///
369/// - `constructor = IDENT` renames the generated constructor from `new` to `IDENT`.
370/// - `debug` implements [`Debug`] using the field values when a database is attached to the current
371/// thread. The generated `default_debug_fmt` method can also be called from a manual [`Debug`]
372/// implementation.
373/// - `heap_size = PATH` records heap use for Salsa's unstable memory-usage reporting. `PATH` must
374/// accept a reference to the tuple of all fields and return its heap allocation size in bytes.
375/// - `persist` enables persistent caching when Salsa's `persistence` feature is enabled. Fields
376/// are serialized as a tuple with [`serde`] by default.
377/// - `persist(serialize = PATH, deserialize = PATH)` enables persistence with custom tuple
378/// serialization functions. Either path may be omitted to use the corresponding [`serde`]
379/// implementation.
380///
381/// ## Struct field attributes
382///
383/// - `#[tracked]` excludes the field from the struct's identity. When the producing query recreates
384/// the same entity with a new value for this field, Salsa updates the existing entity instead of
385/// creating a new one. Reads of the field are tracked separately, so changing it invalidates only
386/// queries that read that field. Use this for properties that may change while the conceptual
387/// entity remains the same.
388/// - `#[returns(MODE)]` selects how the getter returns the field. `ref` (the default) returns
389/// `&FieldTy`; `clone` returns an owned `FieldTy` using [`Clone`]; `copy` returns an owned
390/// `FieldTy` using [`Copy`]; and `deref` uses [`Deref`] to return
391/// `&<FieldTy as Deref>::Target`. `as_ref` and `as_deref` use [`salsa::SalsaAsRef`] and
392/// [`salsa::SalsaAsDeref`] to return borrowed forms such as `Option<&T>` and
393/// `Option<&T::Target>`. Every borrowed result is tied to the database borrow.
394/// - `#[get(IDENT)]` renames the generated getter.
395/// - `#[no_eq]` replaces the stored value and treats the field as changed whenever the struct is
396/// recreated, avoiding the [`PartialEq`] requirement. It is most useful together with
397/// `#[tracked]`: because the field does not contribute to identity, the struct can retain its
398/// identity when recreated, while readers of the field are always invalidated.
399/// - **Unsafe: `#[salsa_value(unsafe(prove(Predicate, ...)))]`** replaces the retention check with
400/// predicates that must hold for every database lifetime. The compiler verifies the predicates,
401/// but the caller must ensure they imply that Salsa can retain the field and expose it with a later
402/// database lifetime.
403/// - **Unsafe: `#[salsa_value(unsafe(prove_safe_to_retain_manually))]`** suppresses the retention
404/// check for this field without adding predicates. The caller must ensure Salsa can retain the
405/// field and expose it with a later database lifetime.
406///
407/// Other attributes, including documentation and lint attributes, are copied to the generated
408/// getter.
409///
410/// # Tracked functions
411///
412/// A tracked function memoizes its result and records the Salsa values read by its body. Salsa
413/// reuses the memoized result while those dependencies remain unchanged.
414///
415/// The first parameter must be an immutable `&dyn DatabaseTrait`; the remaining parameters form
416/// the query key. The function may declare one database lifetime but no type or const parameters.
417/// Every key parameter and the output must implement [`Send`] + [`Sync`]. With no key parameters,
418/// the function has one memoized query per database. A single key parameter must be a Salsa struct
419/// and uses its ID directly. With multiple key parameters, Salsa first interns their tuple to
420/// obtain an ID, adding an interning step to every call. Each key parameter must additionally
421/// implement [`Clone`] + [`Eq`] + [`Hash`]. Equality and hashing determine whether calls use the
422/// same memo, and Salsa always clones the stored tuple when materializing the function arguments.
423/// Interned key parameters and outputs whose types are not unconditionally `'static` must implement
424/// [`salsa::SalsaValue`].
425///
426/// See [tracked functions in the `salsa` crate documentation] for query identity, dependency
427/// tracking, result equality, and memo lifecycle.
428///
429/// ## Function options
430///
431/// - `returns(MODE)` selects how callers receive the memoized result. `ref` (the default) returns
432/// `&Output`; `clone` returns an owned `Output` using [`Clone`]; `copy` returns an owned `Output`
433/// using [`Copy`]; and `deref` uses [`Deref`] to return `&<Output as Deref>::Target`.
434/// `as_ref` and `as_deref` use [`salsa::SalsaAsRef`] and [`salsa::SalsaAsDeref`] to return
435/// borrowed forms such as `Option<&T>` and `Option<&T::Target>`. Every borrowed result is tied to
436/// the database borrow and remains stored in the query's memo.
437/// - `no_eq` treats every newly computed result as changed and removes the output's equality
438/// requirement. It cannot be combined with `cycle_fn`.
439/// - `specify` generates `FUNCTION::specify(db, key, value)`. It supports queries that have both a
440/// per-key incremental implementation and a batch implementation that computes many results at
441/// once. The function must take exactly one key argument, and it must be a tracked struct, not an
442/// input or interned struct. `specify` must be called during the same tracked query invocation
443/// that created the key. It cannot be combined with `lru`. See [specifying query results in the
444/// Salsa book] for an example.
445/// - `lru = INTEGER` bounds the number of memoized values retained by the function and sets the
446/// initial capacity used by `FUNCTION::set_lru_capacity`.
447/// - `cycle_initial = EXPR` enables fixed-point cycle recovery and computes the initial value. The
448/// expression is called as `(db, cycle_head_id, query_arguments...)`.
449/// - `cycle_fn = EXPR` combines successive fixed-point values. It must be accompanied by
450/// `cycle_initial` and is called as
451/// `(db, cycle, previous_value, new_value, query_arguments...)`. See [fixed-point cycle recovery
452/// in the Salsa book] for the convergence requirements and a complete example.
453/// - `cycle_result = EXPR` supplies an immediate fallback for cycles instead of fixed-point
454/// iteration. It is called with the same arguments as `cycle_initial` and cannot be combined
455/// with `cycle_initial` or `cycle_fn`.
456/// - `heap_size = PATH` records heap use for Salsa's unstable memory-usage reporting. `PATH` must
457/// accept a reference to the output and return its heap allocation size in bytes.
458/// - `persist` enables persistent caching when Salsa's `persistence` feature is enabled. The query
459/// inputs and output must implement [`serde::Serialize`] and [`serde::Deserialize`].
460/// - `self_ty = TYPE` prefixes the query's debug name with `TYPE`. The impl-block form supplies
461/// this automatically for methods and associated functions.
462///
463/// ## Legacy function adapter
464///
465/// - **Unsafe: `unsafe(non_salsa_values)` is strongly discouraged.** It adapts output or internally
466/// interned input types that do not implement [`salsa::SalsaValue`] by suppressing the generated
467/// checks. The caller becomes responsible for ensuring retained values remain valid across
468/// revisions. Prefer deriving or implementing [`salsa::SalsaValue`] for those types.
469///
470/// # Tracked impl blocks
471///
472/// Applying `#[salsa::tracked]` to an inherent or trait `impl` allows individual methods and
473/// associated functions in it to also use `#[salsa::tracked(...)]`. The outer attribute accepts no
474/// options; inner attributes accept all tracked-function options.
475///
476/// A tracked method takes `self` by value followed by the database parameter. A tracked associated
477/// function takes the database parameter first. Other methods and associated items are left
478/// unchanged.
479///
480/// # Examples
481///
482/// ```ignore
483/// #[salsa::input]
484/// struct File {
485/// #[returns(deref)]
486/// text: String,
487/// }
488///
489/// #[salsa::tracked(returns(copy))]
490/// fn word_count(db: &dyn salsa::Database, file: File) -> usize {
491/// file.text(db).split_whitespace().count()
492/// }
493///
494/// #[salsa::tracked]
495/// impl File {
496/// #[salsa::tracked(returns(copy))]
497/// fn line_count(self, db: &dyn salsa::Database) -> usize {
498/// self.text(db).lines().count()
499/// }
500/// }
501/// ```
502///
503/// [`Debug`]: std::fmt::Debug
504/// [`Deref`]: std::ops::Deref
505/// [`Eq`]: std::cmp::Eq
506/// [`Hash`]: std::hash::Hash
507/// [`salsa::SalsaAsDeref`]: https://docs.rs/salsa/latest/salsa/trait.SalsaAsDeref.html
508/// [`salsa::SalsaAsRef`]: https://docs.rs/salsa/latest/salsa/trait.SalsaAsRef.html
509/// [`salsa::SalsaValue`]: https://docs.rs/salsa/latest/salsa/trait.SalsaValue.html
510/// [`serde`]: https://docs.rs/serde/latest/serde/
511/// [`serde::Deserialize`]: https://docs.rs/serde/latest/serde/trait.Deserialize.html
512/// [`serde::Serialize`]: https://docs.rs/serde/latest/serde/trait.Serialize.html
513/// [fixed-point cycle recovery in the Salsa book]: https://salsa-rs.github.io/salsa/cycles.html#fixed-point-iteration
514/// [return mode]: https://docs.rs/salsa/latest/salsa/#return-modes
515/// [specifying query results in the Salsa book]: https://salsa-rs.github.io/salsa/overview.html#specify-the-result-of-tracked-functions-for-particular-structs
516/// [tracked functions in the `salsa` crate documentation]: https://docs.rs/salsa/latest/salsa/#tracked-functions-and-memoized-values
517/// [tracked structs in the `salsa` crate documentation]: https://docs.rs/salsa/latest/salsa/#tracked-structs
518#[proc_macro_attribute]
519pub fn tracked(args: TokenStream, input: TokenStream) -> TokenStream {
520 tracked::tracked(args, input)
521}
522
523/// Derives the unsafe [`salsa::SalsaValue`] trait for a struct or enum.
524///
525/// A field whose type is unconditionally `'static` is accepted directly; any other field must
526/// implement [`salsa::SalsaValue`].
527///
528/// The type may declare at most one lifetime parameter. Type and const parameters are supported;
529/// unions are not. Named fields, tuple fields, unit structs, and enum variants are supported.
530///
531/// # Field attributes
532///
533/// These field attributes are supported by `derive(SalsaValue)` and by Salsa's `tracked` and
534/// `interned` struct macros. On a derived type, conditional predicates become bounds on the
535/// generated `SalsaValue` implementation. On tracked and interned structs, they must hold for every
536/// database lifetime. The `input` macro supports neither form.
537///
538/// A field accepts at most one `#[salsa_value(...)]` attribute:
539///
540/// - **Unsafe: `#[salsa_value(unsafe(prove(Predicate, ...)))]`** suppresses the generated retention
541/// check for this field and adds the predicates to the generated `SalsaValue` implementation. The
542/// compiler verifies the predicates, but the author must ensure they imply that Salsa can replace
543/// the field's database lifetime with `'static` for storage and safely restore it later.
544/// - **Unsafe: `#[salsa_value(unsafe(prove_safe_to_retain_manually))]`** suppresses the generated
545/// retention check without adding predicates. The author must ensure the field is safe for every
546/// generic instantiation accepted by the enclosing type.
547///
548/// # Safety
549///
550/// Its field checks establish the structural requirements, but cannot inspect
551/// invariants maintained by unsafe code in the derived type's methods. By
552/// deriving `SalsaValue`, the author asserts that any such invariants remain
553/// valid when Salsa retains the value across revisions and rebinds its database
554/// lifetime.
555///
556/// # Examples
557///
558/// ```ignore
559/// #[derive(salsa::SalsaValue)]
560/// struct QueryValue<'db> {
561/// item: MyInterned<'db>,
562/// }
563/// ```
564///
565/// A conditional proof narrows the generated implementation when an unmodifiable field type does
566/// not implement `SalsaValue`:
567///
568/// ```ignore
569/// #[derive(salsa::SalsaValue)]
570/// struct QueryValue<T> {
571/// #[salsa_value(unsafe(prove(T: salsa::SalsaValue)))]
572/// value: ForeignContainer<T>,
573/// }
574/// ```
575///
576/// [`salsa::SalsaValue`]: https://docs.rs/salsa/latest/salsa/trait.SalsaValue.html
577#[proc_macro_derive(SalsaValue, attributes(salsa_value))]
578pub fn salsa_value(input: TokenStream) -> TokenStream {
579 let item = parse_macro_input!(input as syn::DeriveInput);
580 match salsa_value::salsa_value_derive(item) {
581 Ok(tokens) => tokens.into(),
582 Err(error) => error.into_compile_error().into(),
583 }
584}
585
586pub(crate) fn token_stream_with_error(mut tokens: TokenStream, error: syn::Error) -> TokenStream {
587 tokens.extend(TokenStream::from(error.into_compile_error()));
588 tokens
589}
590
591mod kw {
592 syn::custom_keyword!(prove);
593 syn::custom_keyword!(prove_safe_to_retain_manually);
594}