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: 'static + 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    ///
180    /// # Panics
181    ///
182    /// Panics if the field's current durability is [`Durability::NEVER_CHANGE`].
183    pub fn set_field<R>(
184        &mut self,
185        runtime: &mut Runtime,
186        id: C::Struct,
187        field_index: usize,
188        durability: Option<Durability>,
189        setter: impl FnOnce(&mut C::Fields) -> R,
190    ) -> R {
191        let id: Id = id.as_id();
192
193        let data_raw = Self::data_raw(runtime.table(), id);
194
195        // SAFETY: We hold `&mut` on the runtime so no `&`-references can be active.
196        // Also, we don't access any other data from the table while `r` is active.
197        let data = unsafe { &mut *data_raw };
198
199        assert_ne!(
200            data.durabilities[field_index],
201            Durability::NEVER_CHANGE,
202            "never-changing inputs cannot be mutated"
203        );
204
205        data.revisions[field_index] = runtime.current_revision();
206
207        let field_durability = &mut data.durabilities[field_index];
208        if *field_durability != Durability::MIN {
209            runtime.report_tracked_write(*field_durability);
210        }
211        *field_durability = durability.unwrap_or(*field_durability);
212
213        setter(&mut data.fields)
214    }
215
216    /// Get the singleton input previously created (if any).
217    #[doc(hidden)]
218    pub fn get_singleton_input(&self, zalsa: &Zalsa) -> Option<C::Struct>
219    where
220        C: Configuration<Singleton = Singleton>,
221    {
222        self.singleton
223            .index()
224            .map(|id| FromIdWithDb::from_id(id, zalsa))
225    }
226
227    /// Access field of an input.
228    /// Note that this function returns the entire tuple of value fields.
229    /// The caller is responsible for selecting the appropriate element.
230    pub fn field<'db>(
231        &'db self,
232        zalsa: &'db Zalsa,
233        zalsa_local: &'db ZalsaLocal,
234        id: C::Struct,
235        field_index: usize,
236    ) -> &'db C::Fields {
237        let field_ingredient_index = self.ingredient_index.successor(field_index);
238        let id = id.as_id();
239        let value = Self::data(zalsa, id);
240        let durability = value.durabilities[field_index];
241        let revision = value.revisions[field_index];
242        zalsa_local.report_tracked_read_simple(
243            DatabaseKeyIndex::new(field_ingredient_index, id),
244            durability,
245            revision,
246        );
247        &value.fields
248    }
249
250    /// Returns all data corresponding to the input struct.
251    pub fn entries<'db>(&'db self, zalsa: &'db Zalsa) -> impl Iterator<Item = StructEntry<'db, C>> {
252        zalsa
253            .table()
254            .slots_of::<Value<C>>()
255            .map(|(id, value)| StructEntry {
256                value,
257                key: self.database_key_index(id),
258            })
259    }
260
261    /// Peek at the field values without recording any read dependency.
262    /// Used for debug printouts.
263    pub fn leak_fields<'db>(&'db self, zalsa: &'db Zalsa, id: C::Struct) -> &'db C::Fields {
264        let id = id.as_id();
265        let value = Self::data(zalsa, id);
266        &value.fields
267    }
268}
269
270/// An input struct entry.
271pub struct StructEntry<'db, C>
272where
273    C: Configuration,
274{
275    #[cfg_attr(not(feature = "salsa_unstable"), allow(dead_code))]
276    value: &'db Value<C>,
277    key: DatabaseKeyIndex,
278}
279
280impl<'db, C> StructEntry<'db, C>
281where
282    C: Configuration,
283{
284    /// Returns the `DatabaseKeyIndex` for this entry.
285    pub fn key(&self) -> DatabaseKeyIndex {
286        self.key
287    }
288
289    /// Returns the input struct.
290    pub fn as_struct(&self) -> C::Struct {
291        FromId::from_id(self.key.key_index())
292    }
293
294    #[cfg(feature = "salsa_unstable")]
295    pub fn value(&self) -> &'db Value<C> {
296        self.value
297    }
298}
299
300impl<C: Configuration> Ingredient for IngredientImpl<C> {
301    fn location(&self) -> &'static crate::ingredient::Location {
302        &C::LOCATION
303    }
304
305    fn ingredient_index(&self) -> IngredientIndex {
306        self.ingredient_index
307    }
308
309    unsafe fn maybe_changed_after(
310        &self,
311        _zalsa: &crate::zalsa::Zalsa,
312        _db: crate::database::RawDatabase<'_>,
313        _input: Id,
314        _revision: Revision,
315    ) -> VerifyResult {
316        // Input ingredients are just a counter, they store no data, they are immortal.
317        // Their *fields* are stored in function ingredients elsewhere.
318        panic!("nothing should ever depend on an input struct directly")
319    }
320
321    fn collect_minimum_serialized_edges(
322        &self,
323        _zalsa: &Zalsa,
324        _edge: QueryEdge,
325        _serialized_edges: &mut FxIndexSet<QueryEdge>,
326        _visited_edges: &mut FxHashSet<QueryEdge>,
327    ) {
328        panic!("nothing should ever depend on an input struct directly")
329    }
330
331    fn flatten_cycle_head_dependencies(
332        &self,
333        _zalsa: &Zalsa,
334        _id: Id,
335        _flattened_input_outputs: &mut FxIndexSet<QueryEdge>,
336        _seen: &mut FxHashSet<DatabaseKeyIndex>,
337    ) {
338        panic!("nothing should ever depend on an input struct directly")
339    }
340
341    fn debug_name(&self) -> &'static str {
342        C::DEBUG_NAME
343    }
344
345    fn jar_kind(&self) -> JarKind {
346        JarKind::Struct
347    }
348
349    fn memo_table_types(&self) -> &Arc<MemoTableTypes> {
350        &self.memo_table_types
351    }
352
353    fn memo_table_types_mut(&mut self) -> &mut Arc<MemoTableTypes> {
354        &mut self.memo_table_types
355    }
356
357    /// Returns memory usage information about any inputs.
358    #[cfg(feature = "salsa_unstable")]
359    fn memory_usage(&self, db: &dyn crate::Database) -> Option<Vec<crate::database::SlotInfo>> {
360        let memory_usage = self
361            .entries(db.zalsa())
362            // SAFETY: The memo table belongs to a value that we allocated, so it
363            // has the correct type.
364            .map(|entry| unsafe { entry.value.memory_usage(&self.memo_table_types) })
365            .collect();
366
367        Some(memory_usage)
368    }
369
370    fn is_persistable(&self) -> bool {
371        C::PERSIST
372    }
373
374    fn should_serialize(&self, zalsa: &Zalsa) -> bool {
375        C::PERSIST && self.entries(zalsa).next().is_some()
376    }
377
378    #[cfg(feature = "persistence")]
379    unsafe fn serialize<'db>(
380        &'db self,
381        zalsa: &'db Zalsa,
382        f: &mut dyn FnMut(&dyn erased_serde::Serialize),
383    ) {
384        f(&persistence::SerializeIngredient {
385            zalsa,
386            _ingredient: self,
387        })
388    }
389
390    #[cfg(feature = "persistence")]
391    fn deserialize(
392        &mut self,
393        zalsa: &mut Zalsa,
394        deserializer: &mut dyn erased_serde::Deserializer,
395    ) -> Result<(), erased_serde::Error> {
396        let deserialize = persistence::DeserializeIngredient {
397            zalsa,
398            ingredient: self,
399        };
400
401        serde::de::DeserializeSeed::deserialize(deserialize, deserializer)
402    }
403}
404
405impl<C: Configuration> std::fmt::Debug for IngredientImpl<C> {
406    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
407        f.debug_struct(std::any::type_name::<Self>())
408            .field("index", &self.ingredient_index)
409            .finish()
410    }
411}
412
413#[derive(Debug)]
414pub struct Value<C>
415where
416    C: Configuration,
417{
418    /// Fields of this input struct.
419    ///
420    /// They can change across revisions, but they do not change within
421    /// a particular revision.
422    fields: C::Fields,
423
424    /// Revisions of the fields.
425    revisions: C::Revisions,
426
427    /// Durabilities of the fields.
428    durabilities: C::Durabilities,
429
430    /// Memos
431    memos: MemoTable,
432}
433
434impl<C> Value<C>
435where
436    C: Configuration,
437{
438    /// Fields of this tracked struct.
439    ///
440    /// They can change across revisions, but they do not change within
441    /// a particular revision.
442    #[cfg(feature = "salsa_unstable")]
443    pub fn fields(&self) -> &C::Fields {
444        &self.fields
445    }
446
447    /// Returns memory usage information about the input.
448    ///
449    /// # Safety
450    ///
451    /// The `MemoTable` must belong to a `Value` of the correct type.
452    #[cfg(feature = "salsa_unstable")]
453    unsafe fn memory_usage(&self, memo_table_types: &MemoTableTypes) -> crate::database::SlotInfo {
454        let heap_size = C::heap_size(&self.fields);
455        // SAFETY: The caller guarantees this is the correct types table.
456        let memos = unsafe { memo_table_types.attach_memos(&self.memos) };
457
458        crate::database::SlotInfo {
459            debug_name: C::DEBUG_NAME,
460            size_of_metadata: std::mem::size_of::<Self>() - std::mem::size_of::<C::Fields>(),
461            size_of_fields: std::mem::size_of::<C::Fields>(),
462            heap_size_of_fields: heap_size,
463            memos: memos.memory_usage(),
464        }
465    }
466}
467
468pub trait HasBuilder {
469    type Builder;
470}
471
472// SAFETY: `Value<C>` is our private type branded over the unique configuration `C`.
473unsafe impl<C> Slot for Value<C>
474where
475    C: Configuration,
476{
477    #[inline(always)]
478    unsafe fn memos(
479        this: *const Self,
480        _current_revision: Revision,
481    ) -> *const crate::table::memo::MemoTable {
482        // SAFETY: Caller obligation demands this pointer to be valid.
483        unsafe { &raw const (*this).memos }
484    }
485
486    #[inline(always)]
487    fn memos_mut(&mut self) -> &mut crate::table::memo::MemoTable {
488        &mut self.memos
489    }
490}
491
492#[cfg(feature = "persistence")]
493mod persistence {
494    use std::fmt;
495
496    use serde::ser::{SerializeMap, SerializeStruct};
497    use serde::{Deserialize, de};
498
499    use super::{Configuration, IngredientImpl, Value};
500    use crate::Id;
501    use crate::input::singleton::SingletonChoice;
502    use crate::plumbing::Ingredient;
503    use crate::table::memo::MemoTable;
504    use crate::zalsa::Zalsa;
505
506    pub struct SerializeIngredient<'db, C>
507    where
508        C: Configuration,
509    {
510        pub zalsa: &'db Zalsa,
511        pub _ingredient: &'db IngredientImpl<C>,
512    }
513
514    impl<C> serde::Serialize for SerializeIngredient<'_, C>
515    where
516        C: Configuration,
517    {
518        fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
519        where
520            S: serde::Serializer,
521        {
522            let Self { zalsa, .. } = self;
523
524            let count = zalsa.table().slots_of::<Value<C>>().count();
525            let mut map = serializer.serialize_map(Some(count))?;
526
527            for (id, value) in zalsa.table().slots_of::<Value<C>>() {
528                map.serialize_entry(&id.as_bits(), value)?;
529            }
530
531            map.end()
532        }
533    }
534
535    impl<C> serde::Serialize for Value<C>
536    where
537        C: Configuration,
538    {
539        fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
540        where
541            S: serde::Serializer,
542        {
543            let mut value = serializer.serialize_struct("Value", 3)?;
544
545            let Value {
546                fields,
547                revisions,
548                durabilities,
549                memos: _,
550            } = self;
551
552            value.serialize_field("durabilities", &durabilities)?;
553            value.serialize_field("revisions", &revisions)?;
554            value.serialize_field("fields", &SerializeFields::<C>(fields))?;
555
556            value.end()
557        }
558    }
559
560    struct SerializeFields<'db, C: Configuration>(&'db C::Fields);
561
562    impl<C> serde::Serialize for SerializeFields<'_, C>
563    where
564        C: Configuration,
565    {
566        fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
567        where
568            S: serde::Serializer,
569        {
570            C::serialize(self.0, serializer)
571        }
572    }
573
574    pub struct DeserializeIngredient<'db, C>
575    where
576        C: Configuration,
577    {
578        pub zalsa: &'db mut Zalsa,
579        pub ingredient: &'db mut IngredientImpl<C>,
580    }
581
582    impl<'de, C> de::DeserializeSeed<'de> for DeserializeIngredient<'_, C>
583    where
584        C: Configuration,
585    {
586        type Value = ();
587
588        fn deserialize<D>(self, deserializer: D) -> Result<Self::Value, D::Error>
589        where
590            D: serde::Deserializer<'de>,
591        {
592            deserializer.deserialize_map(self)
593        }
594    }
595
596    impl<'de, C> de::Visitor<'de> for DeserializeIngredient<'_, C>
597    where
598        C: Configuration,
599    {
600        type Value = ();
601
602        fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
603            formatter.write_str("a map")
604        }
605
606        fn visit_map<M>(self, mut access: M) -> Result<Self::Value, M::Error>
607        where
608            M: de::MapAccess<'de>,
609        {
610            let DeserializeIngredient { zalsa, ingredient } = self;
611
612            while let Some((id, value)) = access.next_entry::<u64, DeserializeValue<C>>()? {
613                let id = Id::from_bits(id);
614                let (page_idx, _) = crate::table::split_id(id);
615
616                let value = Value::<C> {
617                    fields: value.fields.0,
618                    revisions: value.revisions,
619                    durabilities: value.durabilities,
620                    // SAFETY: We only ever access the memos of a value that we allocated through
621                    // our `MemoTableTypes`.
622                    memos: unsafe { MemoTable::new(ingredient.memo_table_types()) },
623                };
624
625                // Force initialize the relevant page.
626                zalsa.table_mut().force_page::<Value<C>>(
627                    page_idx,
628                    ingredient.ingredient_index(),
629                    ingredient.memo_table_types(),
630                );
631
632                // Initialize the slot.
633                //
634                // SAFETY: We have a mutable reference to the database.
635                let allocated_id = ingredient.singleton.with_scope(|| unsafe {
636                    zalsa
637                        .table()
638                        .page(page_idx)
639                        .allocate(page_idx, |_| value)
640                        .unwrap_or_else(|_| panic!("serialized an invalid `Id`: {id:?}"))
641                        .0
642                });
643
644                assert_eq!(
645                    allocated_id, id,
646                    "values are serialized in allocation order"
647                );
648            }
649
650            Ok(())
651        }
652    }
653
654    #[derive(Deserialize)]
655    #[serde(rename = "Value")]
656    pub struct DeserializeValue<C: Configuration> {
657        durabilities: C::Durabilities,
658        revisions: C::Revisions,
659        #[serde(bound = "C: Configuration")]
660        fields: DeserializeFields<C>,
661    }
662
663    struct DeserializeFields<C: Configuration>(C::Fields);
664
665    impl<'de, C> serde::Deserialize<'de> for DeserializeFields<C>
666    where
667        C: Configuration,
668    {
669        fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
670        where
671            D: serde::Deserializer<'de>,
672        {
673            C::deserialize(deserializer)
674                .map(DeserializeFields)
675                .map_err(de::Error::custom)
676        }
677    }
678}