diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index e7019f3f8..0c0d3940e 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -41,6 +41,7 @@ jobs: with: toolchain: ${{ matrix.rust }} components: rustfmt, clippy + - uses: taiki-e/install-action@nextest - uses: actions/cache@v4 with: path: | @@ -58,7 +59,7 @@ jobs: - name: Clippy run: cargo clippy --workspace --all-features --all-targets -- -D warnings - name: Test - run: cargo test --workspace --all-features --all-targets + run: cargo nextest run --workspace --all-features --all-targets --no-fail-fast - name: Test docs run: cargo test --workspace --all-features --doc - name: Check (without default features) @@ -73,6 +74,7 @@ jobs: - name: Install Miri uses: dtolnay/rust-toolchain@miri id: rust-toolchain + - uses: taiki-e/install-action@nextest - uses: actions/cache@v4 with: path: | @@ -89,12 +91,11 @@ jobs: - name: Setup Miri run: cargo miri setup - name: Test with Miri - run: cargo miri test --no-fail-fast --all-features + run: cargo miri nextest run --all-features --no-fail-fast --tests env: MIRIFLAGS: -Zmiri-disable-isolation -Zmiri-retag-fields - name: Run examples with Miri - run: | - cargo miri run --example calc + run: cargo miri run --example calc benchmarks: # https://github.com/CodSpeedHQ/action/issues/126 diff --git a/benches/dataflow.rs b/benches/dataflow.rs index d535046e9..dc419a0ea 100644 --- a/benches/dataflow.rs +++ b/benches/dataflow.rs @@ -7,6 +7,8 @@ use salsa::{CycleRecoveryAction, Database as Db, Setter}; use std::collections::BTreeSet; use std::iter::IntoIterator; +include!("shims/global_alloc_overwrite.rs"); + /// A Use of a symbol. #[salsa::input] struct Use { diff --git a/examples/calc/type_check.rs b/examples/calc/type_check.rs index e5bbba6b8..dd5b963f9 100644 --- a/examples/calc/type_check.rs +++ b/examples/calc/type_check.rs @@ -108,7 +108,7 @@ impl<'db> CheckExpression<'_, 'db> { fn check_string( source_text: &str, expected_diagnostics: expect_test::Expect, - edits: &[(&str, expect_test::Expect, expect_test::Expect)], + edits: &[(&str, expect_test::Expect)], ) { use salsa::{Database, Setter}; @@ -135,11 +135,8 @@ fn check_string( expected_diagnostics.assert_eq(&rendered_diagnostics); }); - // Clear logs - db.take_logs(); - // Apply edits and check diagnostics/logs after each one - for (new_source_text, expected_diagnostics, expected_logs) in edits { + for (new_source_text, expected_diagnostics) in edits { source_program .set_text(&mut db) .to(new_source_text.to_string()); @@ -149,8 +146,6 @@ fn check_string( expected_diagnostics .assert_debug_eq(&type_check_program::accumulated::(db, program)); }); - - expected_logs.assert_debug_eq(&db.take_logs()); } } @@ -267,12 +262,6 @@ fn fix_bad_variable_in_function() { expect![[r#" [] "#]], - expect![[r#" - [ - "Event: Event { thread_id: ThreadId(11), kind: WillExecute { database_key: parse_statements(Id(0)) } }", - "Event: Event { thread_id: ThreadId(11), kind: WillExecute { database_key: type_check_function(Id(1800)) } }", - ] - "#]], )], ); } diff --git a/src/revision.rs b/src/revision.rs index 43995f173..f71fc29ca 100644 --- a/src/revision.rs +++ b/src/revision.rs @@ -126,7 +126,7 @@ mod tests { use super::*; #[test] - fn pptional_atomic_revision() { + fn optional_atomic_revision() { let val = OptionalAtomicRevision::new(Some(Revision::start())); assert_eq!(val.load(), Some(Revision::start())); assert_eq!(val.swap(None), Some(Revision::start())); diff --git a/tests/cycle.rs b/tests/cycle.rs index fe5875fc0..7f17034f6 100644 --- a/tests/cycle.rs +++ b/tests/cycle.rs @@ -6,6 +6,7 @@ mod common; use common::{ExecuteValidateLoggerDatabase, LogDatabase}; use expect_test::expect; use salsa::{CycleRecoveryAction, Database as Db, DatabaseImpl as DbImpl, Durability, Setter}; +#[cfg(not(miri))] use test_log::test; #[derive(Clone, Copy, Debug, PartialEq, Eq, salsa::Update)] @@ -31,12 +32,13 @@ impl Value { /// `max_iterate`, `min_panic`, `max_panic`) for testing cycle behaviors. #[salsa::input] struct Inputs { + #[return_ref] inputs: Vec, } impl Inputs { fn values(self, db: &dyn Db) -> impl Iterator + '_ { - self.inputs(db).into_iter().map(|input| input.eval(db)) + self.inputs(db).iter().map(|input| input.eval(db)) } } @@ -69,8 +71,8 @@ enum Input { } impl Input { - fn eval(self, db: &dyn Db) -> Value { - match self { + fn eval(&self, db: &dyn Db) -> Value { + match *self { Self::Value(value) => value, Self::UntrackedRead(value) => { db.report_untracked_read(); @@ -80,30 +82,30 @@ impl Input { Self::MaxIterate(inputs) => max_iterate(db, inputs), Self::MinPanic(inputs) => min_panic(db, inputs), Self::MaxPanic(inputs) => max_panic(db, inputs), - Self::Successor(input) => match input.eval(db) { + Self::Successor(ref input) => match input.eval(db) { Value::N(num) => Value::N(num + 1), other => other, }, - Self::SuccessorOrZero(input) => match input.eval(db) { + Self::SuccessorOrZero(ref input) => match input.eval(db) { Value::N(num) => Value::N(num + 1), _ => Value::N(0), }, } } - fn assert(self, db: &dyn Db, expected: Value) { + fn assert(&self, db: &dyn Db, expected: Value) { assert_eq!(self.eval(db), expected) } - fn assert_value(self, db: &dyn Db, expected: u8) { + fn assert_value(&self, db: &dyn Db, expected: u8) { self.assert(db, Value::N(expected)) } - fn assert_bounds(self, db: &dyn Db) { + fn assert_bounds(&self, db: &dyn Db) { self.assert(db, Value::OutOfBounds) } - fn assert_count(self, db: &dyn Db) { + fn assert_count(&self, db: &dyn Db) { self.assert(db, Value::TooManyIterations) } } @@ -734,7 +736,7 @@ fn cycle_becomes_non_cycle() { a_in.set_inputs(&mut db).to(vec![b]); b_in.set_inputs(&mut db).to(vec![a.clone()]); - a.clone().assert_value(&db, 255); + a.assert_value(&db, 255); b_in.set_inputs(&mut db).to(vec![value(30)]); @@ -758,7 +760,7 @@ fn non_cycle_becomes_cycle() { a_in.set_inputs(&mut db).to(vec![b]); b_in.set_inputs(&mut db).to(vec![value(30)]); - a.clone().assert_value(&db, 30); + a.assert_value(&db, 30); b_in.set_inputs(&mut db).to(vec![a.clone()]); @@ -790,7 +792,7 @@ fn nested_double_multiple_revisions() { Input::Successor(Box::new(b.clone())), ]); - a.clone().assert_count(&db); + a.assert_count(&db); // next revision, we hit max value instead c_in.set_inputs(&mut db).to(vec![ @@ -799,13 +801,13 @@ fn nested_double_multiple_revisions() { Input::Successor(Box::new(b.clone())), ]); - a.clone().assert_bounds(&db); + a.assert_bounds(&db); // and next revision, we converge c_in.set_inputs(&mut db) .to(vec![value(240), a.clone(), b.clone()]); - a.clone().assert_value(&db, 240); + a.assert_value(&db, 240); // one more revision, without relevant changes a_in.set_inputs(&mut db).to(vec![b]); @@ -838,7 +840,7 @@ fn cycle_durability() { .with_durability(Durability::HIGH) .to(vec![a.clone()]); - a.clone().assert_value(&db, 255); + a.assert_value(&db, 255); // next revision, we converge instead a_in.set_inputs(&mut db) @@ -866,8 +868,8 @@ fn cycle_unchanged() { b_in.set_inputs(&mut db).to(vec![value(60), c]); c_in.set_inputs(&mut db).to(vec![b.clone()]); - a.clone().assert_value(&db, 59); - b.clone().assert_value(&db, 60); + a.assert_value(&db, 59); + b.assert_value(&db, 60); db.assert_logs_len(4); @@ -912,8 +914,8 @@ fn cycle_unchanged_nested() { .to(vec![value(61), b.clone(), e.clone()]); e_in.set_inputs(&mut db).to(vec![d.clone()]); - a.clone().assert_value(&db, 59); - b.clone().assert_value(&db, 60); + a.assert_value(&db, 59); + b.assert_value(&db, 60); db.assert_logs_len(10); @@ -965,8 +967,8 @@ fn cycle_unchanged_nested_intertwined() { .to(vec![value(61), b.clone(), e.clone()]); e_in.set_inputs(&mut db).to(vec![d.clone()]); - a.clone().assert_value(&db, 59); - b.clone().assert_value(&db, 60); + a.assert_value(&db, 59); + b.assert_value(&db, 60); // First time we run this test, don't fetch c/d/e here; this means they won't get marked // `verified_final` in R6 (this revision), which will leave us in the next revision (R7) @@ -977,9 +979,9 @@ fn cycle_unchanged_nested_intertwined() { // Second time we run this test, fetch everything in R6, to check the behavior of // `maybe_changed_after` with all validated-final memos. if i == 1 { - c.clone().assert_value(&db, 60); - d.clone().assert_value(&db, 60); - e.clone().assert_value(&db, 60); + c.assert_value(&db, 60); + d.assert_value(&db, 60); + e.assert_value(&db, 60); } db.assert_logs_len(16 + i); diff --git a/tests/lru.rs b/tests/lru.rs index c60e559f3..5e306a821 100644 --- a/tests/lru.rs +++ b/tests/lru.rs @@ -36,7 +36,7 @@ struct MyInput { field: u32, } -#[salsa::tracked(lru = 32)] +#[salsa::tracked(lru = 8)] fn get_hot_potato(db: &dyn LogDatabase, input: MyInput) -> Arc { db.push_log(format!("get_hot_potato({:?})", input.field(db))); Arc::new(HotPotato::new(input.field(db))) @@ -57,16 +57,16 @@ fn lru_works() { let mut db = common::LoggerDatabase::default(); assert_eq!(load_n_potatoes(), 0); - for i in 0..128u32 { + for i in 0..32u32 { let input = MyInput::new(&db, i); let p = get_hot_potato(&db, input); assert_eq!(p.0, i); } - assert_eq!(load_n_potatoes(), 128); + assert_eq!(load_n_potatoes(), 32); // trigger the GC db.synthetic_write(salsa::Durability::HIGH); - assert_eq!(load_n_potatoes(), 32); + assert_eq!(load_n_potatoes(), 8); } #[test] @@ -74,42 +74,42 @@ fn lru_can_be_changed_at_runtime() { let mut db = common::LoggerDatabase::default(); assert_eq!(load_n_potatoes(), 0); - let inputs: Vec<(u32, MyInput)> = (0..128).map(|i| (i, MyInput::new(&db, i))).collect(); + let inputs: Vec<(u32, MyInput)> = (0..32).map(|i| (i, MyInput::new(&db, i))).collect(); for &(i, input) in inputs.iter() { let p = get_hot_potato(&db, input); assert_eq!(p.0, i); } - assert_eq!(load_n_potatoes(), 128); + assert_eq!(load_n_potatoes(), 32); // trigger the GC db.synthetic_write(salsa::Durability::HIGH); - assert_eq!(load_n_potatoes(), 32); + assert_eq!(load_n_potatoes(), 8); - get_hot_potato::set_lru_capacity(&mut db, 64); - assert_eq!(load_n_potatoes(), 32); + get_hot_potato::set_lru_capacity(&mut db, 16); + assert_eq!(load_n_potatoes(), 8); for &(i, input) in inputs.iter() { let p = get_hot_potato(&db, input); assert_eq!(p.0, i); } - assert_eq!(load_n_potatoes(), 128); + assert_eq!(load_n_potatoes(), 32); // trigger the GC db.synthetic_write(salsa::Durability::HIGH); - assert_eq!(load_n_potatoes(), 64); + assert_eq!(load_n_potatoes(), 16); // Special case: setting capacity to zero disables LRU get_hot_potato::set_lru_capacity(&mut db, 0); - assert_eq!(load_n_potatoes(), 64); + assert_eq!(load_n_potatoes(), 16); for &(i, input) in inputs.iter() { let p = get_hot_potato(&db, input); assert_eq!(p.0, i); } - assert_eq!(load_n_potatoes(), 128); + assert_eq!(load_n_potatoes(), 32); // trigger the GC db.synthetic_write(salsa::Durability::HIGH); - assert_eq!(load_n_potatoes(), 128); + assert_eq!(load_n_potatoes(), 32); drop(db); assert_eq!(load_n_potatoes(), 0); @@ -118,10 +118,10 @@ fn lru_can_be_changed_at_runtime() { #[test] fn lru_keeps_dependency_info() { let mut db = common::LoggerDatabase::default(); - let capacity = 32; + let capacity = 8; // Invoke `get_hot_potato2` 33 times. This will (in turn) invoke - // `get_hot_potato`, which will trigger LRU after 32 executions. + // `get_hot_potato`, which will trigger LRU after 8 executions. let inputs: Vec = (0..(capacity + 1)) .map(|i| MyInput::new(&db, i as u32)) .collect(); diff --git a/tests/parallel/cycle_ab_peeping_c.rs b/tests/parallel/cycle_ab_peeping_c.rs index 1c8233fab..cff533e39 100644 --- a/tests/parallel/cycle_ab_peeping_c.rs +++ b/tests/parallel/cycle_ab_peeping_c.rs @@ -15,8 +15,8 @@ use crate::setup::{Knobs, KnobsDatabase}; struct CycleValue(u32); const MIN: CycleValue = CycleValue(0); -const MID: CycleValue = CycleValue(11); -const MAX: CycleValue = CycleValue(22); +const MID: CycleValue = CycleValue(5); +const MAX: CycleValue = CycleValue(10); #[salsa::tracked(cycle_fn=cycle_fn, cycle_initial=cycle_initial)] fn query_a(db: &dyn KnobsDatabase) -> CycleValue { diff --git a/tests/tracked_struct_disambiguates.rs b/tests/tracked_struct_disambiguates.rs index 80d8e9a15..663fedf42 100644 --- a/tests/tracked_struct_disambiguates.rs +++ b/tests/tracked_struct_disambiguates.rs @@ -85,10 +85,7 @@ fn execute() { let mut db = salsa::DatabaseImpl::new(); let inputs = MyInputs::new( &db, - (0..1024) - .into_iter() - .map(|i| MyInput::new(&db, i)) - .collect(), + (0..64).into_iter().map(|i| MyInput::new(&db, i)).collect(), ); let trackeds = batch(&db, inputs); for (id, tracked) in trackeds.into_iter().enumerate() {