Skip to content

Commit 3eba0fd

Browse files
committed
avoid cycles during serialization
1 parent 34882a1 commit 3eba0fd

File tree

8 files changed

+44
-12
lines changed

8 files changed

+44
-12
lines changed

src/accumulator.rs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ use std::panic::UnwindSafe;
88
use accumulated::{Accumulated, AnyAccumulated};
99

1010
use crate::function::{VerifyCycleHeads, VerifyResult};
11-
use crate::hash::FxIndexSet;
11+
use crate::hash::{FxHashSet, FxIndexSet};
1212
use crate::ingredient::{Ingredient, Jar};
1313
use crate::plumbing::ZalsaLocal;
1414
use crate::sync::Arc;
@@ -117,6 +117,7 @@ impl<A: Accumulator> Ingredient for IngredientImpl<A> {
117117
_zalsa: &Zalsa,
118118
_edge: QueryEdge,
119119
_serialized_edges: &mut FxIndexSet<QueryEdge>,
120+
_visited_edges: &mut FxHashSet<QueryEdge>,
120121
) {
121122
panic!("nothing should ever depend on an accumulator directly")
122123
}

src/function.rs

Lines changed: 28 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ use crate::cycle::{
1313
use crate::database::RawDatabase;
1414
use crate::function::delete::DeletedEntries;
1515
use crate::function::sync::{ClaimResult, SyncTable};
16-
use crate::hash::FxIndexSet;
16+
use crate::hash::{FxHashSet, FxIndexSet};
1717
use crate::ingredient::{Ingredient, WaitForResult};
1818
use crate::key::DatabaseKeyIndex;
1919
use crate::plumbing::{self, MemoIngredientMap};
@@ -294,6 +294,7 @@ where
294294
zalsa: &Zalsa,
295295
edge: QueryEdge,
296296
serialized_edges: &mut FxIndexSet<QueryEdge>,
297+
visited_edges: &mut FxHashSet<QueryEdge>,
297298
) {
298299
let input = edge.key().key_index();
299300

@@ -305,10 +306,27 @@ where
305306

306307
let origin = memo.revisions.origin.as_ref();
307308

309+
visited_edges.insert(edge);
310+
308311
// Collect the minimum dependency tree.
309312
for edge in origin.edges() {
313+
// Avoid forming cycles.
314+
if visited_edges.contains(edge) {
315+
continue;
316+
}
317+
318+
// Avoid flattening edges that we're going to serialize directly.
319+
if serialized_edges.contains(edge) {
320+
continue;
321+
}
322+
310323
let dependency = zalsa.lookup_ingredient(edge.key().ingredient_index());
311-
dependency.collect_minimum_serialized_edges(zalsa, *edge, serialized_edges)
324+
dependency.collect_minimum_serialized_edges(
325+
zalsa,
326+
*edge,
327+
serialized_edges,
328+
visited_edges,
329+
)
312330
}
313331
}
314332

@@ -494,7 +512,7 @@ where
494512
#[cfg(feature = "persistence")]
495513
mod persistence {
496514
use super::{Configuration, IngredientImpl, Memo};
497-
use crate::hash::FxIndexSet;
515+
use crate::hash::{FxHashSet, FxIndexSet};
498516
use crate::plumbing::{MemoIngredientMap, SalsaStructInDb};
499517
use crate::zalsa::Zalsa;
500518
use crate::zalsa_local::{QueryEdge, QueryOrigin, QueryOriginRef};
@@ -579,6 +597,7 @@ mod persistence {
579597

580598
// Flatten the dependency edges before serialization.
581599
fn flatten_edges(zalsa: &Zalsa, edges: &[QueryEdge]) -> FxIndexSet<QueryEdge> {
600+
let mut visited_edges = FxHashSet::default();
582601
let mut flattened_edges =
583602
FxIndexSet::with_capacity_and_hasher(edges.len(), Default::default());
584603

@@ -590,7 +609,12 @@ mod persistence {
590609
flattened_edges.insert(edge);
591610
} else {
592611
// Otherwise, serialize the minimum edges necessary to cover the dependency.
593-
dependency.collect_minimum_serialized_edges(zalsa, edge, &mut flattened_edges);
612+
dependency.collect_minimum_serialized_edges(
613+
zalsa,
614+
edge,
615+
&mut flattened_edges,
616+
&mut visited_edges,
617+
);
594618
}
595619
}
596620

src/ingredient.rs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ use crate::cycle::{
66
};
77
use crate::database::RawDatabase;
88
use crate::function::{VerifyCycleHeads, VerifyResult};
9-
use crate::hash::FxIndexSet;
9+
use crate::hash::{FxHashSet, FxIndexSet};
1010
use crate::runtime::Running;
1111
use crate::sync::Arc;
1212
use crate::table::memo::MemoTableTypes;
@@ -68,6 +68,7 @@ pub trait Ingredient: Any + std::fmt::Debug + Send + Sync {
6868
zalsa: &Zalsa,
6969
edge: QueryEdge,
7070
serialized_edges: &mut FxIndexSet<QueryEdge>,
71+
visited_edges: &mut FxHashSet<QueryEdge>,
7172
);
7273

7374
/// Returns information about the current provisional status of `input`.

src/input.rs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ pub mod singleton;
99
use input_field::FieldIngredientImpl;
1010

1111
use crate::function::{VerifyCycleHeads, VerifyResult};
12-
use crate::hash::FxIndexSet;
12+
use crate::hash::{FxHashSet, FxIndexSet};
1313
use crate::id::{AsId, FromId, FromIdWithDb};
1414
use crate::ingredient::Ingredient;
1515
use crate::input::singleton::{Singleton, SingletonChoice};
@@ -284,6 +284,7 @@ impl<C: Configuration> Ingredient for IngredientImpl<C> {
284284
_zalsa: &Zalsa,
285285
_edge: QueryEdge,
286286
_serialized_edges: &mut FxIndexSet<QueryEdge>,
287+
_visited_edges: &mut FxHashSet<QueryEdge>,
287288
) {
288289
panic!("nothing should ever depend on an input struct directly")
289290
}

src/input/input_field.rs

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ use std::fmt;
22
use std::marker::PhantomData;
33

44
use crate::function::{VerifyCycleHeads, VerifyResult};
5-
use crate::hash::FxIndexSet;
5+
use crate::hash::{FxHashSet, FxIndexSet};
66
use crate::ingredient::Ingredient;
77
use crate::input::{Configuration, IngredientImpl, Value};
88
use crate::sync::Arc;
@@ -68,10 +68,12 @@ where
6868
_zalsa: &Zalsa,
6969
edge: QueryEdge,
7070
serialized_edges: &mut FxIndexSet<QueryEdge>,
71+
_visited_edges: &mut FxHashSet<QueryEdge>,
7172
) {
7273
assert!(
7374
C::PERSIST,
74-
"the inputs of a persistable tracked function must be persistable"
75+
"the inputs of a persistable tracked function must be persistable: `{}` is not persistable",
76+
C::DEBUG_NAME
7577
);
7678

7779
// Input dependencies are the leaves of the minimum dependency tree.

src/interned.rs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ use rustc_hash::FxBuildHasher;
1212

1313
use crate::durability::Durability;
1414
use crate::function::{VerifyCycleHeads, VerifyResult};
15-
use crate::hash::FxIndexSet;
15+
use crate::hash::{FxHashSet, FxIndexSet};
1616
use crate::id::{AsId, FromId};
1717
use crate::ingredient::Ingredient;
1818
use crate::plumbing::{self, Jar, ZalsaLocal};
@@ -903,6 +903,7 @@ where
903903
_zalsa: &Zalsa,
904904
edge: QueryEdge,
905905
serialized_edges: &mut FxIndexSet<QueryEdge>,
906+
_visited_edges: &mut FxHashSet<QueryEdge>,
906907
) {
907908
if C::PERSIST {
908909
// If the interned struct is being persisted, it may be reachable through transitive queries.

src/tracked_struct.rs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ use thin_vec::ThinVec;
1212
use tracked_field::FieldIngredientImpl;
1313

1414
use crate::function::{VerifyCycleHeads, VerifyResult};
15-
use crate::hash::FxIndexSet;
15+
use crate::hash::{FxHashSet, FxIndexSet};
1616
use crate::id::{AsId, FromId};
1717
use crate::ingredient::{Ingredient, Jar};
1818
use crate::key::DatabaseKeyIndex;
@@ -949,6 +949,7 @@ where
949949
_zalsa: &Zalsa,
950950
_edge: QueryEdge,
951951
_serialized_edges: &mut FxIndexSet<QueryEdge>,
952+
_visited_edges: &mut FxHashSet<QueryEdge>,
952953
) {
953954
// Note that tracked structs are referenced by the identity map, but that
954955
// only matters if we are serializing the creating query, in which case

src/tracked_struct/tracked_field.rs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
use std::marker::PhantomData;
22

33
use crate::function::{VerifyCycleHeads, VerifyResult};
4-
use crate::hash::FxIndexSet;
4+
use crate::hash::{FxHashSet, FxIndexSet};
55
use crate::ingredient::Ingredient;
66
use crate::sync::Arc;
77
use crate::table::memo::MemoTableTypes;
@@ -74,6 +74,7 @@ where
7474
_zalsa: &Zalsa,
7575
_edge: QueryEdge,
7676
_serialized_edges: &mut FxIndexSet<QueryEdge>,
77+
_visited_edges: &mut FxHashSet<QueryEdge>,
7778
) {
7879
// Tracked fields do not have transitive dependencies, and their dependencies are covered by
7980
// the base inputs.

0 commit comments

Comments
 (0)