diff --git a/src/debug.rs b/src/debug.rs index 00cb2f24..601d3bab 100644 --- a/src/debug.rs +++ b/src/debug.rs @@ -14,6 +14,9 @@ pub trait DebugQueryTable { /// Key of this query. type Key; + /// Value of this query. + type Value; + /// 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. @@ -23,6 +26,30 @@ pub trait DebugQueryTable { fn keys(&self) -> C where C: FromIterator; + + /// Get the (current) set of the entries in the query table. + fn entries(&self) -> C + where + C: FromIterator>; +} + +/// An entry from a query table, for debugging and inspecting the table state. +pub struct TableEntry { + /// key of the query + pub key: K, + /// value of the query, if it is stored + pub value: Option, + _for_future_use: (), +} + +impl TableEntry { + pub(crate) fn new(key: K, value: Option) -> TableEntry { + TableEntry { + key, + value, + _for_future_use: (), + } + } } impl DebugQueryTable for QueryTable<'_, DB, Q> @@ -31,6 +58,7 @@ where Q: Query, { type Key = Q::Key; + type Value = Q::Value; fn is_constant(&self, key: Q::Key) -> bool { self.storage.is_constant(self.db, &key) @@ -42,4 +70,11 @@ where { self.storage.keys(self.db) } + + fn entries(&self) -> C + where + C: FromIterator>, + { + self.storage.entries(self.db) + } } diff --git a/src/derived.rs b/src/derived.rs index 2754b37c..98116397 100644 --- a/src/derived.rs +++ b/src/derived.rs @@ -1,3 +1,4 @@ +use crate::debug::TableEntry; use crate::plumbing::CycleDetected; use crate::plumbing::QueryDescriptor; use crate::plumbing::QueryFunction; @@ -162,6 +163,13 @@ where waiting: Default::default(), } } + + fn value(&self) -> Option { + match self { + QueryState::InProgress { .. } => None, + QueryState::Memoized(memo) => memo.value.clone(), + } + } } struct Memo @@ -901,6 +909,16 @@ where let map = self.map.read(); map.keys().cloned().collect() } + + fn entries(&self, _db: &DB) -> C + where + C: std::iter::FromIterator>, + { + let map = self.map.read(); + map.iter() + .map(|(key, query_state)| TableEntry::new(key.clone(), query_state.value())) + .collect() + } } impl QueryStorageMassOps for DerivedStorage diff --git a/src/input.rs b/src/input.rs index 2ac519c1..f91dd3db 100644 --- a/src/input.rs +++ b/src/input.rs @@ -1,3 +1,4 @@ +use crate::debug::TableEntry; use crate::plumbing::CycleDetected; use crate::plumbing::InputQueryStorageOps; use crate::plumbing::QueryStorageMassOps; @@ -200,6 +201,18 @@ where let map = self.map.read(); map.keys().cloned().collect() } + + fn entries(&self, _db: &DB) -> C + where + C: std::iter::FromIterator>, + { + let map = self.map.read(); + map.iter() + .map(|(key, stamped_value)| { + TableEntry::new(key.clone(), Some(stamped_value.value.clone())) + }) + .collect() + } } impl QueryStorageMassOps for InputStorage diff --git a/src/plumbing.rs b/src/plumbing.rs index 61768bed..d4184806 100644 --- a/src/plumbing.rs +++ b/src/plumbing.rs @@ -1,5 +1,6 @@ #![allow(missing_docs)] +use crate::debug::TableEntry; use crate::Database; use crate::Query; use crate::QueryTable; @@ -133,6 +134,11 @@ where fn keys(&self, db: &DB) -> C where C: std::iter::FromIterator; + + /// Get the (current) set of the entries in the query storage + fn entries(&self, db: &DB) -> C + where + C: std::iter::FromIterator>; } /// An optional trait that is implemented for "user mutable" storage: