diff --git a/src/debug.rs b/src/debug.rs new file mode 100644 index 0000000..491ffdf --- /dev/null +++ b/src/debug.rs @@ -0,0 +1,28 @@ +//! Debugging APIs: these are meant for use when unit-testing or +//! debugging your application but aren't ordinarily needed. + +use crate::Database; +use crate::Query; +use crate::QueryStorageOps; +use crate::QueryTable; + +pub trait DebugQueryTable { + type Key; + + /// True if salsa thinks that the value for `key` is a + /// **constant**, meaning that it can never change, no matter what + /// values the inputs take on from this point. + fn is_constant(&self, key: Self::Key) -> bool; +} + +impl DebugQueryTable for QueryTable<'_, DB, Q> +where + DB: Database, + Q: Query, +{ + type Key = Q::Key; + + fn is_constant(&self, key: Q::Key) -> bool { + self.storage.is_constant(self.db, &key) + } +} diff --git a/src/derived.rs b/src/derived.rs index 5a37097..c1042f3 100644 --- a/src/derived.rs +++ b/src/derived.rs @@ -396,6 +396,15 @@ where true } + + fn is_constant(&self, _db: &DB, key: &Q::Key) -> bool { + let map_read = self.map.read(); + match map_read.get(key) { + None => false, + Some(QueryState::InProgress) => panic!("query in progress"), + Some(QueryState::Memoized(memo)) => memo.changed_at.is_constant(), + } + } } impl UncheckedMutQueryStorageOps for DerivedStorage diff --git a/src/input.rs b/src/input.rs index c81523a..face524 100644 --- a/src/input.rs +++ b/src/input.rs @@ -177,6 +177,14 @@ where changed_at.changed_since(revision) } + + fn is_constant(&self, _db: &DB, key: &Q::Key) -> bool { + let map_read = self.map.read(); + map_read + .get(key) + .map(|v| v.changed_at.is_constant()) + .unwrap_or(false) + } } impl InputQueryStorageOps for InputStorage diff --git a/src/lib.rs b/src/lib.rs index cb98a17..af20b33 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -12,6 +12,7 @@ use std::fmt::Display; use std::fmt::Write; use std::hash::Hash; +pub mod debug; pub mod derived; pub mod input; pub mod runtime; @@ -119,6 +120,9 @@ where key: &Q::Key, descriptor: &DB::QueryDescriptor, ) -> bool; + + /// Check if `key` is (currently) believed to be a constant. + fn is_constant(&self, db: &DB, key: &Q::Key) -> bool; } /// An optional trait that is implemented for "user mutable" storage: