mirror of
https://github.com/salsa-rs/salsa.git
synced 2024-11-24 20:20:26 +00:00
fad97eeb6a
This had two unexpected consequences, one unfortunate, one "medium": * All `salsa::Database` must be `'static`. This falls out from `Q::DynDb` not having access to any lifetimes, but also the defaulting rules for `dyn QueryGroup` that make it `dyn QueryGroup + 'static`. We don't really support generic databases anyway yet so this isn't a big deal, and we can add workarounds later (ideally via GATs). * It is now statically impossible to invoke `snapshot` from a query, and so we don't need to test that it panics. This is because the signature of `snapshot` returns a `Snapshot<Self>` and that is not accessible to a `dyn QueryGroup` type. Similarly, invoking `Runtime::snapshot` directly is not possible becaues it is crate-private. So I removed the test. This seems ok, but eventually I would like to expose ways for queries to do parallel execution (matklad and I had talked about a "speculation" primitive for enabling that). * This commit is 99% boilerplate I did with search-and-replace. I also rolled in a few other changes I might have preferred to factor out, most notably removing the `GetQueryTable` plumbing trait in favor of free-methods, but it was awkward to factor them out and get all the generics right (so much simpler in this version).
77 lines
2.4 KiB
Rust
77 lines
2.4 KiB
Rust
use crate::implementation::{TestContext, TestContextImpl};
|
|
use salsa::{Database, Durability};
|
|
|
|
#[salsa::query_group(MemoizedVolatile)]
|
|
pub(crate) trait MemoizedVolatileContext: TestContext {
|
|
// Queries for testing a "volatile" value wrapped by
|
|
// memoization.
|
|
fn memoized2(&self) -> usize;
|
|
fn memoized1(&self) -> usize;
|
|
fn volatile(&self) -> usize;
|
|
}
|
|
|
|
fn memoized2(db: &dyn MemoizedVolatileContext) -> usize {
|
|
db.log().add("Memoized2 invoked");
|
|
db.memoized1()
|
|
}
|
|
|
|
fn memoized1(db: &dyn MemoizedVolatileContext) -> usize {
|
|
db.log().add("Memoized1 invoked");
|
|
let v = db.volatile();
|
|
v / 2
|
|
}
|
|
|
|
fn volatile(db: &dyn MemoizedVolatileContext) -> usize {
|
|
db.log().add("Volatile invoked");
|
|
db.salsa_runtime().report_untracked_read();
|
|
db.clock().increment()
|
|
}
|
|
|
|
#[test]
|
|
fn volatile_x2() {
|
|
let query = TestContextImpl::default();
|
|
|
|
// Invoking volatile twice doesn't execute twice, because volatile
|
|
// queries are memoized by default.
|
|
query.volatile();
|
|
query.volatile();
|
|
query.assert_log(&["Volatile invoked"]);
|
|
}
|
|
|
|
/// Test that:
|
|
///
|
|
/// - On the first run of R0, we recompute everything.
|
|
/// - On the second run of R1, we recompute nothing.
|
|
/// - On the first run of R1, we recompute Memoized1 but not Memoized2 (since Memoized1 result
|
|
/// did not change).
|
|
/// - On the second run of R1, we recompute nothing.
|
|
/// - On the first run of R2, we recompute everything (since Memoized1 result *did* change).
|
|
#[test]
|
|
fn revalidate() {
|
|
let mut query = TestContextImpl::default();
|
|
|
|
query.memoized2();
|
|
query.assert_log(&["Memoized2 invoked", "Memoized1 invoked", "Volatile invoked"]);
|
|
|
|
query.memoized2();
|
|
query.assert_log(&[]);
|
|
|
|
// Second generation: volatile will change (to 1) but memoized1
|
|
// will not (still 0, as 1/2 = 0)
|
|
query.salsa_runtime_mut().synthetic_write(Durability::LOW);
|
|
query.memoized2();
|
|
query.assert_log(&["Memoized1 invoked", "Volatile invoked"]);
|
|
query.memoized2();
|
|
query.assert_log(&[]);
|
|
|
|
// Third generation: volatile will change (to 2) and memoized1
|
|
// will too (to 1). Therefore, after validating that Memoized1
|
|
// changed, we now invoke Memoized2.
|
|
query.salsa_runtime_mut().synthetic_write(Durability::LOW);
|
|
|
|
query.memoized2();
|
|
query.assert_log(&["Memoized1 invoked", "Volatile invoked", "Memoized2 invoked"]);
|
|
|
|
query.memoized2();
|
|
query.assert_log(&[]);
|
|
}
|