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