Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion components/salsa-macro-rules/src/setup_input_struct.rs
Original file line number Diff line number Diff line change
Expand Up @@ -392,7 +392,7 @@ macro_rules! setup_input_struct {
pub(super) fn new_builder($($field_id: $field_ty),*) -> $Builder {
$Builder {
fields: ($($field_id,)*),
durabilities: [::salsa::Durability::default(); $N],
durabilities: [::salsa::Durability::MIN; $N],
}
}

Expand Down
6 changes: 5 additions & 1 deletion components/salsa-macro-rules/src/setup_tracked_fn.rs
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,8 @@ macro_rules! setup_tracked_fn {
// If true, the input and output values implement `serde::{Serialize, Deserialize}`.
persist: $persist:tt,

force_durability: $force_durability:expr,

assert_return_type_is_update: {$($assert_return_type_is_update:tt)*},

$(self_ty: $self_ty:ty,)?
Expand Down Expand Up @@ -286,6 +288,8 @@ macro_rules! setup_tracked_fn {

const CYCLE_STRATEGY: $zalsa::CycleRecoveryStrategy = $zalsa::CycleRecoveryStrategy::$cycle_recovery_strategy;

const FORCE_DURABILITY: Option<$zalsa::Durability> = $force_durability;

$($values_equal)+

$(
Expand Down Expand Up @@ -387,7 +391,7 @@ macro_rules! setup_tracked_fn {
zalsa,
struct_index,
first_index,
$zalsa::function::MemoEntryType::of::<$zalsa::function::Memo<$Configuration>>(),
$zalsa::function::MemoEntryType::of::<$zalsa::function::AmbiguousMemo<$Configuration>>(),
intern_ingredient_memo_types,
)
};
Expand Down
1 change: 1 addition & 0 deletions components/salsa-macros/src/accumulator.rs
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,7 @@ impl AllowedOptions for Accumulator {
const SELF_TY: bool = false;
// TODO: Support serializing accumulators.
const PERSIST: AllowedPersistOptions = AllowedPersistOptions::Invalid;
const FORCE_DURABILITY: bool = false;
}

struct StructMacro {
Expand Down
2 changes: 2 additions & 0 deletions components/salsa-macros/src/input.rs
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,8 @@ impl AllowedOptions for InputStruct {
const SELF_TY: bool = false;

const PERSIST: AllowedPersistOptions = AllowedPersistOptions::AllowedValue;

const FORCE_DURABILITY: bool = false;
}

impl SalsaStructAllowedOptions for InputStruct {
Expand Down
2 changes: 2 additions & 0 deletions components/salsa-macros/src/interned.rs
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,8 @@ impl AllowedOptions for InternedStruct {
const SELF_TY: bool = false;

const PERSIST: AllowedPersistOptions = AllowedPersistOptions::AllowedValue;

const FORCE_DURABILITY: bool = false;
}

impl SalsaStructAllowedOptions for InternedStruct {
Expand Down
20 changes: 20 additions & 0 deletions components/salsa-macros/src/options.rs
Original file line number Diff line number Diff line change
Expand Up @@ -115,6 +115,9 @@ pub(crate) struct Options<A: AllowedOptions> {
/// functions. This is merely used to refine the query name.
pub self_ty: Option<syn::Type>,

/// Force the durability of the query to always be this value.
pub force_durability: Option<syn::Expr>,

/// Remember the `A` parameter, which plays no role after parsing.
phantom: PhantomData<A>,
}
Expand Down Expand Up @@ -157,6 +160,7 @@ impl<A: AllowedOptions> Default for Options<A> {
heap_size_fn: Default::default(),
self_ty: Default::default(),
persist: Default::default(),
force_durability: Default::default(),
}
}
}
Expand All @@ -182,6 +186,7 @@ pub(crate) trait AllowedOptions {
const HEAP_SIZE: bool;
const SELF_TY: bool;
const PERSIST: AllowedPersistOptions;
const FORCE_DURABILITY: bool;
}

pub(crate) enum AllowedPersistOptions {
Expand Down Expand Up @@ -536,6 +541,17 @@ impl<A: AllowedOptions> syn::parse::Parse for Options<A> {
"`self_ty` option not allowed here",
));
}
} else if ident == "force_durability" {
if A::FORCE_DURABILITY {
let _eq = Equals::parse(input)?;
let path = syn::Expr::parse(input)?;
options.force_durability = Some(path);
} else {
return Err(syn::Error::new(
ident.span(),
"`force_durability` option not allowed here",
));
}
} else {
return Err(syn::Error::new(
ident.span(),
Expand Down Expand Up @@ -575,6 +591,7 @@ impl<A: AllowedOptions> quote::ToTokens for Options<A> {
heap_size_fn,
self_ty,
persist,
force_durability,
phantom: _,
} = self;
if let Some(returns) = returns {
Expand Down Expand Up @@ -648,5 +665,8 @@ impl<A: AllowedOptions> quote::ToTokens for Options<A> {
tokens.extend(quote::quote! { persist(#args), });
}
}
if let Some(force_durability) = force_durability {
tokens.extend(quote::quote! { force_durability = #force_durability, });
}
}
}
7 changes: 7 additions & 0 deletions components/salsa-macros/src/tracked_fn.rs
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,8 @@ impl AllowedOptions for TrackedFn {
const SELF_TY: bool = true;

const PERSIST: AllowedPersistOptions = AllowedPersistOptions::AllowedIdent;

const FORCE_DURABILITY: bool = true;
}

struct Macro {
Expand Down Expand Up @@ -209,6 +211,10 @@ impl Macro {
Some(ty) => quote! { self_ty: #ty, },
None => quote! {},
};
let force_durability = match &self.args.force_durability {
Some(durability) => quote!(Some(#durability)),
None => quote!(None),
};

Ok(crate::debug::dump_tokens(
fn_name,
Expand All @@ -234,6 +240,7 @@ impl Macro {
lru: #lru,
return_mode: #return_mode,
persist: #persist,
force_durability: #force_durability,
assert_return_type_is_update: { #assert_return_type_is_update },
#self_ty
unused_names: [
Expand Down
2 changes: 2 additions & 0 deletions components/salsa-macros/src/tracked_struct.rs
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,8 @@ impl AllowedOptions for TrackedStruct {
const SELF_TY: bool = false;

const PERSIST: AllowedPersistOptions = AllowedPersistOptions::AllowedValue;

const FORCE_DURABILITY: bool = false;
}

impl SalsaStructAllowedOptions for TrackedStruct {
Expand Down
4 changes: 4 additions & 0 deletions src/accumulator/accumulated_map.rs
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,10 @@ impl std::fmt::Debug for AccumulatedMap {
}

impl AccumulatedMap {
pub(crate) const EMPTY: AccumulatedMap = AccumulatedMap {
map: hashbrown::HashMap::with_hasher(FxBuildHasher),
};

pub fn accumulate<A: Accumulator>(&mut self, index: IngredientIndex, value: A) {
self.map
.entry(index)
Expand Down
13 changes: 10 additions & 3 deletions src/active_query.rs
Original file line number Diff line number Diff line change
Expand Up @@ -106,7 +106,6 @@ impl ActiveQuery {
) {
self.durability = self.durability.min(durability);
self.changed_at = self.changed_at.max(changed_at);
self.input_outputs.insert(QueryEdge::input(input));
self.cycle_heads.extend(cycle_heads);
#[cfg(feature = "accumulator")]
{
Expand All @@ -115,6 +114,10 @@ impl ActiveQuery {
false => accumulated_inputs.load(),
});
}
if !cycle_heads.is_empty() || durability != Durability::NEVER_CHANGE {
// During cycles we need to record dependencies.
self.input_outputs.insert(QueryEdge::input(input));
}
}

pub(super) fn add_read_simple(
Expand All @@ -125,7 +128,9 @@ impl ActiveQuery {
) {
self.durability = self.durability.min(durability);
self.changed_at = self.changed_at.max(revision);
self.input_outputs.insert(QueryEdge::input(input));
if durability != Durability::NEVER_CHANGE {
self.input_outputs.insert(QueryEdge::input(input));
}
}

pub(super) fn add_untracked_read(&mut self, changed_at: Revision) {
Expand All @@ -147,7 +152,9 @@ impl ActiveQuery {

/// Adds a key to our list of outputs.
pub(super) fn add_output(&mut self, key: DatabaseKeyIndex) {
self.input_outputs.insert(QueryEdge::output(key));
if self.durability != Durability::NEVER_CHANGE {
self.input_outputs.insert(QueryEdge::output(key));
}
}

/// True if the given key was output by this query.
Expand Down
2 changes: 2 additions & 0 deletions src/cycle.rs
Original file line number Diff line number Diff line change
Expand Up @@ -217,6 +217,7 @@ impl<'de> serde::Deserialize<'de> for AtomicIterationCount {
pub struct CycleHeads(ThinVec<CycleHead>);

impl CycleHeads {
#[inline]
pub(crate) fn is_empty(&self) -> bool {
self.0.is_empty()
}
Expand Down Expand Up @@ -505,6 +506,7 @@ pub enum ProvisionalStatus<'db> {
iteration: IterationCount,
verified_at: Revision,
},
FinalNeverChange,
FallbackImmediate,
}

Expand Down
21 changes: 15 additions & 6 deletions src/durability.rs
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,7 @@ impl std::fmt::Debug for Durability {
DurabilityVal::Low => f.write_str("Durability::LOW"),
DurabilityVal::Medium => f.write_str("Durability::MEDIUM"),
DurabilityVal::High => f.write_str("Durability::HIGH"),
DurabilityVal::NeverChange => f.write_str("Durability::NEVER_CHANGE"),
}
} else {
f.debug_tuple("Durability")
Expand All @@ -61,14 +62,17 @@ enum DurabilityVal {
Low = 0,
Medium = 1,
High = 2,
NeverChange = 3,
}

impl From<u8> for DurabilityVal {
#[inline]
fn from(value: u8) -> Self {
match value {
0 => DurabilityVal::Low,
1 => DurabilityVal::Medium,
2 => DurabilityVal::High,
3 => DurabilityVal::NeverChange,
_ => panic!("invalid durability"),
}
}
Expand All @@ -87,23 +91,28 @@ impl Durability {

/// High durability: things that are not expected to change under
/// common usage.
///
/// Example: the standard library or something from crates.io
pub const HIGH: Durability = Durability(DurabilityVal::High);

/// The input is guaranteed to never change. Queries calling it won't have
/// it as a dependency.
///
/// Example: the standard library or something from crates.io.
pub const NEVER_CHANGE: Durability = Durability(DurabilityVal::NeverChange);

/// The minimum possible durability; equivalent to LOW but
/// "conceptually" distinct (i.e., if we add more durability
/// levels, this could change).
pub(crate) const MIN: Durability = Self::LOW;
pub const MIN: Durability = Self::LOW;

/// The maximum possible durability; equivalent to HIGH but
/// The maximum possible durability; equivalent to NEVER_CHANGE but
/// "conceptually" distinct (i.e., if we add more durability
/// levels, this could change).
pub(crate) const MAX: Durability = Self::HIGH;
pub(crate) const MAX: Durability = Self::NEVER_CHANGE;

/// Number of durability levels.
pub(crate) const LEN: usize = Self::HIGH.0 as usize + 1;
pub(crate) const LEN: usize = Self::MAX.0 as usize + 1;

#[inline]
pub(crate) fn index(self) -> usize {
self.0 as usize
}
Expand Down
Loading
Loading