add a "runtime" and use that from query context impls

This commit is contained in:
Niko Matsakis 2018-09-29 05:31:26 -04:00
parent ac7b02b7ef
commit 288fe5b25f
6 changed files with 82 additions and 62 deletions

View file

@ -1,17 +1,13 @@
use crate::class_table;
use crate::compiler::{CompilerQueryContext, Interner};
use salsa::dyn_descriptor::DynDescriptor;
use salsa::query_context_storage;
use salsa::BaseQueryContext;
use salsa::Query;
use std::cell::RefCell;
use std::fmt::Write;
#[derive(Default)]
pub struct QueryContextImpl {
runtime: salsa::Runtime<QueryContextImpl>,
storage: QueryContextImplStorage,
interner: Interner,
execution_stack: RefCell<Vec<DynDescriptor>>,
}
// This is an example of how you "link up" all the queries in your
@ -42,34 +38,9 @@ impl CompilerQueryContext for QueryContextImpl {
// permit behavior refinement.
impl BaseQueryContext for QueryContextImpl {
type QueryDescriptor = DynDescriptor;
type QueryDescriptor = salsa::dyn_descriptor::DynDescriptor;
fn execute_query_implementation<Q>(
&self,
descriptor: Self::QueryDescriptor,
key: &Q::Key,
) -> Q::Value
where
Q: Query<Self>,
{
self.execution_stack.borrow_mut().push(descriptor);
let value = Q::execute(self, key.clone());
self.execution_stack.borrow_mut().pop();
value
}
fn report_unexpected_cycle(&self, descriptor: Self::QueryDescriptor) -> ! {
let execution_stack = self.execution_stack.borrow();
let start_index = (0..execution_stack.len())
.rev()
.filter(|&i| execution_stack[i] == descriptor)
.next()
.unwrap();
let mut message = format!("Internal error, cycle detected:\n");
for descriptor in &execution_stack[start_index..] {
writeln!(message, "- {:?}\n", descriptor).unwrap();
}
panic!(message)
fn salsa_runtime(&self) -> &salsa::runtime::Runtime<QueryContextImpl> {
&self.runtime
}
}

View file

@ -3,6 +3,7 @@ use std::cell::Cell;
#[derive(Default)]
pub struct QueryContextImpl {
runtime: salsa::Runtime<QueryContextImpl>,
storage: QueryContextImplStorage,
counter: Cell<usize>,
}
@ -27,19 +28,7 @@ impl queries::CounterContext for QueryContextImpl {
impl salsa::BaseQueryContext for QueryContextImpl {
type QueryDescriptor = salsa::dyn_descriptor::DynDescriptor;
fn execute_query_implementation<Q>(
&self,
_descriptor: Self::QueryDescriptor,
key: &Q::Key,
) -> Q::Value
where
Q: salsa::Query<Self>,
{
let value = Q::execute(self, key.clone());
value
}
fn report_unexpected_cycle(&self, _descriptor: Self::QueryDescriptor) -> ! {
panic!("cycle")
fn salsa_runtime(&self) -> &salsa::runtime::Runtime<QueryContextImpl> {
&self.runtime
}
}

View file

@ -1,5 +1,6 @@
#![deny(rust_2018_idioms)]
#![feature(in_band_lifetimes)]
#![feature(crate_visibility_modifier)]
#![feature(nll)]
#![feature(min_const_fn)]
#![feature(const_fn)]
@ -20,8 +21,11 @@ use std::hash::Hash;
pub mod dyn_descriptor;
pub mod memoized;
pub mod runtime;
pub mod transparent;
pub use self::runtime::Runtime;
pub trait BaseQueryContext: Sized {
/// A "query descriptor" packages up all the possible queries and a key.
/// It is used to store information about (e.g.) the stack.
@ -31,16 +35,8 @@ pub trait BaseQueryContext: Sized {
/// for a more open-ended option.
type QueryDescriptor: Debug + Eq;
fn execute_query_implementation<Q>(
&self,
descriptor: Self::QueryDescriptor,
key: &Q::Key,
) -> Q::Value
where
Q: Query<Self>;
/// Reports an unexpected cycle attempting to access the query Q with the given key.
fn report_unexpected_cycle(&self, descriptor: Self::QueryDescriptor) -> !;
/// Gives access to the underlying salsa runtime.
fn salsa_runtime(&self) -> &runtime::Runtime<Self>;
}
pub trait Query<QC: BaseQueryContext>: Debug + Default + Sized + 'static {
@ -86,7 +82,9 @@ where
self.storage
.try_fetch(self.query, &key, || self.descriptor(&key))
.unwrap_or_else(|CycleDetected| {
self.query.report_unexpected_cycle(self.descriptor(&key))
self.query
.salsa_runtime()
.report_unexpected_cycle(self.descriptor(&key))
})
}
@ -301,6 +299,8 @@ macro_rules! query_definition {
};
}
/// This macro generates the "query storage" that goes into your query
/// context.
#[macro_export]
macro_rules! query_context_storage {
(
@ -336,8 +336,6 @@ macro_rules! query_context_storage {
self,
&self.$storage_field.$query_method,
// FIXME: we should not hardcode the descriptor like this.
// Have to think of the best fix.
$crate::dyn_descriptor::DynDescriptor::from_key::<
Self,
$QueryType,

View file

@ -75,7 +75,9 @@ where
// If we get here, the query is in progress, and we are the
// ones tasked with finding its final value.
let descriptor = descriptor();
let value = query.execute_query_implementation::<Q>(descriptor, key);
let value = query
.salsa_runtime()
.execute_query_implementation::<Q>(query, descriptor, key);
{
let mut map_write = self.map.write();

58
src/runtime.rs Normal file
View file

@ -0,0 +1,58 @@
use crate::BaseQueryContext;
use crate::Query;
use std::cell::RefCell;
use std::fmt::Write;
pub struct Runtime<QC>
where
QC: BaseQueryContext,
{
execution_stack: RefCell<Vec<QC::QueryDescriptor>>,
}
impl<QC> Default for Runtime<QC>
where
QC: BaseQueryContext,
{
fn default() -> Self {
Runtime {
execution_stack: RefCell::default(),
}
}
}
impl<QC> Runtime<QC>
where
QC: BaseQueryContext,
{
crate fn execute_query_implementation<Q>(
&self,
query: &QC,
descriptor: QC::QueryDescriptor,
key: &Q::Key,
) -> Q::Value
where
Q: Query<QC>,
{
self.execution_stack.borrow_mut().push(descriptor);
let value = Q::execute(query, key.clone());
self.execution_stack.borrow_mut().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())
.rev()
.filter(|&i| execution_stack[i] == descriptor)
.next()
.unwrap();
let mut message = format!("Internal error, cycle detected:\n");
for descriptor in &execution_stack[start_index..] {
writeln!(message, "- {:?}\n", descriptor).unwrap();
}
panic!(message)
}
}

View file

@ -35,6 +35,8 @@ where
// here? Or should we just call `Q::execute`, and maybe
// separate out the `push`/`pop` operations.
let descriptor = descriptor();
Ok(query.execute_query_implementation::<Q>(descriptor, key))
Ok(query
.salsa_runtime()
.execute_query_implementation::<Q>(query, descriptor, key))
}
}