@@ -19,9 +19,6 @@ pub enum VerifyResult {
19
19
///
20
20
/// The inner value tracks whether the memo or any of its dependencies have an
21
21
/// accumulated value.
22
- ///
23
- /// Don't mark memos verified until we've iterated the full cycle to ensure no inputs changed
24
- /// when encountering this variant.
25
22
Unchanged ( InputAccumulatedValues ) ,
26
23
}
27
24
@@ -37,10 +34,6 @@ impl VerifyResult {
37
34
pub ( crate ) fn unchanged ( ) -> Self {
38
35
Self :: Unchanged ( InputAccumulatedValues :: Empty )
39
36
}
40
-
41
- pub ( crate ) const fn is_unchanged ( & self ) -> bool {
42
- matches ! ( self , Self :: Unchanged ( _) )
43
- }
44
37
}
45
38
46
39
impl < C > IngredientImpl < C >
@@ -146,11 +139,11 @@ where
146
139
// Check if the inputs are still valid. We can just compare `changed_at`.
147
140
let deep_verify =
148
141
self . deep_verify_memo ( db, zalsa, old_memo, database_key_index, cycle_heads) ;
149
- if deep_verify . is_unchanged ( ) {
142
+ if let VerifyResult :: Unchanged ( accumulated_inputs ) = deep_verify {
150
143
return Some ( if old_memo. revisions . changed_at > revision {
151
144
VerifyResult :: Changed
152
145
} else {
153
- VerifyResult :: Unchanged ( old_memo . revisions . accumulated_inputs . load ( ) )
146
+ VerifyResult :: Unchanged ( accumulated_inputs)
154
147
} ) ;
155
148
}
156
149
@@ -316,18 +309,18 @@ where
316
309
memo = memo. tracing_debug( )
317
310
) ;
318
311
319
- if memo. revisions . cycle_heads . is_empty ( ) {
312
+ let cycle_heads = & memo. revisions . cycle_heads ;
313
+ if cycle_heads. is_empty ( ) {
320
314
return true ;
321
315
}
322
316
323
- let cycle_heads = & memo. revisions . cycle_heads ;
324
-
325
317
zalsa_local. with_query_stack ( |stack| {
326
318
cycle_heads. iter ( ) . all ( |cycle_head| {
327
- stack. iter ( ) . rev ( ) . any ( |query| {
328
- query. database_key_index == cycle_head. database_key_index
329
- && query. iteration_count ( ) == cycle_head. iteration_count
330
- } )
319
+ stack
320
+ . iter ( )
321
+ . rev ( )
322
+ . find ( |query| query. database_key_index == cycle_head. database_key_index )
323
+ . is_some_and ( |query| query. iteration_count ( ) == cycle_head. iteration_count )
331
324
} )
332
325
} )
333
326
}
@@ -385,10 +378,7 @@ where
385
378
// when we hit the cycle. Any dependencies accessed when creating the fixpoint initial
386
379
// are tracked by the outer query. Nothing should have changed assuming that the
387
380
// fixpoint initial function is deterministic.
388
- QueryOrigin :: FixpointInitial => {
389
- cycle_heads. push_initial ( database_key_index) ;
390
- VerifyResult :: unchanged ( )
391
- }
381
+ QueryOrigin :: FixpointInitial => VerifyResult :: unchanged ( ) ,
392
382
QueryOrigin :: DerivedUntracked ( _) => {
393
383
// Untracked inputs? Have to assume that it changed.
394
384
VerifyResult :: Changed
@@ -402,16 +392,18 @@ where
402
392
return VerifyResult :: Changed ;
403
393
}
404
394
395
+ let dyn_db = db. as_dyn_database ( ) ;
396
+
397
+ let mut last_verified_at = old_memo. verified_at . load ( ) ;
398
+ let mut first_iteration = true ;
405
399
' cycle: loop {
400
+ let mut inputs = InputAccumulatedValues :: Empty ;
406
401
// Fully tracked inputs? Iterate over the inputs and check them, one by one.
407
402
//
408
403
// NB: It's important here that we are iterating the inputs in the order that
409
404
// they executed. It's possible that if the value of some input I0 is no longer
410
405
// valid, then some later input I1 might never have executed at all, so verifying
411
406
// it is still up to date is meaningless.
412
- let last_verified_at = old_memo. verified_at . load ( ) ;
413
- let mut inputs = InputAccumulatedValues :: Empty ;
414
- let dyn_db = db. as_dyn_database ( ) ;
415
407
for & edge in edges. input_outputs . iter ( ) {
416
408
match edge {
417
409
QueryEdge :: Input ( dependency_index) => {
@@ -421,9 +413,7 @@ where
421
413
last_verified_at,
422
414
cycle_heads,
423
415
) {
424
- VerifyResult :: Changed => {
425
- break ' cycle VerifyResult :: Changed ;
426
- }
416
+ VerifyResult :: Changed => break ' cycle VerifyResult :: Changed ,
427
417
VerifyResult :: Unchanged ( input_accumulated) => {
428
418
inputs |= input_accumulated;
429
419
}
@@ -477,9 +467,17 @@ where
477
467
// from cycle heads. We will handle our own memo (and the rest of our cycle) on a
478
468
// future iteration; first the outer cycle head needs to verify itself.
479
469
480
- let in_heads = cycle_heads. remove ( & database_key_index) ;
470
+ let was_in_heads = cycle_heads. remove ( & database_key_index) ;
471
+ let heads_non_empty = !cycle_heads. is_empty ( ) ;
472
+ if heads_non_empty {
473
+ // case 2 / 4
474
+ break ' cycle VerifyResult :: Unchanged ( inputs) ;
475
+ } else if !first_iteration {
476
+ // 3 (second loop turn)
477
+ break ' cycle VerifyResult :: Unchanged ( inputs) ;
478
+ } else {
479
+ last_verified_at = zalsa. current_revision ( ) ;
481
480
482
- if cycle_heads. is_empty ( ) {
483
481
old_memo. mark_as_verified ( zalsa, database_key_index) ;
484
482
old_memo. revisions . accumulated_inputs . store ( inputs) ;
485
483
@@ -490,11 +488,15 @@ where
490
488
. store ( true , Ordering :: Relaxed ) ;
491
489
}
492
490
493
- if in_heads {
491
+ if was_in_heads {
492
+ first_iteration = false ;
493
+ // case 3
494
494
continue ' cycle;
495
+ } else {
496
+ // case 1
497
+ break ' cycle VerifyResult :: Unchanged ( inputs) ;
495
498
}
496
499
}
497
- break ' cycle VerifyResult :: Unchanged ( inputs) ;
498
500
}
499
501
}
500
502
}
0 commit comments