message: introduce a `LocalState` type
diff: use crate::Query;
  use crate::QueryContext;
  +use rustc_hash::FxHashMap;
  use std::cell::RefCell;
  use std::fmt::Write;
  -use std::sync::atomic::AtomicU64;
  +use std::sync::atomic::{AtomicU64, Ordering};
  use std::sync::Arc;
  pub struct Runtime<QC>
  @@ -10,9 +11,10 @@ where
  QC: QueryContext,
  {
  shared_state: Arc<SharedState<QC>>,
  - execution_stack: RefCell<Vec<QC::QueryDescriptor>>,
  + local_state: RefCell<LocalState<QC>>,
  }
  +/// State that will be common to all threads (when we support multiple threads)
  struct SharedState<QC>
  where
  QC: QueryContext,
  @@ -21,9 +23,23 @@ where
  revision: AtomicU64,
  }
  +/// State that will be specific to a single execution threads (when we support multiple threads)
  +struct LocalState<QC>
  +where
  + QC: QueryContext,
  +{
  + query_stack: Vec<QC::QueryDescriptor>,
  +}
  +
  #[derive(Copy, Clone, Debug, PartialEq, Eq, Hash, PartialOrd, Ord)]
  pub struct Revision {
  - generation: usize,
  + generation: u64,
  +}
  +
  +impl Revision {
  + crate fn zero() -> Self {
  + Revision { generation: 0 }
  + }
  }
  impl<QC> Default for Runtime<QC>
  @@ -36,7 +52,9 @@ where
  storage: Default::default(),
  revision: Default::default(),
  }),
  - execution_stack: RefCell::default(),
  + local_state: RefCell::new(LocalState {
  + query_stack: Default::default(),
  + }),
  }
  }
  }
  @@ -49,6 +67,20 @@ where
  &self.shared_state.storage
  }
  + /// Read current value of the revision counter.
  + crate fn current_revision(&self) -> Revision {
  + Revision {
  + generation: self.shared_state.revision.load(Ordering::SeqCst),
  + }
  + }
  +
  + /// Increments the current revision counter and returns the new value.
  + crate fn increment_revision(&self) -> Revision {
  + Revision {
  + generation: 1 + self.shared_state.revision.fetch_add(1, Ordering::SeqCst),
  + }
  + }
  +
  crate fn execute_query_implementation<Q>(
  &self,
  query: &QC,
  @@ -58,23 +90,25 @@ where
  where
  Q: Query<QC>,
  {
  - self.execution_stack.borrow_mut().push(descriptor);
  + self.local_state.borrow_mut().query_stack.push(descriptor);
  let value = Q::execute(query, key.clone());
  - self.execution_stack.borrow_mut().pop();
  + self.local_state.borrow_mut().query_stack.pop();
  value
  }
  /// Obviously, this should be user configurable at some point.
  crate fn report_unexpected_cycle(&self, descriptor: QC::QueryDescriptor) -> ! {
  - let execution_stack = self.execution_stack.borrow();
  - let start_index = (0..execution_stack.len())
  + let local_state = self.local_state.borrow();
  + let LocalState { query_stack, .. } = &*local_state;
  +
  + let start_index = (0..query_stack.len())
  .rev()
  - .filter(|&i| execution_stack[i] == descriptor)
  + .filter(|&i| query_stack[i] == descriptor)
  .next()
  .unwrap();
  let mut message = format!("Internal error, cycle detected:\n");
  - for descriptor in &execution_stack[start_index..] {
  + for descriptor in &query_stack[start_index..] {
  writeln!(message, "- {:?}\n", descriptor).unwrap();
  }
  panic!(message)
  