Skip to main content

salsa/
input.rs

1use std::any::{Any, TypeId};
2use std::fmt;
3use std::ops::IndexMut;
4
5pub mod input_field;
6pub mod setter;
7pub mod singleton;
8
9use input_field::FieldIngredientImpl;
10
11use crate::function::VerifyResult;
12use crate::hash::{FxHashSet, FxIndexSet};
13use crate::id::{AsId, FromId, FromIdWithDb};
14use crate::ingredient::Ingredient;
15use crate::input::singleton::{Singleton, SingletonChoice};
16use crate::key::DatabaseKeyIndex;
17use crate::plumbing::{self, Jar, ZalsaLocal};
18use crate::sync::Arc;
19use crate::table::memo::{MemoTable, MemoTableTypes};
20use crate::table::{Slot, Table};
21use crate::zalsa::{IngredientIndex, JarKind, Zalsa};
22use crate::zalsa_local::QueryEdge;
23use crate::{Durability, Id, Revision, Runtime};
24
25pub trait Configuration: Any {
26    const DEBUG_NAME: &'static str;
27    const FIELD_DEBUG_NAMES: &'static [&'static str];
28    const LOCATION: crate::ingredient::Location;
29
30    /// Whether this struct should be persisted with the database.
31    const PERSIST: bool;
32
33    /// The singleton state for this input if any.
34    type Singleton: SingletonChoice + Send + Sync;
35
36    /// The input struct (which wraps an `Id`)
37    type Struct: FromId + AsId + 'static + Send + Sync;
38
39    /// A (possibly empty) tuple of the fields for this struct.
40    type Fields: Send + Sync;
41
42    /// A array of [`Revision`], one per each of the value fields.
43    #[cfg(feature = "persistence")]
44    type Revisions: Send
45        + Sync
46        + fmt::Debug
47        + IndexMut<usize, Output = Revision>
48        + plumbing::serde::Serialize
49        + for<'de> plumbing::serde::Deserialize<'de>;
50
51    #[cfg(not(feature = "persistence"))]
52    type Revisions: Send + Sync + fmt::Debug + IndexMut<usize, Output = Revision>;
53
54    /// A array of [`Durability`], one per each of the value fields.
55    #[cfg(feature = "persistence")]
56    type Durabilities: Send
57        + Sync
58        + fmt::Debug
59        + IndexMut<usize, Output = Durability>
60        + plumbing::serde::Serialize
61        + for<'de> plumbing::serde::Deserialize<'de>;
62
63    #[cfg(not(feature = "persistence"))]
64    type Durabilities: Send + Sync + fmt::Debug + IndexMut<usize, Output = Durability>;
65
66    /// Returns the size of any heap allocations in the output value, in bytes.
67    fn heap_size(_value: &Self::Fields) -> Option<usize> {
68        None
69    }
70
71    /// Serialize the fields using `serde`.
72    ///
73    /// Panics if the value is not persistable, i.e. `Configuration::PERSIST` is `false`.
74    fn serialize<S>(value: &Self::Fields, serializer: S) -> Result<S::Ok, S::Error>
75    where
76        S: plumbing::serde::Serializer;
77
78    /// Deserialize the fields using `serde`.
79    ///
80    /// Panics if the value is not persistable, i.e. `Configuration::PERSIST` is `false`.
81    fn deserialize<'de, D>(deserializer: D) -> Result<Self::Fields, D::Error>
82    where
83        D: plumbing::serde::Deserializer<'de>;
84}
85
86pub struct JarImpl<C: Configuration> {
87    _phantom: std::marker::PhantomData<C>,
88}
89
90impl<C: Configuration> Default for JarImpl<C> {
91    fn default() -> Self {
92        Self {
93            _phantom: Default::default(),
94        }
95    }
96}
97
98impl<C: Configuration> Jar for JarImpl<C> {
99    fn create_ingredients(
100        _zalsa: &mut Zalsa,
101        struct_index: crate::zalsa::IngredientIndex,
102    ) -> Vec<Box<dyn Ingredient>> {
103        let struct_ingredient: IngredientImpl<C> = IngredientImpl::new(struct_index);
104
105        std::iter::once(Box::new(struct_ingredient) as _)
106            .chain((0..C::FIELD_DEBUG_NAMES.len()).map(|field_index| {
107                Box::new(<FieldIngredientImpl<C>>::new(struct_index, field_index)) as _
108            }))
109            .collect()
110    }
111
112    fn id_struct_type_id() -> TypeId {
113        TypeId::of::<C::Struct>()
114    }
115}
116
117pub struct IngredientImpl<C: Configuration> {
118    ingredient_index: IngredientIndex,
119    singleton: C::Singleton,
120    memo_table_types: Arc<MemoTableTypes>,
121    _phantom: std::marker::PhantomData<C::Struct>,
122}
123
124impl<C: Configuration> IngredientImpl<C> {
125    pub fn new(index: IngredientIndex) -> Self {
126        Self {
127            ingredient_index: index,
128            singleton: Default::default(),
129            memo_table_types: Arc::new(MemoTableTypes::default()),
130            _phantom: std::marker::PhantomData,
131        }
132    }
133
134    fn data(zalsa: &Zalsa, id: Id) -> &Value<C> {
135        zalsa.table().get(id)
136    }
137
138    fn data_raw(table: &Table, id: Id) -> *mut Value<C> {
139        table.get_raw(id)
140    }
141
142    pub fn database_key_index(&self, id: Id) -> DatabaseKeyIndex {
143        DatabaseKeyIndex::new(self.ingredient_index, id)
144    }
145
146    pub fn new_input(
147        &self,
148        zalsa: &Zalsa,
149        zalsa_local: &ZalsaLocal,
150        fields: C::Fields,
151        revisions: C::Revisions,
152        durabilities: C::Durabilities,
153    ) -> C::Struct {
154        let id = self.singleton.with_scope(|| {
155            zalsa_local
156                .allocate(zalsa, self.ingredient_index, |_| Value::<C> {
157                    fields,
158                    revisions,
159                    durabilities,
160                    // SAFETY: We only ever access the memos of a value that we allocated through
161                    // our `MemoTableTypes`.
162                    memos: unsafe { MemoTable::new(self.memo_table_types()) },
163                })
164                .0
165        });
166
167        FromIdWithDb::from_id(id, zalsa)
168    }
169
170    /// Change the value of the field `field_index` to a new value.
171    ///
172    /// # Parameters
173    ///
174    /// * `runtime`, the salsa runtiem
175    /// * `id`, id of the input struct
176    /// * `field_index`, index of the field that will be changed
177    /// * `durability`, durability of the new value. If omitted, uses the durability of the previous value.
178    /// * `setter`, function that modifies the fields tuple; should only modify the element for `field_index`
179    pub fn set_field<R>(
180        &mut self,
181        runtime: &mut Runtime,
182        id: C::Struct,
183        field_index: usize,
184        durability: Option<Durability>,
185        setter: impl FnOnce(&mut C::Fields) -> R,
186    ) -> R {
187        let id: Id = id.as_id();
188
189        let data_raw = Self::data_raw(runtime.table(), id);
190
191        // SAFETY: We hold `&mut` on the runtime so no `&`-references can be active.
192        // Also, we don't access any other data from the table while `r` is active.
193        let data = unsafe { &mut *data_raw };
194
195        data.revisions[field_index] = runtime.current_revision();
196
197        let field_durability = &mut data.durabilities[field_index];
198        if *field_durability != Durability::MIN {
199            runtime.report_tracked_write(*field_durability);
200        }
201        *field_durability = durability.unwrap_or(*field_durability);
202
203        setter(&mut data.fields)
204    }
205
206    /// Get the singleton input previously created (if any).
207    #[doc(hidden)]
208    pub fn get_singleton_input(&self, zalsa: &Zalsa) -> Option<C::Struct>
209    where
210        C: Configuration<Singleton = Singleton>,
211    {
212        self.singleton
213            .index()
214            .map(|id| FromIdWithDb::from_id(id, zalsa))
215    }
216
217    /// Access field of an input.
218    /// Note that this function returns the entire tuple of value fields.
219    /// The caller is responsible for selecting the appropriate element.
220    pub fn field<'db>(
221        &'db self,
222        zalsa: &'db Zalsa,
223        zalsa_local: &'db ZalsaLocal,
224        id: C::Struct,
225        field_index: usize,
226    ) -> &'db C::Fields {
227        let field_ingredient_index = self.ingredient_index.successor(field_index);
228        let id = id.as_id();
229        let value = Self::data(zalsa, id);
230        let durability = value.durabilities[field_index];
231        let revision = value.revisions[field_index];
232        zalsa_local.report_tracked_read_simple(
233            DatabaseKeyIndex::new(field_ingredient_index, id),
234            durability,
235            revision,
236        );
237        &value.fields
238    }
239
240    /// Returns all data corresponding to the input struct.
241    pub fn entries<'db>(&'db self, zalsa: &'db Zalsa) -> impl Iterator<Item = StructEntry<'db, C>> {
242        zalsa
243            .table()
244            .slots_of::<Value<C>>()
245            .map(|(id, value)| StructEntry {
246                value,
247                key: self.database_key_index(id),
248            })
249    }
250
251    /// Peek at the field values without recording any read dependency.
252    /// Used for debug printouts.
253    pub fn leak_fields<'db>(&'db self, zalsa: &'db Zalsa, id: C::Struct) -> &'db C::Fields {
254        let id = id.as_id();
255        let value = Self::data(zalsa, id);
256        &value.fields
257    }
258}
259
260/// An input struct entry.
261pub struct StructEntry<'db, C>
262where
263    C: Configuration,
264{
265    value: &'db Value<C>,
266    key: DatabaseKeyIndex,
267}
268
269impl<'db, C> StructEntry<'db, C>
270where
271    C: Configuration,
272{
273    /// Returns the `DatabaseKeyIndex` for this entry.
274    pub fn key(&self) -> DatabaseKeyIndex {
275        self.key
276    }
277
278    /// Returns the input struct.
279    pub fn as_struct(&self) -> C::Struct {
280        FromId::from_id(self.key.key_index())
281    }
282
283    #[cfg(feature = "salsa_unstable")]
284    pub fn value(&self) -> &'db Value<C> {
285        self.value
286    }
287}
288
289impl<C: Configuration> Ingredient for IngredientImpl<C> {
290    fn location(&self) -> &'static crate::ingredient::Location {
291        &C::LOCATION
292    }
293
294    fn ingredient_index(&self) -> IngredientIndex {
295        self.ingredient_index
296    }
297
298    unsafe fn maybe_changed_after(
299        &self,
300        _zalsa: &crate::zalsa::Zalsa,
301        _db: crate::database::RawDatabase<'_>,
302        _input: Id,
303        _revision: Revision,
304    ) -> VerifyResult {
305        // Input ingredients are just a counter, they store no data, they are immortal.
306        // Their *fields* are stored in function ingredients elsewhere.
307        panic!("nothing should ever depend on an input struct directly")
308    }
309
310    fn collect_minimum_serialized_edges(
311        &self,
312        _zalsa: &Zalsa,
313        _edge: QueryEdge,
314        _serialized_edges: &mut FxIndexSet<QueryEdge>,
315        _visited_edges: &mut FxHashSet<QueryEdge>,
316    ) {
317        panic!("nothing should ever depend on an input struct directly")
318    }
319
320    fn flatten_cycle_head_dependencies(
321        &self,
322        _zalsa: &Zalsa,
323        _id: Id,
324        _flattened_input_outputs: &mut FxIndexSet<QueryEdge>,
325        _seen: &mut FxHashSet<DatabaseKeyIndex>,
326    ) {
327        panic!("nothing should ever depend on an input struct directly")
328    }
329
330    fn debug_name(&self) -> &'static str {
331        C::DEBUG_NAME
332    }
333
334    fn jar_kind(&self) -> JarKind {
335        JarKind::Struct
336    }
337
338    fn memo_table_types(&self) -> &Arc<MemoTableTypes> {
339        &self.memo_table_types
340    }
341
342    fn memo_table_types_mut(&mut self) -> &mut Arc<MemoTableTypes> {
343        &mut self.memo_table_types
344    }
345
346    /// Returns memory usage information about any inputs.
347    #[cfg(feature = "salsa_unstable")]
348    fn memory_usage(&self, db: &dyn crate::Database) -> Option<Vec<crate::database::SlotInfo>> {
349        let memory_usage = self
350            .entries(db.zalsa())
351            // SAFETY: The memo table belongs to a value that we allocated, so it
352            // has the correct type.
353            .map(|entry| unsafe { entry.value.memory_usage(&self.memo_table_types) })
354            .collect();
355
356        Some(memory_usage)
357    }
358
359    fn is_persistable(&self) -> bool {
360        C::PERSIST
361    }
362
363    fn should_serialize(&self, zalsa: &Zalsa) -> bool {
364        C::PERSIST && self.entries(zalsa).next().is_some()
365    }
366
367    #[cfg(feature = "persistence")]
368    unsafe fn serialize<'db>(
369        &'db self,
370        zalsa: &'db Zalsa,
371        f: &mut dyn FnMut(&dyn erased_serde::Serialize),
372    ) {
373        f(&persistence::SerializeIngredient {
374            zalsa,
375            _ingredient: self,
376        })
377    }
378
379    #[cfg(feature = "persistence")]
380    fn deserialize(
381        &mut self,
382        zalsa: &mut Zalsa,
383        deserializer: &mut dyn erased_serde::Deserializer,
384    ) -> Result<(), erased_serde::Error> {
385        let deserialize = persistence::DeserializeIngredient {
386            zalsa,
387            ingredient: self,
388        };
389
390        serde::de::DeserializeSeed::deserialize(deserialize, deserializer)
391    }
392}
393
394impl<C: Configuration> std::fmt::Debug for IngredientImpl<C> {
395    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
396        f.debug_struct(std::any::type_name::<Self>())
397            .field("index", &self.ingredient_index)
398            .finish()
399    }
400}
401
402#[derive(Debug)]
403pub struct Value<C>
404where
405    C: Configuration,
406{
407    /// Fields of this input struct.
408    ///
409    /// They can change across revisions, but they do not change within
410    /// a particular revision.
411    fields: C::Fields,
412
413    /// Revisions of the fields.
414    revisions: C::Revisions,
415
416    /// Durabilities of the fields.
417    durabilities: C::Durabilities,
418
419    /// Memos
420    memos: MemoTable,
421}
422
423impl<C> Value<C>
424where
425    C: Configuration,
426{
427    /// Fields of this tracked struct.
428    ///
429    /// They can change across revisions, but they do not change within
430    /// a particular revision.
431    #[cfg(feature = "salsa_unstable")]
432    pub fn fields(&self) -> &C::Fields {
433        &self.fields
434    }
435
436    /// Returns memory usage information about the input.
437    ///
438    /// # Safety
439    ///
440    /// The `MemoTable` must belong to a `Value` of the correct type.
441    #[cfg(feature = "salsa_unstable")]
442    unsafe fn memory_usage(&self, memo_table_types: &MemoTableTypes) -> crate::database::SlotInfo {
443        let heap_size = C::heap_size(&self.fields);
444        // SAFETY: The caller guarantees this is the correct types table.
445        let memos = unsafe { memo_table_types.attach_memos(&self.memos) };
446
447        crate::database::SlotInfo {
448            debug_name: C::DEBUG_NAME,
449            size_of_metadata: std::mem::size_of::<Self>() - std::mem::size_of::<C::Fields>(),
450            size_of_fields: std::mem::size_of::<C::Fields>(),
451            heap_size_of_fields: heap_size,
452            memos: memos.memory_usage(),
453        }
454    }
455}
456
457pub trait HasBuilder {
458    type Builder;
459}
460
461// SAFETY: `Value<C>` is our private type branded over the unique configuration `C`.
462unsafe impl<C> Slot for Value<C>
463where
464    C: Configuration,
465{
466    #[inline(always)]
467    unsafe fn memos(
468        this: *const Self,
469        _current_revision: Revision,
470    ) -> *const crate::table::memo::MemoTable {
471        // SAFETY: Caller obligation demands this pointer to be valid.
472        unsafe { &raw const (*this).memos }
473    }
474
475    #[inline(always)]
476    fn memos_mut(&mut self) -> &mut crate::table::memo::MemoTable {
477        &mut self.memos
478    }
479}
480
481#[cfg(feature = "persistence")]
482mod persistence {
483    use std::fmt;
484
485    use serde::ser::{SerializeMap, SerializeStruct};
486    use serde::{Deserialize, de};
487
488    use super::{Configuration, IngredientImpl, Value};
489    use crate::Id;
490    use crate::input::singleton::SingletonChoice;
491    use crate::plumbing::Ingredient;
492    use crate::table::memo::MemoTable;
493    use crate::zalsa::Zalsa;
494
495    pub struct SerializeIngredient<'db, C>
496    where
497        C: Configuration,
498    {
499        pub zalsa: &'db Zalsa,
500        pub _ingredient: &'db IngredientImpl<C>,
501    }
502
503    impl<C> serde::Serialize for SerializeIngredient<'_, C>
504    where
505        C: Configuration,
506    {
507        fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
508        where
509            S: serde::Serializer,
510        {
511            let Self { zalsa, .. } = self;
512
513            let count = zalsa.table().slots_of::<Value<C>>().count();
514            let mut map = serializer.serialize_map(Some(count))?;
515
516            for (id, value) in zalsa.table().slots_of::<Value<C>>() {
517                map.serialize_entry(&id.as_bits(), value)?;
518            }
519
520            map.end()
521        }
522    }
523
524    impl<C> serde::Serialize for Value<C>
525    where
526        C: Configuration,
527    {
528        fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
529        where
530            S: serde::Serializer,
531        {
532            let mut value = serializer.serialize_struct("Value", 3)?;
533
534            let Value {
535                fields,
536                revisions,
537                durabilities,
538                memos: _,
539            } = self;
540
541            value.serialize_field("durabilities", &durabilities)?;
542            value.serialize_field("revisions", &revisions)?;
543            value.serialize_field("fields", &SerializeFields::<C>(fields))?;
544
545            value.end()
546        }
547    }
548
549    struct SerializeFields<'db, C: Configuration>(&'db C::Fields);
550
551    impl<C> serde::Serialize for SerializeFields<'_, C>
552    where
553        C: Configuration,
554    {
555        fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
556        where
557            S: serde::Serializer,
558        {
559            C::serialize(self.0, serializer)
560        }
561    }
562
563    pub struct DeserializeIngredient<'db, C>
564    where
565        C: Configuration,
566    {
567        pub zalsa: &'db mut Zalsa,
568        pub ingredient: &'db mut IngredientImpl<C>,
569    }
570
571    impl<'de, C> de::DeserializeSeed<'de> for DeserializeIngredient<'_, C>
572    where
573        C: Configuration,
574    {
575        type Value = ();
576
577        fn deserialize<D>(self, deserializer: D) -> Result<Self::Value, D::Error>
578        where
579            D: serde::Deserializer<'de>,
580        {
581            deserializer.deserialize_map(self)
582        }
583    }
584
585    impl<'de, C> de::Visitor<'de> for DeserializeIngredient<'_, C>
586    where
587        C: Configuration,
588    {
589        type Value = ();
590
591        fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
592            formatter.write_str("a map")
593        }
594
595        fn visit_map<M>(self, mut access: M) -> Result<Self::Value, M::Error>
596        where
597            M: de::MapAccess<'de>,
598        {
599            let DeserializeIngredient { zalsa, ingredient } = self;
600
601            while let Some((id, value)) = access.next_entry::<u64, DeserializeValue<C>>()? {
602                let id = Id::from_bits(id);
603                let (page_idx, _) = crate::table::split_id(id);
604
605                let value = Value::<C> {
606                    fields: value.fields.0,
607                    revisions: value.revisions,
608                    durabilities: value.durabilities,
609                    // SAFETY: We only ever access the memos of a value that we allocated through
610                    // our `MemoTableTypes`.
611                    memos: unsafe { MemoTable::new(ingredient.memo_table_types()) },
612                };
613
614                // Force initialize the relevant page.
615                zalsa.table_mut().force_page::<Value<C>>(
616                    page_idx,
617                    ingredient.ingredient_index(),
618                    ingredient.memo_table_types(),
619                );
620
621                // Initialize the slot.
622                //
623                // SAFETY: We have a mutable reference to the database.
624                let allocated_id = ingredient.singleton.with_scope(|| unsafe {
625                    zalsa
626                        .table()
627                        .page(page_idx)
628                        .allocate(page_idx, |_| value)
629                        .unwrap_or_else(|_| panic!("serialized an invalid `Id`: {id:?}"))
630                        .0
631                });
632
633                assert_eq!(
634                    allocated_id, id,
635                    "values are serialized in allocation order"
636                );
637            }
638
639            Ok(())
640        }
641    }
642
643    #[derive(Deserialize)]
644    #[serde(rename = "Value")]
645    pub struct DeserializeValue<C: Configuration> {
646        durabilities: C::Durabilities,
647        revisions: C::Revisions,
648        #[serde(bound = "C: Configuration")]
649        fields: DeserializeFields<C>,
650    }
651
652    struct DeserializeFields<C: Configuration>(C::Fields);
653
654    impl<'de, C> serde::Deserialize<'de> for DeserializeFields<C>
655    where
656        C: Configuration,
657    {
658        fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
659        where
660            D: serde::Deserializer<'de>,
661        {
662            C::deserialize(deserializer)
663                .map(DeserializeFields)
664                .map_err(de::Error::custom)
665        }
666    }
667}