mirror of
https://github.com/salsa-rs/salsa.git
synced 2025-07-07 13:25:17 +00:00

Some checks are pending
Test / Test (push) Waiting to run
Test / Miri (push) Waiting to run
Test / Shuttle (push) Waiting to run
Test / Benchmarks (push) Waiting to run
Book / Book (push) Waiting to run
Book / Deploy (push) Blocked by required conditions
Release-plz / Release-plz release (push) Waiting to run
Release-plz / Release-plz PR (push) Waiting to run
* Set `validate_final` in `execute` after removing the last cycle head * Add runaway query repro * Add tracing * Fix part 1 * Fix `cycle_head_kinds` to always return provisional for memos that aren't verified final (They should be validated by `validate_same_iteration` or wait for the cycle head * Fix cycle error * Documentation * Fix await for queries depending on initial value * correctly initialize queued * Cleanup * Short circuit if entire query runs on single thread * Move parallel code into its own method * Rename method, add self_key to queued * Revert self-key changes * Move check *after* `deep_verify_memo` * Add a test for a cycle with changing cycle heads * Short circuit more often * Consider iteration in `validate_provisional` * Only yield if all heads result in a cycle. Retry if even just one inner cycle made progress (in which case there's a probably a new memo) * Fix hangs * Cargo fmt * clippy * Fix hang if cycle initial panics * Rename `cycle_head_kind` enable `cycle_a_t1_b_t2_fallback` shuttle test * Cleanup * Docs
127 lines
3.6 KiB
Rust
127 lines
3.6 KiB
Rust
use expect_test::expect;
|
|
use salsa::{Backtrace, Database, DatabaseImpl};
|
|
use test_log::test;
|
|
|
|
#[salsa::input(debug)]
|
|
struct Thing {
|
|
detailed: bool,
|
|
}
|
|
|
|
#[salsa::tracked]
|
|
fn query_a(db: &dyn Database, thing: Thing) -> String {
|
|
query_b(db, thing)
|
|
}
|
|
|
|
#[salsa::tracked]
|
|
fn query_b(db: &dyn Database, thing: Thing) -> String {
|
|
query_c(db, thing)
|
|
}
|
|
|
|
#[salsa::tracked]
|
|
fn query_c(db: &dyn Database, thing: Thing) -> String {
|
|
query_d(db, thing)
|
|
}
|
|
|
|
#[salsa::tracked]
|
|
fn query_d(db: &dyn Database, thing: Thing) -> String {
|
|
query_e(db, thing)
|
|
}
|
|
|
|
#[salsa::tracked]
|
|
fn query_e(db: &dyn Database, thing: Thing) -> String {
|
|
if thing.detailed(db) {
|
|
format!("{:#}", Backtrace::capture().unwrap())
|
|
} else {
|
|
format!("{}", Backtrace::capture().unwrap())
|
|
}
|
|
}
|
|
#[salsa::tracked]
|
|
fn query_f(db: &dyn Database, thing: Thing) -> String {
|
|
query_cycle(db, thing)
|
|
}
|
|
|
|
#[salsa::tracked(cycle_fn=cycle_fn, cycle_initial=cycle_initial)]
|
|
fn query_cycle(db: &dyn Database, thing: Thing) -> String {
|
|
let backtrace = query_cycle(db, thing);
|
|
if backtrace.is_empty() {
|
|
query_e(db, thing)
|
|
} else {
|
|
backtrace
|
|
}
|
|
}
|
|
|
|
fn cycle_initial(_db: &dyn salsa::Database, _thing: Thing) -> String {
|
|
String::new()
|
|
}
|
|
|
|
fn cycle_fn(
|
|
_db: &dyn salsa::Database,
|
|
_value: &str,
|
|
_count: u32,
|
|
_thing: Thing,
|
|
) -> salsa::CycleRecoveryAction<String> {
|
|
salsa::CycleRecoveryAction::Iterate
|
|
}
|
|
|
|
#[test]
|
|
fn backtrace_works() {
|
|
let db = DatabaseImpl::default();
|
|
|
|
let backtrace = query_a(&db, Thing::new(&db, false)).replace("\\", "/");
|
|
expect![[r#"
|
|
query stacktrace:
|
|
0: query_e(Id(0))
|
|
at tests/backtrace.rs:30
|
|
1: query_d(Id(0))
|
|
at tests/backtrace.rs:25
|
|
2: query_c(Id(0))
|
|
at tests/backtrace.rs:20
|
|
3: query_b(Id(0))
|
|
at tests/backtrace.rs:15
|
|
4: query_a(Id(0))
|
|
at tests/backtrace.rs:10
|
|
"#]]
|
|
.assert_eq(&backtrace);
|
|
|
|
let backtrace = query_a(&db, Thing::new(&db, true)).replace("\\", "/");
|
|
expect![[r#"
|
|
query stacktrace:
|
|
0: query_e(Id(1)) -> (R1, Durability::LOW)
|
|
at tests/backtrace.rs:30
|
|
1: query_d(Id(1)) -> (R1, Durability::HIGH)
|
|
at tests/backtrace.rs:25
|
|
2: query_c(Id(1)) -> (R1, Durability::HIGH)
|
|
at tests/backtrace.rs:20
|
|
3: query_b(Id(1)) -> (R1, Durability::HIGH)
|
|
at tests/backtrace.rs:15
|
|
4: query_a(Id(1)) -> (R1, Durability::HIGH)
|
|
at tests/backtrace.rs:10
|
|
"#]]
|
|
.assert_eq(&backtrace);
|
|
|
|
let backtrace = query_f(&db, Thing::new(&db, false)).replace("\\", "/");
|
|
expect![[r#"
|
|
query stacktrace:
|
|
0: query_e(Id(2))
|
|
at tests/backtrace.rs:30
|
|
1: query_cycle(Id(2))
|
|
at tests/backtrace.rs:43
|
|
cycle heads: query_cycle(Id(2)) -> IterationCount(0)
|
|
2: query_f(Id(2))
|
|
at tests/backtrace.rs:38
|
|
"#]]
|
|
.assert_eq(&backtrace);
|
|
|
|
let backtrace = query_f(&db, Thing::new(&db, true)).replace("\\", "/");
|
|
expect![[r#"
|
|
query stacktrace:
|
|
0: query_e(Id(3)) -> (R1, Durability::LOW)
|
|
at tests/backtrace.rs:30
|
|
1: query_cycle(Id(3)) -> (R1, Durability::HIGH, iteration = IterationCount(0))
|
|
at tests/backtrace.rs:43
|
|
cycle heads: query_cycle(Id(3)) -> IterationCount(0)
|
|
2: query_f(Id(3)) -> (R1, Durability::HIGH)
|
|
at tests/backtrace.rs:38
|
|
"#]]
|
|
.assert_eq(&backtrace);
|
|
}
|