@@ -802,7 +802,13 @@ fn nested_double_multiple_revisions() {
802
802
a. clone ( ) . assert_bounds ( & db) ;
803
803
804
804
// and next revision, we converge
805
- c_in. set_inputs ( & mut db) . to ( vec ! [ value( 240 ) , a. clone( ) , b] ) ;
805
+ c_in. set_inputs ( & mut db)
806
+ . to ( vec ! [ value( 240 ) , a. clone( ) , b. clone( ) ] ) ;
807
+
808
+ a. clone ( ) . assert_value ( & db, 240 ) ;
809
+
810
+ // one more revision, without relevant changes
811
+ a_in. set_inputs ( & mut db) . to ( vec ! [ b] ) ;
806
812
807
813
a. assert_value ( & db, 240 ) ;
808
814
}
@@ -879,3 +885,120 @@ fn cycle_unchanged() {
879
885
880
886
a. assert_value ( & db, 45 ) ;
881
887
}
888
+
889
+ /// a:Np(v59, b) -> b:Ni(v60, c) -> c:Np(d) -> d:Ni(v61, b, e) -> e:Np(d)
890
+ /// ^ | ^ |
891
+ /// +--------------------------+ +--------------+
892
+ ///
893
+ /// If nothing in a nested cycle changed in the new revision, no part of the cycle should
894
+ /// re-execute.
895
+ #[ test]
896
+ fn cycle_unchanged_nested ( ) {
897
+ let mut db = ExecuteValidateLoggerDatabase :: default ( ) ;
898
+ let a_in = Inputs :: new ( & db, vec ! [ ] ) ;
899
+ let b_in = Inputs :: new ( & db, vec ! [ ] ) ;
900
+ let c_in = Inputs :: new ( & db, vec ! [ ] ) ;
901
+ let d_in = Inputs :: new ( & db, vec ! [ ] ) ;
902
+ let e_in = Inputs :: new ( & db, vec ! [ ] ) ;
903
+ let a = Input :: MinPanic ( a_in) ;
904
+ let b = Input :: MinIterate ( b_in) ;
905
+ let c = Input :: MinPanic ( c_in) ;
906
+ let d = Input :: MinIterate ( d_in) ;
907
+ let e = Input :: MinPanic ( e_in) ;
908
+ a_in. set_inputs ( & mut db) . to ( vec ! [ value( 59 ) , b. clone( ) ] ) ;
909
+ b_in. set_inputs ( & mut db) . to ( vec ! [ value( 60 ) , c. clone( ) ] ) ;
910
+ c_in. set_inputs ( & mut db) . to ( vec ! [ d. clone( ) ] ) ;
911
+ d_in. set_inputs ( & mut db)
912
+ . to ( vec ! [ value( 61 ) , b. clone( ) , e. clone( ) ] ) ;
913
+ e_in. set_inputs ( & mut db) . to ( vec ! [ d. clone( ) ] ) ;
914
+
915
+ a. clone ( ) . assert_value ( & db, 59 ) ;
916
+ b. clone ( ) . assert_value ( & db, 60 ) ;
917
+
918
+ db. assert_logs_len ( 15 ) ;
919
+
920
+ // next revision, we change only A, which is not part of the cycle and the cycle does not
921
+ // depend on.
922
+ a_in. set_inputs ( & mut db) . to ( vec ! [ value( 45 ) , b. clone( ) ] ) ;
923
+ b. assert_value ( & db, 60 ) ;
924
+
925
+ db. assert_logs ( expect ! [ [ r#"
926
+ [
927
+ "salsa_event(DidValidateMemoizedValue { database_key: min_iterate(Id(1)) })",
928
+ "salsa_event(DidValidateMemoizedValue { database_key: min_iterate(Id(3)) })",
929
+ "salsa_event(DidValidateMemoizedValue { database_key: min_panic(Id(4)) })",
930
+ "salsa_event(DidValidateMemoizedValue { database_key: min_iterate(Id(3)) })",
931
+ "salsa_event(DidValidateMemoizedValue { database_key: min_panic(Id(2)) })",
932
+ "salsa_event(DidValidateMemoizedValue { database_key: min_iterate(Id(1)) })",
933
+ ]"# ] ] ) ;
934
+
935
+ a. assert_value ( & db, 45 ) ;
936
+ }
937
+
938
+ /// +--------------------------------+
939
+ /// | v
940
+ /// a:Np(v59, b) -> b:Ni(v60, c) -> c:Np(d, e) -> d:Ni(v61, b, e) -> e:Ni(d)
941
+ /// ^ | ^ |
942
+ /// +-----------------------------+ +--------------+
943
+ ///
944
+ /// If nothing in a nested cycle changed in the new revision, no part of the cycle should
945
+ /// re-execute.
946
+ #[ test_log:: test]
947
+ fn cycle_unchanged_nested_intertwined ( ) {
948
+ // We run this test twice in order to catch some subtly different cases; see below.
949
+ for i in 0 ..1 {
950
+ let mut db = ExecuteValidateLoggerDatabase :: default ( ) ;
951
+ let a_in = Inputs :: new ( & db, vec ! [ ] ) ;
952
+ let b_in = Inputs :: new ( & db, vec ! [ ] ) ;
953
+ let c_in = Inputs :: new ( & db, vec ! [ ] ) ;
954
+ let d_in = Inputs :: new ( & db, vec ! [ ] ) ;
955
+ let e_in = Inputs :: new ( & db, vec ! [ ] ) ;
956
+ let a = Input :: MinPanic ( a_in) ;
957
+ let b = Input :: MinIterate ( b_in) ;
958
+ let c = Input :: MinPanic ( c_in) ;
959
+ let d = Input :: MinIterate ( d_in) ;
960
+ let e = Input :: MinIterate ( e_in) ;
961
+ a_in. set_inputs ( & mut db) . to ( vec ! [ value( 59 ) , b. clone( ) ] ) ;
962
+ b_in. set_inputs ( & mut db) . to ( vec ! [ value( 60 ) , c. clone( ) ] ) ;
963
+ c_in. set_inputs ( & mut db) . to ( vec ! [ d. clone( ) , e. clone( ) ] ) ;
964
+ d_in. set_inputs ( & mut db)
965
+ . to ( vec ! [ value( 61 ) , b. clone( ) , e. clone( ) ] ) ;
966
+ e_in. set_inputs ( & mut db) . to ( vec ! [ d. clone( ) ] ) ;
967
+
968
+ a. clone ( ) . assert_value ( & db, 59 ) ;
969
+ b. clone ( ) . assert_value ( & db, 60 ) ;
970
+
971
+ // First time we run this test, don't fetch c/d/e here; this means they won't get marked
972
+ // `verified_final` in R6 (this revision), which will leave us in the next revision (R7)
973
+ // with a chain of could-be-provisional memos from the previous revision which should be
974
+ // final but were never confirmed as such; this triggers the case in `deep_verify_memo`
975
+ // where we need to double-check `validate_provisional` after traversing dependencies.
976
+ //
977
+ // Second time we run this test, fetch everything in R6, to check the behavior of
978
+ // `maybe_changed_after` with all validated-final memos.
979
+ if i == 1 {
980
+ c. clone ( ) . assert_value ( & db, 60 ) ;
981
+ d. clone ( ) . assert_value ( & db, 60 ) ;
982
+ e. clone ( ) . assert_value ( & db, 60 ) ;
983
+ }
984
+
985
+ db. assert_logs_len ( 27 + i) ;
986
+
987
+ // next revision, we change only A, which is not part of the cycle and the cycle does not
988
+ // depend on.
989
+ a_in. set_inputs ( & mut db) . to ( vec ! [ value( 45 ) , b. clone( ) ] ) ;
990
+ b. assert_value ( & db, 60 ) ;
991
+
992
+ db. assert_logs ( expect ! [ [ r#"
993
+ [
994
+ "salsa_event(DidValidateMemoizedValue { database_key: min_iterate(Id(1)) })",
995
+ "salsa_event(DidValidateMemoizedValue { database_key: min_iterate(Id(3)) })",
996
+ "salsa_event(DidValidateMemoizedValue { database_key: min_iterate(Id(4)) })",
997
+ "salsa_event(DidValidateMemoizedValue { database_key: min_iterate(Id(3)) })",
998
+ "salsa_event(DidValidateMemoizedValue { database_key: min_panic(Id(2)) })",
999
+ "salsa_event(DidValidateMemoizedValue { database_key: min_iterate(Id(1)) })",
1000
+ ]"# ] ] ) ;
1001
+
1002
+ a. assert_value ( & db, 45 ) ;
1003
+ }
1004
+ }
0 commit comments