@@ -13,7 +13,7 @@ use crate::cycle::{
1313use crate :: database:: RawDatabase ;
1414use crate :: function:: delete:: DeletedEntries ;
1515use crate :: function:: sync:: { ClaimResult , SyncTable } ;
16- use crate :: hash:: FxIndexSet ;
16+ use crate :: hash:: { FxHashSet , FxIndexSet } ;
1717use crate :: ingredient:: { Ingredient , WaitForResult } ;
1818use crate :: key:: DatabaseKeyIndex ;
1919use 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" ) ]
495513mod 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 = FxIndexSet :: 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
0 commit comments