1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
use std::{
fmt,
sync::atomic::{AtomicU32, Ordering},
};
use crate::{
cycle::CycleRecoveryStrategy,
ingredient::{fmt_index, Ingredient, IngredientRequiresReset},
key::{DatabaseKeyIndex, DependencyIndex},
runtime::{local_state::QueryOrigin, Runtime},
AsId, IngredientIndex, Revision,
};
pub trait InputId: AsId {}
impl<T: AsId> InputId for T {}
pub struct InputIngredient<Id>
where
Id: InputId,
{
ingredient_index: IngredientIndex,
counter: AtomicU32,
debug_name: &'static str,
_phantom: std::marker::PhantomData<Id>,
}
impl<Id> InputIngredient<Id>
where
Id: InputId,
{
pub fn new(index: IngredientIndex, debug_name: &'static str) -> Self {
Self {
ingredient_index: index,
counter: Default::default(),
debug_name,
_phantom: std::marker::PhantomData,
}
}
pub fn database_key_index(&self, id: Id) -> DatabaseKeyIndex {
DatabaseKeyIndex {
ingredient_index: self.ingredient_index,
key_index: id.as_id(),
}
}
pub fn new_input(&self, _runtime: &Runtime) -> Id {
let next_id = self.counter.fetch_add(1, Ordering::Relaxed);
Id::from_id(crate::Id::from_u32(next_id))
}
pub fn new_singleton_input(&self, _runtime: &Runtime) -> Id {
if self.counter.load(Ordering::Relaxed) >= 1 {
panic!("singleton struct may not be duplicated");
}
self.counter.store(1, Ordering::Relaxed);
Id::from_id(crate::Id::from_u32(0))
}
pub fn get_singleton_input(&self, _runtime: &Runtime) -> Option<Id> {
(self.counter.load(Ordering::Relaxed) > 0).then(|| Id::from_id(crate::Id::from_u32(0)))
}
}
impl<DB: ?Sized, Id> Ingredient<DB> for InputIngredient<Id>
where
Id: InputId,
{
fn maybe_changed_after(&self, _db: &DB, _input: DependencyIndex, _revision: Revision) -> bool {
false
}
fn cycle_recovery_strategy(&self) -> CycleRecoveryStrategy {
CycleRecoveryStrategy::Panic
}
fn origin(&self, _key_index: crate::Id) -> Option<QueryOrigin> {
None
}
fn mark_validated_output(
&self,
_db: &DB,
executor: DatabaseKeyIndex,
output_key: Option<crate::Id>,
) {
unreachable!(
"mark_validated_output({:?}, {:?}): input cannot be the output of a tracked function",
executor, output_key
);
}
fn remove_stale_output(
&self,
_db: &DB,
executor: DatabaseKeyIndex,
stale_output_key: Option<crate::Id>,
) {
unreachable!(
"remove_stale_output({:?}, {:?}): input cannot be the output of a tracked function",
executor, stale_output_key
);
}
fn reset_for_new_revision(&mut self) {
panic!("unexpected call to `reset_for_new_revision`")
}
fn salsa_struct_deleted(&self, _db: &DB, _id: crate::Id) {
panic!(
"unexpected call: input ingredients do not register for salsa struct deletion events"
);
}
fn fmt_index(&self, index: Option<crate::Id>, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
fmt_index(self.debug_name, index, fmt)
}
}
impl<Id> IngredientRequiresReset for InputIngredient<Id>
where
Id: InputId,
{
const RESET_ON_NEW_REVISION: bool = false;
}