Closed
Description
#[test]
fn repro() {
#[derive(Debug, PartialEq, Eq, PartialOrd, Ord, Clone)]
struct BadHash(String);
impl std::hash::Hash for BadHash {
fn hash<H: std::hash::Hasher>(&self, state: &mut H) {
0.hash(state);
}
}
#[salsa::input]
struct Input {
field: String
}
#[salsa::interned]
struct Interned {
field: String
}
#[salsa::tracked]
struct Output<'db> {
pub id: String,
#[tracked]
field: Interned<'db>
}
#[salsa::tracked]
fn outer_query<'db>(db: &'db dyn Database, input: Input) -> Vec<Output<'db>> {
let res: Vec<Output<'_>> = inner_query(db, input)
.into_iter()
.map(|i| Output::new(db, input.field(db), i))
.collect();
sleep(Duration::from_millis(500));
db.unwind_if_revision_cancelled();
for r in &res {
r.id(db);
r.field(db);
}
res
}
#[salsa::tracked]
fn inner_query<'db>(db: &'db dyn Database, input: Input) -> Vec<Interned<'db>> {
let res: Vec<Interned<'db>> = (0..10).map(|i| {
Interned::new(db, format!("{}_{i}", input.field(db)))
}).collect();
res
}
tracing_subscriber::fmt()
.with_max_level(Level::ERROR)
.with_ansi(false)
.with_writer(std::io::stderr)
.init();
let mut threads = vec![];
let mut db = salsa::DatabaseImpl::default();
let i1 = Input::new(&db, "i1".to_owned());
let i2 = Input::new(&db, "i2".to_owned());
let i3 = Input::new(&db, "i3".to_owned());
let d = db.clone();
threads.push(spawn(move || {
outer_query(&d, i1);
}));
let d = db.clone();
threads.push(spawn(move || {
outer_query(&d, i2);
}));
sleep(Duration::from_millis(1000));
db.synthetic_write(Durability::HIGH);
let d = db.clone();
threads.push(spawn(move || {
outer_query(&d, i2);
}));
sleep(Duration::from_millis(250));
db.synthetic_write(Durability::HIGH);
let d = db.clone();
threads.push(spawn(move || {
outer_query(&d, i2);
}));
sleep(Duration::from_millis(250));
db.synthetic_write(Durability::HIGH);
let d = db.clone();
threads.push(spawn(move || {
outer_query(&d, i3);
}));
sleep(Duration::from_millis(250));
db.synthetic_write(Durability::HIGH);
let d = db.clone();
threads.push(spawn(move || {
outer_query(&d, i1);
}));
sleep(Duration::from_millis(0));
db.synthetic_write(Durability::HIGH);
for t in threads {
t.join();
}
for t in outer_query(&db, i1) {
t.field(&db).field(&db);
}
}
Repro is a little bit messy, ill try to reduce it more
Bug introduced in 15c28cd