Control rewinding via SkyFunction.Environment

SkyFunction implementations need to know whether to return Restart or
fail (with a thrown exception). The Environment provides this
configuration, driven by the GraphInconsistencyReceiver in use during
the evaluation.

RELNOTES: None.
PiperOrigin-RevId: 308191628
diff --git a/src/test/java/com/google/devtools/build/lib/actions/ExecutableSymlinkActionTest.java b/src/test/java/com/google/devtools/build/lib/actions/ExecutableSymlinkActionTest.java
index f64993b..8c9c672 100644
--- a/src/test/java/com/google/devtools/build/lib/actions/ExecutableSymlinkActionTest.java
+++ b/src/test/java/com/google/devtools/build/lib/actions/ExecutableSymlinkActionTest.java
@@ -68,6 +68,7 @@
         ActionInputPrefetcher.NONE,
         actionKeyContext,
         /*metadataHandler=*/ null,
+        /*rewindingEnabled=*/ false,
         LostInputsCheck.NONE,
         outErr,
         /*eventHandler=*/ null,
diff --git a/src/test/java/com/google/devtools/build/lib/actions/util/ActionsTestUtil.java b/src/test/java/com/google/devtools/build/lib/actions/util/ActionsTestUtil.java
index 1f73d08..792fe3a 100644
--- a/src/test/java/com/google/devtools/build/lib/actions/util/ActionsTestUtil.java
+++ b/src/test/java/com/google/devtools/build/lib/actions/util/ActionsTestUtil.java
@@ -157,6 +157,7 @@
         ActionInputPrefetcher.NONE,
         actionKeyContext,
         metadataHandler,
+        /*rewindingEnabled=*/ false,
         LostInputsCheck.NONE,
         fileOutErr,
         eventHandler,
@@ -178,6 +179,7 @@
         ActionInputPrefetcher.NONE,
         new ActionKeyContext(),
         /*metadataHandler=*/ null,
+        /*rewindingEnabled=*/ false,
         LostInputsCheck.NONE,
         /*fileOutErr=*/ null,
         eventHandler,
@@ -204,6 +206,7 @@
         ActionInputPrefetcher.NONE,
         actionKeyContext,
         metadataHandler,
+        /*rewindingEnabled=*/ false,
         LostInputsCheck.NONE,
         fileOutErr,
         eventHandler,
@@ -321,6 +324,11 @@
     public boolean inErrorBubblingForTesting() {
       return false;
     }
+
+    @Override
+    public boolean restartPermitted() {
+      return false;
+    }
   }
 
   static class NullArtifactOwner implements ArtifactOwner {
diff --git a/src/test/java/com/google/devtools/build/lib/analysis/actions/FileWriteActionTestCase.java b/src/test/java/com/google/devtools/build/lib/analysis/actions/FileWriteActionTestCase.java
index 912d858..7ded773 100644
--- a/src/test/java/com/google/devtools/build/lib/analysis/actions/FileWriteActionTestCase.java
+++ b/src/test/java/com/google/devtools/build/lib/analysis/actions/FileWriteActionTestCase.java
@@ -70,6 +70,7 @@
             ActionInputPrefetcher.NONE,
             actionKeyContext,
             /*metadataHandler=*/ null,
+            /*rewindingEnabled=*/ false,
             LostInputsCheck.NONE,
             new FileOutErr(),
             new StoredEventHandler(),
diff --git a/src/test/java/com/google/devtools/build/lib/analysis/actions/ParamFileWriteActionTest.java b/src/test/java/com/google/devtools/build/lib/analysis/actions/ParamFileWriteActionTest.java
index 8b3fd57..bf5e221 100644
--- a/src/test/java/com/google/devtools/build/lib/analysis/actions/ParamFileWriteActionTest.java
+++ b/src/test/java/com/google/devtools/build/lib/analysis/actions/ParamFileWriteActionTest.java
@@ -209,6 +209,7 @@
         ActionInputPrefetcher.NONE,
         actionKeyContext,
         /*metadataHandler=*/ null,
+        /*rewindingEnabled=*/ false,
         LostInputsCheck.NONE,
         new FileOutErr(),
         new StoredEventHandler(),
diff --git a/src/test/java/com/google/devtools/build/lib/analysis/actions/SymlinkActionTest.java b/src/test/java/com/google/devtools/build/lib/analysis/actions/SymlinkActionTest.java
index 4c5b88a..8665a2f 100644
--- a/src/test/java/com/google/devtools/build/lib/analysis/actions/SymlinkActionTest.java
+++ b/src/test/java/com/google/devtools/build/lib/analysis/actions/SymlinkActionTest.java
@@ -91,6 +91,7 @@
                 ActionInputPrefetcher.NONE,
                 actionKeyContext,
                 /*metadataHandler=*/ null,
+                /*rewindingEnabled=*/ false,
                 LostInputsCheck.NONE,
                 /*fileOutErr=*/ null,
                 new StoredEventHandler(),
diff --git a/src/test/java/com/google/devtools/build/lib/analysis/actions/TemplateExpansionActionTest.java b/src/test/java/com/google/devtools/build/lib/analysis/actions/TemplateExpansionActionTest.java
index ba35d5d..3385026 100644
--- a/src/test/java/com/google/devtools/build/lib/analysis/actions/TemplateExpansionActionTest.java
+++ b/src/test/java/com/google/devtools/build/lib/analysis/actions/TemplateExpansionActionTest.java
@@ -196,6 +196,7 @@
         ActionInputPrefetcher.NONE,
         actionKeyContext,
         /*metadataHandler=*/ null,
+        /*rewindingEnabled=*/ false,
         LostInputsCheck.NONE,
         new FileOutErr(),
         new StoredEventHandler(),
diff --git a/src/test/java/com/google/devtools/build/lib/analysis/util/BuildViewTestCase.java b/src/test/java/com/google/devtools/build/lib/analysis/util/BuildViewTestCase.java
index 0a01821..115bf3e 100644
--- a/src/test/java/com/google/devtools/build/lib/analysis/util/BuildViewTestCase.java
+++ b/src/test/java/com/google/devtools/build/lib/analysis/util/BuildViewTestCase.java
@@ -2288,6 +2288,7 @@
           /*actionInputPrefetcher=*/ null,
           actionKeyContext,
           /*metadataHandler=*/ null,
+          /*rewindingEnabled=*/ false,
           LostInputsCheck.NONE,
           actionLogBufferPathGenerator.generate(ArtifactPathResolver.IDENTITY),
           reporter,
diff --git a/src/test/java/com/google/devtools/build/lib/exec/StandaloneTestStrategyTest.java b/src/test/java/com/google/devtools/build/lib/exec/StandaloneTestStrategyTest.java
index 2c5db86..562ba1a 100644
--- a/src/test/java/com/google/devtools/build/lib/exec/StandaloneTestStrategyTest.java
+++ b/src/test/java/com/google/devtools/build/lib/exec/StandaloneTestStrategyTest.java
@@ -127,6 +127,7 @@
           ActionInputPrefetcher.NONE,
           new ActionKeyContext(),
           /*metadataHandler=*/ null,
+          /*rewindingEnabled=*/ false,
           LostInputsCheck.NONE,
           fileOutErr,
           /*eventHandler=*/ null,
diff --git a/src/test/java/com/google/devtools/build/lib/exec/local/LocalSpawnRunnerTest.java b/src/test/java/com/google/devtools/build/lib/exec/local/LocalSpawnRunnerTest.java
index aea170a..6bde2b5 100644
--- a/src/test/java/com/google/devtools/build/lib/exec/local/LocalSpawnRunnerTest.java
+++ b/src/test/java/com/google/devtools/build/lib/exec/local/LocalSpawnRunnerTest.java
@@ -279,6 +279,11 @@
     }
 
     @Override
+    public boolean isRewindingEnabled() {
+      return false;
+    }
+
+    @Override
     public void checkForLostInputs() {}
 
     @Override
diff --git a/src/test/java/com/google/devtools/build/lib/remote/RemoteSpawnCacheTest.java b/src/test/java/com/google/devtools/build/lib/remote/RemoteSpawnCacheTest.java
index 50fe92c..c33b937 100644
--- a/src/test/java/com/google/devtools/build/lib/remote/RemoteSpawnCacheTest.java
+++ b/src/test/java/com/google/devtools/build/lib/remote/RemoteSpawnCacheTest.java
@@ -209,6 +209,11 @@
         }
 
         @Override
+        public boolean isRewindingEnabled() {
+          return false;
+        }
+
+        @Override
         public void checkForLostInputs() {}
 
         @Override
diff --git a/src/test/java/com/google/devtools/build/lib/remote/util/FakeSpawnExecutionContext.java b/src/test/java/com/google/devtools/build/lib/remote/util/FakeSpawnExecutionContext.java
index 5bab193..67f7d30 100644
--- a/src/test/java/com/google/devtools/build/lib/remote/util/FakeSpawnExecutionContext.java
+++ b/src/test/java/com/google/devtools/build/lib/remote/util/FakeSpawnExecutionContext.java
@@ -165,5 +165,10 @@
   }
 
   @Override
+  public boolean isRewindingEnabled() {
+    return false;
+  }
+
+  @Override
   public void checkForLostInputs() {}
 }
diff --git a/src/test/java/com/google/devtools/build/lib/rules/cpp/CreateIncSymlinkActionTest.java b/src/test/java/com/google/devtools/build/lib/rules/cpp/CreateIncSymlinkActionTest.java
index bcdb9c6..e1f6ebc 100644
--- a/src/test/java/com/google/devtools/build/lib/rules/cpp/CreateIncSymlinkActionTest.java
+++ b/src/test/java/com/google/devtools/build/lib/rules/cpp/CreateIncSymlinkActionTest.java
@@ -128,6 +128,7 @@
         /*actionInputPrefetcher=*/ null,
         /*actionKeyContext=*/ null,
         /*metadataHandler=*/ null,
+        /*rewindingEnabled=*/ false,
         LostInputsCheck.NONE,
         /*fileOutErr=*/ null,
         new StoredEventHandler(),
diff --git a/src/test/java/com/google/devtools/build/lib/rules/cpp/LtoBackendActionTest.java b/src/test/java/com/google/devtools/build/lib/rules/cpp/LtoBackendActionTest.java
index 71d0b39..63c6189 100644
--- a/src/test/java/com/google/devtools/build/lib/rules/cpp/LtoBackendActionTest.java
+++ b/src/test/java/com/google/devtools/build/lib/rules/cpp/LtoBackendActionTest.java
@@ -91,6 +91,7 @@
             ActionInputPrefetcher.NONE,
             actionKeyContext,
             /*metadataHandler=*/ null,
+            /*rewindingEnabled=*/ false,
             LostInputsCheck.NONE,
             new FileOutErr(),
             new StoredEventHandler(),
diff --git a/src/test/java/com/google/devtools/build/lib/rules/objc/BazelJ2ObjcLibraryTest.java b/src/test/java/com/google/devtools/build/lib/rules/objc/BazelJ2ObjcLibraryTest.java
index 2c93856..a2b4fe4 100644
--- a/src/test/java/com/google/devtools/build/lib/rules/objc/BazelJ2ObjcLibraryTest.java
+++ b/src/test/java/com/google/devtools/build/lib/rules/objc/BazelJ2ObjcLibraryTest.java
@@ -796,6 +796,7 @@
             ActionInputPrefetcher.NONE,
             actionKeyContext,
             /*metadataHandler=*/ null,
+            /*rewindingEnabled=*/ false,
             LostInputsCheck.NONE,
             /*fileOutErr=*/ null,
             /*eventHandler=*/ null,
@@ -850,6 +851,7 @@
             ActionInputPrefetcher.NONE,
             actionKeyContext,
             /*metadataHandler=*/ null,
+            /*rewindingEnabled=*/ false,
             LostInputsCheck.NONE,
             /*fileOutErr=*/ null,
             /*eventHandler=*/ null,
diff --git a/src/test/java/com/google/devtools/build/lib/standalone/StandaloneSpawnStrategyTest.java b/src/test/java/com/google/devtools/build/lib/standalone/StandaloneSpawnStrategyTest.java
index 054d413..ff66eb2 100644
--- a/src/test/java/com/google/devtools/build/lib/standalone/StandaloneSpawnStrategyTest.java
+++ b/src/test/java/com/google/devtools/build/lib/standalone/StandaloneSpawnStrategyTest.java
@@ -201,6 +201,7 @@
         ActionInputPrefetcher.NONE,
         new ActionKeyContext(),
         /*metadataHandler=*/ null,
+        /*rewindingEnabled=*/ false,
         LostInputsCheck.NONE,
         outErr,
         reporter,
diff --git a/src/test/java/com/google/devtools/build/skyframe/MemoizingEvaluatorTest.java b/src/test/java/com/google/devtools/build/skyframe/MemoizingEvaluatorTest.java
index 7681d03..bbd73d1 100644
--- a/src/test/java/com/google/devtools/build/skyframe/MemoizingEvaluatorTest.java
+++ b/src/test/java/com/google/devtools/build/skyframe/MemoizingEvaluatorTest.java
@@ -59,6 +59,7 @@
 import com.google.devtools.build.skyframe.proto.GraphInconsistency.Inconsistency;
 import java.lang.ref.WeakReference;
 import java.util.ArrayList;
+import java.util.Collection;
 import java.util.Collections;
 import java.util.List;
 import java.util.Map;
@@ -177,30 +178,31 @@
   protected Set<InconsistencyData> setupGraphInconsistencyReceiver(boolean allowDuplicates) {
     Set<InconsistencyData> inconsistencies = Sets.newConcurrentHashSet();
     tester.setGraphInconsistencyReceiver(
-        (key, otherKeys, inconsistency) -> {
-          if (otherKeys == null) {
-            Preconditions.checkState(
-                inconsistencies.add(
-                        InconsistencyData.create(key, /*otherKey=*/ null, inconsistency))
-                    || allowDuplicates,
-                "Duplicate inconsistency: (%s, %s, %s)\nexisting = %s",
-                key,
-                null,
-                inconsistency,
-                inconsistencies);
-          } else {
-            for (SkyKey otherKey : otherKeys) {
-              Preconditions.checkState(
-                  inconsistencies.add(InconsistencyData.create(key, otherKey, inconsistency))
-                      || allowDuplicates,
-                  "Duplicate inconsistency: (%s, %s, %s)\nexisting = %s",
-                  key,
-                  otherKey,
-                  inconsistency,
-                  inconsistencies);
-            }
-          }
-        });
+        restartEnabledInconsistencyReceiver(
+            (key, otherKeys, inconsistency) -> {
+              if (otherKeys == null) {
+                Preconditions.checkState(
+                    inconsistencies.add(
+                            InconsistencyData.create(key, /*otherKey=*/ null, inconsistency))
+                        || allowDuplicates,
+                    "Duplicate inconsistency: (%s, %s, %s)\nexisting = %s",
+                    key,
+                    null,
+                    inconsistency,
+                    inconsistencies);
+              } else {
+                for (SkyKey otherKey : otherKeys) {
+                  Preconditions.checkState(
+                      inconsistencies.add(InconsistencyData.create(key, otherKey, inconsistency))
+                          || allowDuplicates,
+                      "Duplicate inconsistency: (%s, %s, %s)\nexisting = %s",
+                      key,
+                      otherKey,
+                      inconsistency,
+                      inconsistencies);
+                }
+              }
+            }));
     // #initialize must be called after setting the GraphInconsistencyReceiver for the receiver to
     // be registered with the test's memoizing evaluator.
     tester.initialize(/*keepEdges=*/ true);
@@ -2413,12 +2415,14 @@
     StringValue expectedValue = new StringValue("done");
     AtomicInteger numInconsistencyCalls = new AtomicInteger(0);
     tester.setGraphInconsistencyReceiver(
-        (key, otherKey, inconsistency) -> {
-          Preconditions.checkState(otherKey == null, otherKey);
-          Preconditions.checkState(inconsistency == Inconsistency.RESET_REQUESTED, inconsistency);
-          Preconditions.checkState(restartingKey.equals(key), key);
-          numInconsistencyCalls.incrementAndGet();
-        });
+        restartEnabledInconsistencyReceiver(
+            (key, otherKey, inconsistency) -> {
+              Preconditions.checkState(otherKey == null, otherKey);
+              Preconditions.checkState(
+                  inconsistency == Inconsistency.RESET_REQUESTED, inconsistency);
+              Preconditions.checkState(restartingKey.equals(key), key);
+              numInconsistencyCalls.incrementAndGet();
+            }));
     tester.initialize(/*keepEdges=*/ true);
     AtomicInteger numFunctionCalls = new AtomicInteger(0);
     tester
@@ -2471,12 +2475,14 @@
     SkyKey restartingKey = GraphTester.skyKey("restart");
     AtomicInteger numInconsistencyCalls = new AtomicInteger(0);
     tester.setGraphInconsistencyReceiver(
-        (key, otherKey, inconsistency) -> {
-          Preconditions.checkState(otherKey == null, otherKey);
-          Preconditions.checkState(inconsistency == Inconsistency.RESET_REQUESTED, inconsistency);
-          Preconditions.checkState(restartingKey.equals(key), key);
-          numInconsistencyCalls.incrementAndGet();
-        });
+        restartEnabledInconsistencyReceiver(
+            (key, otherKey, inconsistency) -> {
+              Preconditions.checkState(otherKey == null, otherKey);
+              Preconditions.checkState(
+                  inconsistency == Inconsistency.RESET_REQUESTED, inconsistency);
+              Preconditions.checkState(restartingKey.equals(key), key);
+              numInconsistencyCalls.incrementAndGet();
+            }));
     tester.initialize(mode != RunResetNodeOnRequestWithDepsMode.NO_KEEP_EDGES_SO_NO_REEVALUATION);
     StringValue expectedValue = new StringValue("done");
     SkyKey alreadyRequestedDep = GraphTester.skyKey("alreadyRequested");
@@ -2573,18 +2579,19 @@
     SkyKey missingChild = GraphTester.skyKey("missing");
     AtomicInteger numInconsistencyCalls = new AtomicInteger(0);
     tester.setGraphInconsistencyReceiver(
-        (key, otherKeys, inconsistency) -> {
-          Preconditions.checkState(otherKeys.size() == 1, otherKeys);
-          Preconditions.checkState(
-              missingChild.equals(Iterables.getOnlyElement(otherKeys)),
-              "%s %s",
-              missingChild,
-              otherKeys);
-          Preconditions.checkState(
-              inconsistency == Inconsistency.DIRTY_PARENT_HAD_MISSING_CHILD, inconsistency);
-          Preconditions.checkState(topKey.equals(key), key);
-          numInconsistencyCalls.incrementAndGet();
-        });
+        restartEnabledInconsistencyReceiver(
+            (key, otherKeys, inconsistency) -> {
+              Preconditions.checkState(otherKeys.size() == 1, otherKeys);
+              Preconditions.checkState(
+                  missingChild.equals(Iterables.getOnlyElement(otherKeys)),
+                  "%s %s",
+                  missingChild,
+                  otherKeys);
+              Preconditions.checkState(
+                  inconsistency == Inconsistency.DIRTY_PARENT_HAD_MISSING_CHILD, inconsistency);
+              Preconditions.checkState(topKey.equals(key), key);
+              numInconsistencyCalls.incrementAndGet();
+            }));
     tester.initialize(/*keepEdges=*/ true);
     tester.getOrCreate(missingChild).setConstantValue(new StringValue("will go missing"));
     SkyKey presentChild = GraphTester.nonHermeticKey("present");
@@ -5430,4 +5437,20 @@
       return null;
     }
   }
+
+  private static GraphInconsistencyReceiver restartEnabledInconsistencyReceiver(
+      GraphInconsistencyReceiver delegate) {
+    return new GraphInconsistencyReceiver() {
+      @Override
+      public void noteInconsistencyAndMaybeThrow(
+          SkyKey key, @Nullable Collection<SkyKey> otherKeys, Inconsistency inconsistency) {
+        delegate.noteInconsistencyAndMaybeThrow(key, otherKeys, inconsistency);
+      }
+
+      @Override
+      public boolean restartPermitted() {
+        return true;
+      }
+    };
+  }
 }