mirror of
https://github.com/salsa-rs/salsa.git
synced 2025-01-22 21:05:11 +00:00
add a "runtime" and use that from query context impls
This commit is contained in:
parent
ac7b02b7ef
commit
288fe5b25f
6 changed files with 82 additions and 62 deletions
|
@ -1,17 +1,13 @@
|
||||||
use crate::class_table;
|
use crate::class_table;
|
||||||
use crate::compiler::{CompilerQueryContext, Interner};
|
use crate::compiler::{CompilerQueryContext, Interner};
|
||||||
use salsa::dyn_descriptor::DynDescriptor;
|
|
||||||
use salsa::query_context_storage;
|
use salsa::query_context_storage;
|
||||||
use salsa::BaseQueryContext;
|
use salsa::BaseQueryContext;
|
||||||
use salsa::Query;
|
|
||||||
use std::cell::RefCell;
|
|
||||||
use std::fmt::Write;
|
|
||||||
|
|
||||||
#[derive(Default)]
|
#[derive(Default)]
|
||||||
pub struct QueryContextImpl {
|
pub struct QueryContextImpl {
|
||||||
|
runtime: salsa::Runtime<QueryContextImpl>,
|
||||||
storage: QueryContextImplStorage,
|
storage: QueryContextImplStorage,
|
||||||
interner: Interner,
|
interner: Interner,
|
||||||
execution_stack: RefCell<Vec<DynDescriptor>>,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// This is an example of how you "link up" all the queries in your
|
// 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.
|
// permit behavior refinement.
|
||||||
|
|
||||||
impl BaseQueryContext for QueryContextImpl {
|
impl BaseQueryContext for QueryContextImpl {
|
||||||
type QueryDescriptor = DynDescriptor;
|
type QueryDescriptor = salsa::dyn_descriptor::DynDescriptor;
|
||||||
|
|
||||||
fn execute_query_implementation<Q>(
|
fn salsa_runtime(&self) -> &salsa::runtime::Runtime<QueryContextImpl> {
|
||||||
&self,
|
&self.runtime
|
||||||
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)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -3,6 +3,7 @@ use std::cell::Cell;
|
||||||
|
|
||||||
#[derive(Default)]
|
#[derive(Default)]
|
||||||
pub struct QueryContextImpl {
|
pub struct QueryContextImpl {
|
||||||
|
runtime: salsa::Runtime<QueryContextImpl>,
|
||||||
storage: QueryContextImplStorage,
|
storage: QueryContextImplStorage,
|
||||||
counter: Cell<usize>,
|
counter: Cell<usize>,
|
||||||
}
|
}
|
||||||
|
@ -27,19 +28,7 @@ impl queries::CounterContext for QueryContextImpl {
|
||||||
impl salsa::BaseQueryContext for QueryContextImpl {
|
impl salsa::BaseQueryContext for QueryContextImpl {
|
||||||
type QueryDescriptor = salsa::dyn_descriptor::DynDescriptor;
|
type QueryDescriptor = salsa::dyn_descriptor::DynDescriptor;
|
||||||
|
|
||||||
fn execute_query_implementation<Q>(
|
fn salsa_runtime(&self) -> &salsa::runtime::Runtime<QueryContextImpl> {
|
||||||
&self,
|
&self.runtime
|
||||||
_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")
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
24
src/lib.rs
24
src/lib.rs
|
@ -1,5 +1,6 @@
|
||||||
#![deny(rust_2018_idioms)]
|
#![deny(rust_2018_idioms)]
|
||||||
#![feature(in_band_lifetimes)]
|
#![feature(in_band_lifetimes)]
|
||||||
|
#![feature(crate_visibility_modifier)]
|
||||||
#![feature(nll)]
|
#![feature(nll)]
|
||||||
#![feature(min_const_fn)]
|
#![feature(min_const_fn)]
|
||||||
#![feature(const_fn)]
|
#![feature(const_fn)]
|
||||||
|
@ -20,8 +21,11 @@ use std::hash::Hash;
|
||||||
|
|
||||||
pub mod dyn_descriptor;
|
pub mod dyn_descriptor;
|
||||||
pub mod memoized;
|
pub mod memoized;
|
||||||
|
pub mod runtime;
|
||||||
pub mod transparent;
|
pub mod transparent;
|
||||||
|
|
||||||
|
pub use self::runtime::Runtime;
|
||||||
|
|
||||||
pub trait BaseQueryContext: Sized {
|
pub trait BaseQueryContext: Sized {
|
||||||
/// A "query descriptor" packages up all the possible queries and a key.
|
/// A "query descriptor" packages up all the possible queries and a key.
|
||||||
/// It is used to store information about (e.g.) the stack.
|
/// 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.
|
/// for a more open-ended option.
|
||||||
type QueryDescriptor: Debug + Eq;
|
type QueryDescriptor: Debug + Eq;
|
||||||
|
|
||||||
fn execute_query_implementation<Q>(
|
/// Gives access to the underlying salsa runtime.
|
||||||
&self,
|
fn salsa_runtime(&self) -> &runtime::Runtime<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) -> !;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub trait Query<QC: BaseQueryContext>: Debug + Default + Sized + 'static {
|
pub trait Query<QC: BaseQueryContext>: Debug + Default + Sized + 'static {
|
||||||
|
@ -86,7 +82,9 @@ where
|
||||||
self.storage
|
self.storage
|
||||||
.try_fetch(self.query, &key, || self.descriptor(&key))
|
.try_fetch(self.query, &key, || self.descriptor(&key))
|
||||||
.unwrap_or_else(|CycleDetected| {
|
.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_export]
|
||||||
macro_rules! query_context_storage {
|
macro_rules! query_context_storage {
|
||||||
(
|
(
|
||||||
|
@ -336,8 +336,6 @@ macro_rules! query_context_storage {
|
||||||
self,
|
self,
|
||||||
&self.$storage_field.$query_method,
|
&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::<
|
$crate::dyn_descriptor::DynDescriptor::from_key::<
|
||||||
Self,
|
Self,
|
||||||
$QueryType,
|
$QueryType,
|
||||||
|
|
|
@ -75,7 +75,9 @@ where
|
||||||
// If we get here, the query is in progress, and we are the
|
// If we get here, the query is in progress, and we are the
|
||||||
// ones tasked with finding its final value.
|
// ones tasked with finding its final value.
|
||||||
let descriptor = descriptor();
|
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();
|
let mut map_write = self.map.write();
|
||||||
|
|
58
src/runtime.rs
Normal file
58
src/runtime.rs
Normal 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)
|
||||||
|
}
|
||||||
|
}
|
|
@ -35,6 +35,8 @@ where
|
||||||
// here? Or should we just call `Q::execute`, and maybe
|
// here? Or should we just call `Q::execute`, and maybe
|
||||||
// separate out the `push`/`pop` operations.
|
// separate out the `push`/`pop` operations.
|
||||||
let descriptor = descriptor();
|
let descriptor = descriptor();
|
||||||
Ok(query.execute_query_implementation::<Q>(descriptor, key))
|
Ok(query
|
||||||
|
.salsa_runtime()
|
||||||
|
.execute_query_implementation::<Q>(query, descriptor, key))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue